Showing preview only (2,305K chars total). Download the full file or copy to clipboard to get everything.
Repository: bluzelle/swarmDB
Branch: devel
Commit: 3315336eec8b
Files: 221
Total size: 2.2 MB
Directory structure:
gitextract_w88obzzf/
├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── CONTRIBUTOR.md
├── LICENSE
├── README.md
├── SUMMARY.md
├── audit/
│ ├── CMakeLists.txt
│ ├── audit.cpp
│ ├── audit.hpp
│ ├── audit_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── audit_test.cpp
├── chaos/
│ ├── CMakeLists.txt
│ ├── chaos.cpp
│ ├── chaos.hpp
│ ├── chaos_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── chaos_test.cpp
├── cmake/
│ ├── add_gmock_test.cmake
│ ├── boost.cmake
│ ├── git_commit.cmake
│ ├── googletest.cmake
│ ├── jsoncpp.cmake
│ ├── openssl.cmake
│ ├── rocksdb.cmake
│ ├── static_analysis.cmake
│ ├── static_analysis.sh
│ ├── swarm_git_commit.hpp.in
│ ├── swarm_version.cmake
│ └── swarm_version.hpp.in
├── crud/
│ ├── CMakeLists.txt
│ ├── crud.cpp
│ ├── crud.hpp
│ ├── crud_base.hpp
│ ├── subscription_manager.cpp
│ ├── subscription_manager.hpp
│ ├── subscription_manager_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ ├── crud_test.cpp
│ └── subscription_manager_test.cpp
├── crypto/
│ ├── CMakeLists.txt
│ ├── crypto.cpp
│ ├── crypto.hpp
│ ├── crypto_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── crypto_test.cpp
├── depend/
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── boost/
│ │ ├── CMakeLists.txt
│ │ └── package/
│ │ ├── .gitattributes
│ │ └── CMakeLists.txt
│ ├── googletest/
│ │ ├── CMakeLists.txt
│ │ └── package/
│ │ ├── .gitattributes
│ │ └── CMakeLists.txt
│ ├── jsoncpp/
│ │ ├── CMakeLists.txt
│ │ └── package/
│ │ ├── .gitattributes
│ │ └── CMakeLists.txt
│ ├── openssl/
│ │ ├── CMakeLists.txt
│ │ └── package/
│ │ ├── .gitattributes
│ │ └── CMakeLists.txt
│ └── rocksdb/
│ ├── CMakeLists.txt
│ └── package/
│ ├── .gitattributes
│ └── CMakeLists.txt
├── include/
│ ├── bluzelle.hpp
│ ├── boost_asio_beast.hpp
│ └── system_clock.hpp
├── mocks/
│ ├── CMakeLists.txt
│ ├── mock_boost_asio_beast.hpp
│ ├── mock_chaos_base.hpp
│ ├── mock_crud_base.hpp
│ ├── mock_crypto_base.hpp
│ ├── mock_monitor.hpp
│ ├── mock_node_base.hpp
│ ├── mock_options_base.hpp
│ ├── mock_pbft_base.hpp
│ ├── mock_pbft_failure_detector.hpp
│ ├── mock_pbft_service_base.hpp
│ ├── mock_peers_beacon_base.hpp
│ ├── mock_session_base.hpp
│ ├── mock_status_provider_base.hpp
│ ├── mock_storage_base.hpp
│ ├── mock_subscription_manager_base.hpp
│ ├── mock_system_clock.hpp
│ ├── mock_utils_interface.hpp
│ ├── smart_mock_io.cpp
│ ├── smart_mock_io.hpp
│ ├── smart_mock_node.cpp
│ ├── smart_mock_node.hpp
│ ├── smart_mock_peers_beacon.cpp
│ └── smart_mock_peers_beacon.hpp
├── monitor/
│ ├── CMakeLists.txt
│ ├── monitor.cpp
│ ├── monitor.hpp
│ ├── monitor_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── monitor_test.cpp
├── node/
│ ├── CMakeLists.txt
│ ├── node.cpp
│ ├── node.hpp
│ ├── node_base.hpp
│ ├── session.cpp
│ ├── session.hpp
│ ├── session_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ ├── node_test.cpp
│ └── session_test.cpp
├── options/
│ ├── CMakeLists.txt
│ ├── options.cpp
│ ├── options.hpp
│ ├── options_base.hpp
│ ├── simple_options.cpp
│ ├── simple_options.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── options_test.cpp
├── pbft/
│ ├── CMakeLists.txt
│ ├── database_pbft_service.cpp
│ ├── database_pbft_service.hpp
│ ├── dummy_pbft_service.cpp
│ ├── dummy_pbft_service.hpp
│ ├── operations/
│ │ ├── CMakeLists.txt
│ │ ├── pbft_memory_operation.cpp
│ │ ├── pbft_memory_operation.hpp
│ │ ├── pbft_operation.cpp
│ │ ├── pbft_operation.hpp
│ │ ├── pbft_operation_manager.cpp
│ │ ├── pbft_operation_manager.hpp
│ │ ├── pbft_persistent_operation.cpp
│ │ ├── pbft_persistent_operation.hpp
│ │ └── test/
│ │ ├── CMakeLists.txt
│ │ ├── pbft_operation_manager_test.cpp
│ │ ├── pbft_operation_test_common.cpp
│ │ └── pbft_persistent_operation_test.cpp
│ ├── pbft.cpp
│ ├── pbft.hpp
│ ├── pbft_base.hpp
│ ├── pbft_checkpoint_manager.cpp
│ ├── pbft_checkpoint_manager.hpp
│ ├── pbft_persistent_state.cpp
│ ├── pbft_persistent_state.hpp
│ ├── pbft_service_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ ├── database_pbft_service_test.cpp
│ ├── pbft_audit_test.cpp
│ ├── pbft_catchup_test.cpp
│ ├── pbft_checkpoint_tests.cpp
│ ├── pbft_newview_test.cpp
│ ├── pbft_peer_change_test.cpp
│ ├── pbft_persistent_state_test.cpp
│ ├── pbft_proto_test.cpp
│ ├── pbft_proto_test.hpp
│ ├── pbft_test.cpp
│ ├── pbft_test_common.cpp
│ ├── pbft_test_common.hpp
│ ├── pbft_timestamp_test.cpp
│ └── pbft_viewchange_test.cpp
├── peers_beacon/
│ ├── CMakeLists.txt
│ ├── peer_address.hpp
│ ├── peers_beacon.cpp
│ ├── peers_beacon.hpp
│ ├── peers_beacon_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── peers_beacon_tests.cpp
├── pkg/
│ ├── CMakeLists.txt
│ └── debian/
│ ├── CMakeLists.txt
│ ├── postinst
│ └── postrm
├── policy/
│ ├── CMakeLists.txt
│ ├── eviction_base.hpp
│ ├── random.cpp
│ ├── random.hpp
│ ├── test/
│ │ ├── CMakeLists.txt
│ │ └── eviction_test.cpp
│ ├── volatile_ttl.cpp
│ └── volatile_ttl.hpp
├── proto/
│ ├── CMakeLists.txt
│ ├── audit.proto
│ ├── bluzelle.proto
│ ├── database.proto
│ ├── pbft.proto
│ └── status.proto
├── qa/
│ └── integration-tests.sh
├── scripts/
│ ├── crud
│ ├── generate-key
│ └── sign_uuid.sh
├── scripts-1.md
├── status/
│ ├── CMakeLists.txt
│ ├── status.cpp
│ ├── status.hpp
│ ├── status_provider_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── status_test.cpp
├── storage/
│ ├── CMakeLists.txt
│ ├── mem_storage.cpp
│ ├── mem_storage.hpp
│ ├── rocksdb_storage.cpp
│ ├── rocksdb_storage.hpp
│ ├── storage_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── storage_test.cpp
├── swarm/
│ ├── CMakeLists.txt
│ └── main.cpp
├── utils/
│ ├── CMakeLists.txt
│ ├── blacklist.cpp
│ ├── blacklist.hpp
│ ├── bytes_to_debug_string.cpp
│ ├── bytes_to_debug_string.hpp
│ ├── crypto.cpp
│ ├── crypto.hpp
│ ├── esr_peer_info.cpp
│ ├── http_req.cpp
│ ├── make_endpoint.cpp
│ ├── make_endpoint.hpp
│ ├── test/
│ │ ├── CMakeLists.txt
│ │ ├── make_endpoint_test.cpp
│ │ └── utils_test.cpp
│ ├── utils_interface.hpp
│ └── utils_interface_base.hpp
└── valgrind/
├── bluzelle.supp
├── create_suppressions.sh
└── parse_valgrind_suppressions.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.idea/
.state/
build/
logs/
cmake-build-debug/
cmake-build-release/
scripts/bluzelle_pb2.py
scripts/database_pb2.py
scripts/audit_pb2.py
scripts/pbft_pb2.py
scripts/status_pb2.py
*.pyc
*.pem
================================================
FILE: .travis.yml
================================================
sudo: false
language: cpp
env:
global:
- PROJECT_VERSION_MAJOR="0"
- PROJECT_VERSION_MINOR="7"
- PROJECT_VERSION_PATCH="${TRAVIS_BUILD_NUMBER}"
- PROJECT_VERSION="${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}"
- PACKAGE_ARCHITECTURE="amd64"
- PACKAGE_NAME="bluzelle-swarmdb"
- PACKAGE_NAME_DEB="${PACKAGE_NAME}_${PROJECT_VERSION}_${PACKAGE_ARCHITECTURE}.deb"
- PACKAGE_NAME_OSX="${PACKAGE_NAME}_${PROJECT_VERSION}_darwin_${PACKAGE_ARCHITECTURE}.tar.gz"
- secure: "vF3zRyPiUm+VOVAq1y6TDGqr5s2XYk7In6Zh8LbX0VNv6ROQ7HEwusbO6tuR4I0Og0m59RplQd3oAr3nxLMN/85YQw1vvVbc+TC1wIenM15bfEgCKjTsiFbIEf7fPgUyqVg/YLGSEsskcXiFrfb5IyFmAj+v37u0N56u4B3/ga82e5RIXvu641z1Ex2sS0L/MhN4TOluI/5ASeg/D6QHKVx59HiX/PjOkWbCKY10p5CzbXgNyik37NrI1ZKnLTtYFCznuPeXpt4Vx0YdCLOaJw4uG2ay2CjayOmOvXlNWb9iHXL5EveovptDhSSqAJjzy+MqwnrjJHsciOBHX2efpeCpSBx6tGw9e8bi6Xg3MJvdPjEcfKoAWBG2MdJUAdGk48eduvdPqnx/Ig7//ez9aYLgbXaac3k09N5SeyPZuRE2mnQoXNcO2ApL3NfOAJ/3WRtFo/scgu8rBfEZrIqy2BAgnOK86TYZwIR1CabQgPDClY9XddcZ+PBQ4a+j/CqDTcjdYR5I7ABV4nPgCU2rheKEhKMv8yw4kFl5U6wFUOtkEdxFJk3+d8oxHPrQf0CDFKovkSEcMzEgcJE1DsVLNzNPlE9y12+Rsopt/fcCNqSvyl22XaI7O9UnE/j+Y2ATlydB+6olEvOEd02K9WYuVUotyeBu4bB8sY0V4VDREUI="
- secure: "Z4h7T0uHpz3WLtX93NckznB/FujL7LncaZdxJQ5DrWOtIpUJA7REix8oMDyTaXqhsksX5x24CdxuArmFkgE5G1xJK7sIgI7R6RlDG0shRyfMBWaB0Olbsxq9FiZb11Cmguq2ANoPdwFj53BwSjLs+8QW7wWx2NE4TF0JWWNBVVi1hcX5cPc2xW8oEy7657mxCTq6/G8upOonMRHmiB3M+u9Xn0Sv7+SCmtkFw6uUSGfRRkwwRl0haf0qwlOg6o6Aihen0zFEM/Rf3imx5JhyxtlW6KQBG8WZOmv2gQ9AXD9sAZG4H52Klr81QIhKrzlQNEoLvPtkhqTFXCGlBRH7bBXbCYRFYhvm8j1ja2tM46wZHwdIx5gtUqLk5+PcNdFEO335003GeOPewzayk44WWkPQyHPkNLTLAnLJawKkSDsLsWIokl0BGz5m2O08GBoohTd0LaOQrEi3npI92s6OasxPh9wcCwYYwGT5WqLmnKc6XRpI5I+RFN6yjPYCYUwgCd5LVkOG5hpvg8tTYG63gxshPJWSWv5yObMPppmObnpQNjPOdw63m9cpnevo2DbGLZsHedDyqMGhjZnn3CG8ZlRQvdPLo56l2gFRxhw8J2xnk1C2ffil8C9IjiTLBK+Y5ALd17BuI40ZA+ClRHy8Z6MFXgMfFlr/YBrUtY3tvGg="
- secure: "Hp7Ww6XhkZvzOsktsaL8lyiMbXLP3u/Entj7UXomywDr7gMIAyoIiD122bZ1Wa+sbNfnNd8lKS1AZxMtwxbhAK9hcB6ZvypAE3i4pfoQWxd4jq3pXltJ2oLbXEWzH1aGcTtibf2vI6WBpI8mPGWrykBeQfCzd0qs6t5pNzeA43ta77WCADWJivxe69l4rqxUGmXZVbGzApUgn5UP7FTscuByitQm6KPft63sre6aSC1P9FKWD4VOFlDqol3v+Bsmn05bNc9a/UuLq/C6vSa6BxsJpalMIRtlXE+MRXVpYxnBNS1UlH+8LA6txG3fwisyvwXG5KjO4tDuVLIYzuK1+TBCCnFBbTJ+2aCZ9iR7sA34A+AUbF2JyTfGtR4RnOd2cMgGuWgn1ASoe2c5GE45aK/s+ijDsKpzzHl8gR3QJS7yd0U/KCgnW3bsq4mRq95sjA/5MZuS2gmIpMS0JoprLmjXikZLI3LDQc8VHqK5U2ne/W7xZyszc57IlJI6HiL2v2yw25m8/yna7PXyAYFPsZ8LRzoZJvq/uBVh8sAnhpgMfQ5FxOuJGvhH56UjvcXqIYfz1a4ELIl8b2rLq6M1qUWYHwlTq8xHHhWShQBpfEiZQBncD0+K7LO7KhJb78sqJcbMFcgsWooKqlsElGQwK92BUkECRu8eC4n8uaaJ/GM="
- secure: "D3BGFKFKHDG0ajTpvEAP7poQmOvSUq2l7jG9q7hK+xHDRKBhM7YfSUJicz5H358VBKURoURLbykq3WXw/gpzTSVqpusXJ4UjGiAZLRXHlTsyXW0IVGvXXPx53SiJkHbfVC/3MK22rzV9LYR3wxEt7k9xKLfRGBr+tAiTzi/ikox/4ibIx6cb0PQGrVTbeoSJfJfF6VQvzeaoST7K9CREJGb9PuLpiXPRt0CIeY5Y1r7+HCJSzO2XWX+8i+DpMB7ZItQjrt09vaoDoUS5WPxL92+S8nrWNH++LhEzvq1PTtZs0bQkLHG+zfrM/5j2Q34HP6QZceVSixMzEz2l9wE0lZI5d21udnh1CApbaZvHHvLuR7cvZGv6VCNZefZhKTsDAs+GRMYLhZgauqxnOxug0ZO8ErLHJ0K87l/U0krBUCtMTO5FPodEPahXVOe9UXlBnl8FFhihQ4VB23TXWbFy0qa1M1iCV3jT27hpDHCmPuD5KwGWzDITrnaC0+YzQpmOuZKLB/wlQdJD7XmRkV3OCye1ejwFpwCD1SMJLZBTd4rReAgxxgT4f0xq/IuoGORvAXYDbZeYNrISYrxN8u6LAAc56IDQ7F8nZO/l85gPZaSrkzL4zeuDhWsMr/SBysBL2XlwhL9iSYHWEhgr67hJVOzVUqpMCH6nr2Y8hc4cK1w="
matrix:
include:
- os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb [trusted=yes] http://ppa.launchpad.net/maarten-fonville/protobuf/ubuntu xenial main'
packages:
- g++-7
- pkg-config
- protobuf-compiler
- libprotobuf-dev
- libsnappy-dev
- libbz2-dev
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- CMAKE_URL="https://cmake.org/files/v3.12/cmake-3.12.1-Linux-x86_64.tar.gz"
- CMAKE_COMMAND="$HOME/.local/bin/cmake -DPMD_EXE=$HOME/pmd-bin-6.6.0/bin/run.sh ${CMAKE_OPTIONS}"
cache:
directories:
- $HOME/.local
before_install:
- eval "${MATRIX_EVAL}"
- mkdir -p $HOME/.local
- |
pip install --user cpp-coveralls
if [ ! -e $HOME/.local/bin/cmake ]; then
echo "CMake not found in the cache, get and extract it..."
travis_retry curl -L ${CMAKE_URL} \
| tar -xz -C $HOME/.local --strip-components=1
else
echo "Using cached CMake"
fi
- |
if [ ! -e $HOME/pmd-bin-6.6.0/bin/run.sh ]; then
echo "PMD not found in the cache, get and extract it..."
cd $HOME
travis_retry curl -OL "https://github.com/pmd/pmd/releases/download/pmd_releases%2F6.6.0/pmd-bin-6.6.0.zip"
unzip pmd-bin-6.6.0.zip
rm pmd-bin-6.6.0.zip
else
echo "Using cached PMD"
fi
compiler:
- gcc
before_script:
- cd ${TRAVIS_BUILD_DIR}
- mkdir build
- cd build
- >
if { [ "$TRAVIS_BRANCH" = "master" ] || [[ $TRAVIS_BRANCH == *"release"* ]]; } && [ $TRAVIS_OS_NAME = "linux" ] ; then
${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPROJECT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} -DPROJECT_VERSION_MINOR=${PROJECT_VERSION_MINOR} -DPROJECT_VERSION_PATCH=${PROJECT_VERSION_PATCH} ..
else
${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -DENABLE_GCOV=ON -DPROJECT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} -DPROJECT_VERSION_MINOR=${PROJECT_VERSION_MINOR} -DPROJECT_VERSION_PATCH=${PROJECT_VERSION_PATCH} ..
fi
script:
- ${CXX} --version
- echo CXXFLAGS=${CXXFLAGS}
- git lfs install
- git lfs pull
- make -j2
- make static_analysis
- ctest
- make package
after_success:
- coveralls -r ${TRAVIS_BUILD_DIR} -e 'build/boost' -e 'build/openssl' -e 'build/rocksdb' -e 'build/jsoncpp' -e 'build/googletest' -e 'build/proto' -e 'build/CMakeFiles' -e 'build/swarm_version.hpp' -e 'audit/test' -e 'bootstrap/test' -e 'chaos/test' -e 'crud/test' -e 'crypto/test' -e 'ethereum/test' -e 'http/test' -e 'mocks' -e 'node/test' -e 'options/test' -e 'pbft/test' -e 'status/test' -e 'storage/test' -e 'swarm' -e 'include' -e 'utils/test' --gcov-options '\-lp'
- echo ${TRAVIS_BRANCH}
- if [ "$TRAVIS_BRANCH" = "master" ] ; then PACKAGE_COMPONENT="stable" ; else PACKAGE_COMPONENT="unstable" ; fi
- |
if [ "$TRAVIS_BRANCH" = "master" ] || [ "$TRAVIS_BRANCH" = "devel" ] || [[ $TRAVIS_BRANCH == *"release"* ]]; then
travis_retry curl -u${REPO_USER}:${REPO_PASSWORD} -XPUT "https://bluzelle.jfrog.io/bluzelle/debian-local/pool/${PACKAGE_NAME_DEB};deb.distribution=all;deb.component=${PACKAGE_COMPONENT};deb.architecture=${PACKAGE_ARCHITECTURE}" -T ${TRAVIS_BUILD_DIR}/build/${PACKAGE_NAME_DEB}
fi
if [ "$TRAVIS_BRANCH" = "master" ] ; then
git lfs fetch --all
git tag ${PROJECT_VERSION}
git remote add origin-swarm https://${GITHUB_TOKEN}@github.com/bluzelle/swarmdb.git > /dev/null 2>&1
git push --quiet --set-upstream origin-swarm ${TRAVIS_BRANCH} --tags
fi
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.10)
project(bluzelle CXX)
# ensure type is set
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
include(cmake/swarm_version.cmake)
message("Build version ${PROJECT_VERSION}")
# Setup version header
configure_file(${PROJECT_SOURCE_DIR}/cmake/swarm_version.hpp.in ${CMAKE_BINARY_DIR}/swarm_version.hpp.tmp)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/swarm_version.hpp.tmp ${CMAKE_BINARY_DIR}/swarm_version.hpp)
execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/swarm_version.hpp.tmp)
include_directories(${CMAKE_BINARY_DIR}) # hides path bug!
# use ccache if available...
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif(CCACHE_FOUND)
# output dir
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
# compiler options...
set(CMAKE_CXX_STANDARD 17)
add_compile_options("-fdiagnostics-color=auto")
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY)
# todo: remove -Wno-implicit-fallthrough once CI moves past gcc 7.4.0...
set(warnings "-Wall -Wextra -Werror -Wpedantic -Wno-implicit-fallthrough")
if (APPLE)
set(warnings "${warnings} -Wno-invalid-offsetof")
else()
# for beast and gcc release builds...
if("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
set(warnings "${warnings} -Wno-maybe-uninitialized")
endif()
# todo: these may no longer be required...
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.2)
message(STATUS "GCC ${CMAKE_CXX_COMPILER_VERSION} warning workaround: -Wno-deprecated-copy -Wno-sign-compare (Still needed?)")
set(warnings "${warnings} -Wno-deprecated-copy -Wno-sign-compare")
endif()
endif()
set(CMAKE_CXX_FLAGS ${warnings})
# old or new way?
if(NOT BUILD_DEPEND)
add_subdirectory(depend)
else()
include(cmake/boost.cmake)
include(cmake/rocksdb.cmake)
include(cmake/jsoncpp.cmake)
include(cmake/googletest.cmake)
include(cmake/openssl.cmake)
endif()
# find packages
include(cmake/add_gmock_test.cmake)
set(Protobuf_USE_STATIC_LIBS ON)
include(FindProtobuf)
find_package(Protobuf REQUIRED)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(SYSTEM ${PROTOBUF_INCLUDE_DIR})
enable_testing()
# coverage?
if (ENABLE_GCOV)
if (NOT APPLE)
set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage" CACHE INTERNAL "")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}")
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
endif()
endif()
add_subdirectory(proto)
set(BLUZELLE_STD_INCLUDES ${Boost_INCLUDE_DIRS} ${GTEST_INCLUDE_DIR} ${JSONCPP_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${PROTO_INCLUDE_DIRS} ${ROCKSDB_INCLUDE_DIRS})
add_subdirectory(peers_beacon)
add_subdirectory(crud)
add_subdirectory(node)
add_subdirectory(options)
add_subdirectory(pkg)
add_subdirectory(status)
add_subdirectory(storage)
add_subdirectory(swarm)
add_subdirectory(utils)
add_subdirectory(audit)
add_subdirectory(pbft)
add_subdirectory(chaos)
add_subdirectory(crypto)
add_subdirectory(monitor)
add_subdirectory(mocks)
add_subdirectory(policy)
include(cmake/static_analysis.cmake)
# git commit used to build
add_custom_command(
OUTPUT swarm_git_commit
COMMENT "Generating swarm_git_commit.hpp"
COMMAND ${CMAKE_COMMAND}
-D PROJECT_SOURCE_DIR=${CMAKE_SOURCE_DIR}
-D PROJECT_BINARY_DIR=${CMAKE_BINARY_DIR}
-P ${CMAKE_SOURCE_DIR}/cmake/git_commit.cmake
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
add_custom_target(swarm-git-commit ALL DEPENDS swarm_git_commit)
# enable valgrind for CI...
if(ENABLE_MEMCHECK)
# todo: add to CI: ctest --test-action memcheck
if(NOT APPLE)
set(MEMORYCHECK_SUPPRESSIONS_FILE ${PROJECT_SOURCE_DIR}/valgrind/bluzelle.supp)
set(VALGRIND_COMMAND_OPTIONS "--error-exitcode=1 --leak-check=full --show-reachable=yes --error-limit=no --gen-suppressions=all")
include(CTest)
endif()
endif()
================================================
FILE: CONTRIBUTOR.md
================================================
# Contributing to Bluzelle
Welcome to wanting to contribute to Bluzelle! Thank you for taking your time to contribute.
The following is a set of guidelines for contributing to the Bluzelle ecosystem (this includes swarmDB, the drivers, and more). These are of course mostly just guidelines, not rules. Feel free to use your best judgement, and you can always contribute proposals to change this guide via a pull request!
#### Table Of Contents
[Code of Conduct](#code-of-conduct)
[The Quick Start Guide](#the-quick-start-guide)
[Getting Started](#getting-started)
[How Can I Contribute?](#how-can-icontribute)
[Coding Style Guide](#coding-style-guide)
## Code of Conduct
This project and its participants are governed by the [Bluzelle Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project, you are expected to uphold the code. Report unacceptable behaviour to [opensource@bluzelle.com](mailto:opensource@bluzelle.com).
The general idea here is that you should be **respectful**, **positive** and **considerate**. When asking questions, please be **patient** for a response, **specific** in what you are asking, and always think **collaboratively**. You are reminded that you should not **spam**, post links to sites that violate our Terms of Use, or post third party advertisements.
## The Quick Start Guide
Join our community resources:
* [mailing list](https://groups.google.com/forum/#!forum/bluzelle) - this is the Google group where Bluzelle developers discuss development plans. Users are also encourage to ask questions here. You can either subscribe to the list, or read it as a forum.
* [Gitter](https://gitter.im/bluzelle) - if chat is something you prefer, and you're looking for answers quicker, get to the Bluzelle Gitter community. We have several rooms and you could post to the Lobby or anywhere you feel is appropriate. Remember though that you *may* not get answers immediately, as the Bluzelle project is distributed worldwide, and it might take some time for you to get an answer. Please be patient.
## Getting Started
Bluzelle is growing to be a large open source project. There are many repositories on [GitHub](http://github.com/bluzelle) and it is a good idea to familiarise yourself with them.
* [bluzelle/swarmDB](https://github.com/bluzelle/swarmDB) - this is the core Bluzelle decentralised database.
Do pay attention to the branches within swarmDB as there are plenty!
### Client Libraries
* [pyBluzelle](https://github.com/bluzelle/pyBluzelle) - this is the Python client library for Bluzelle swarmDB.
* [swarmclient-js](https://github.com/bluzelle/swarmclient-js) - this is the JavaScript client library for Bluzelle swarmDB.
* [bluzelle-php](https://github.com/bluzelle/bluzelle-php) - this is the PHP client library for Bluzelle swarmDB.
* [swarmclient-rb](https://github.com/bluzelle/swarmclient-rb) - this is the Ruby client library for Bluzelle swarmDB.
## How Can I Contribute?
### How to report bugs
The Swarmdb project is tracking issues within github issues. If you find a bug within the software or documentation please open a new [issue](https://github.com/bluzelle/swarmDB/issues). Your bug will be placed on our backlog and addressed based on priotiry.
### How do I suggest enhancements?
Enhancements can be requested in two ways.
1. Like bugs you can open a new [issue](https://github.com/bluzelle/swarmDB/issues)
2. More proactively you can make the code or documentation change and submit it as a pull request
### Making your first code contribution
### Branching Model
Basic standards will be in place across all Bluzelle repositories that are based off the [Git Flow model](https://datasift.github.io/gitflow/IntroducingGitFlow.html). Below you will find a description of each branch and it’s intended purpose.
#### Devel
**Branch**: Devel
**Purpose**: The Devel branch the official integration branch.
**Perquisite for commits**: Merges to this branch are by pull request only and must pass the Travis Build and have at least one code review. Any committer can merge a pull request once the above requisites are satisfied. Only squash merges are allowed in this branch.
**Tags**: None
**Build artifacts**: Build automation may push to an “unstable” repository for testing
#### Master
**Branch**: Master
**Purpose**: Master will ***ONLY*** have commits related to official releases (major, minor and patch).
**Prerequisite for commit**: Merges to this branch are by pull request only and must pass the Travis Build and have at least one code review. ONLY official branch owners can merge a pull request. Only merges are allowed on this branch.
**Tags**: `${major}-${minor}-${TRAVIS-BUILD}`
**Build artifacts**: Build automation must push to an official repo either public or the Bluzelle artifactory repositories
#### Feature Branch
**Branch**: `/task/${username}/${taskname}`
**Purpose**: This is a feature branch and is meant to last for the duration of feature development. There is no implication of stability in a feature branch and developers have absolute freedom on what happens within these branches. After merging to the devel branch the feature branch is deleted.
**Prerequisite for commit**: None
**Tags**: None
**Build artifacts**: None
#### Commit Messages
Commit messages must follow the basic structure in the example provided below. An “issuekey” may be either a GitHub Issue or Jira Issue. Commit messages will contain a single line description of the change, followed by a more in depth description of the commit.
Example:
~~~~
${issuekey} This is a one line commit message
This is a longer commit paragraph for more detail. It may also contain bullet points:
feature change 1
feature change 2
side effect 1
~~~~
### Pull requests and signing the Bluzelle Contributor License Agreement (CLA)
Once you have submitted a pull request, you will also have to sign the Bluzelle Contributor License Agreement (CLA). This is done automatically, as long as you have a GitHub account, and submit the pull request. Without signing the CLA, your contribution cannot be accepted and there will be no review for the pull request to get it merged.
We use an automated platform to track digital signatures tied to your GitHub username.
## Coding Style Guide
Use this document as a guideline, if you don't find what you need here please contact a Bluzelle employee with your comments or suggestions.
Another great resource is the Google C++ Style guide (https://google.github.io/styleguide/cppguide.html)
### Project Layout
* CMake is used to generate a build environment. (ie. makefiles, xcode project etc.)
* Source and test file naming is based on the class being defined/tested:
ex. node module
node
├── CMakeLists.txt
├── node_base.hpp
├── node.cpp
├── node.hpp
├── session_base.hpp
├── session.cpp
├── session.hpp
└── test
├── CMakeLists.txt
├── node_test.cpp
└── session_test.cpp
### Code style
* Write your code as though you are writing it for publication.
* Your code should compile with no warnings using the C++ 17 flag.
* Allman coding style using 4 space characters for indentation. (https://en.wikipedia.org/wiki/Indentation_style#Allman_style)
* Try to limit line length to 120 characters. Continuation of code should be the next line with one indentation level.
* Header files should use newer "#pragma once" instead of traditional #ifdef guard macros.
* Source and test file naming is based on the class being defined/tested:
class this_is_an_example:
{
...
this_is_an_example.hpp
this_is_an_example.cpp
this_is_an_example_test.cpp
* When modifying existing code continue the style that it was created to maintain consistency.
* Function/method definitions should have return type on a separate line:
bool
class::method()
{
...
return true;
}
* Use #include<cstdint> for POD types such as uint32_t, uint64_t etc.
* Do not use "auto" for POD types
* Use auto for types that can not be defined or are rather verbose such as a lambda or an iterator.
* Use snake case for class & variable naming:
class this_is_snake_case
{
...
variables:
uint32_t widget_count;
* Class layout should be public, protected & private:
class foo
{
public:
// initialization list layout example...
foo(uint32_t foo_counter, uint32_t max_widgets)
: foo_counter(foo_counter)
, max_widgets(max_widgets)
{
}
private:
uint32_t foo_counter = 0; // prefer class initialization of variable if not passed through constructor
const uin32_t max_widgets;
};
* Constructor layout should align with the first parameter:
foo::foo(unsigned int age,
float weight_in_tonnes,
string name,
string city,
string country)
: this->age(age)
, this->weight_in_tonnes(weight_in_tonnes)
, this->name(name)
, this->city(city)
, this->country(country)
{
...
}
* Do not use Hungarian notation.
* Class and variable names should be descriptive; avoid abbreviation unless using a standard nomenclature such as TCP, UDP, HTTP & CURL.
* Code within namespace should be indented
* Even single lines of code for conditionals and loops should be enclosed by braces.
switch(my_value)
{
case MY_CONST_GLOBAL:
{
...
}
break;
default:
{
...
}
break;
}
* When using multiple levels of namespaces use c++17's syntax:
namespace bzn::utils
{
class ....
* Use "using namespace" sparingly and only where you should follow the DRY principle.
* Use Test Driven Development
* Use CI's code coverage reporting to help identify untested code and exception cases
* Create a mockable interface class to help test code that would require complex setup or dependencies such as a server
class foo_base
{
public:
virtual ~foo_base() = default;
void function_one() const = 0;
...
* Do not use dynamic cast unless there is a very compelling reason
* Const casts are not to be used under any circumstances
* Reinterpret casts are only to be used in situations where “void” pointers are being upcast
* Const should be used in every place it can be used. For example, imagine the following function get_window in some class prototype:
const Window* get_window(const Foo* const some_variable_name) const
* Derived classes from an interface should be marked as final unless the intent is to use it as a base class.
* Use references everywhere applicable for function parameters.
* Globals will be declared const within an unnamed namespace
namespace
{
const uint32_t MY_CONST_GLOBAL = 1337;
}
* As a fundamental principle, there should be no entropy whatsoever in the code.Some common examples of entropy include the use of static initialization where the order of instantiation is often non-deterministic.
* Variable names must CLEARLY describe the type and usage
* Use std::shared_ptr & std::unique_ptr instead of raw pointers.
* Use const where possible (functions & variables)
* Do not use typedef, but use "using xyz_t" language feature where new types have a suffix of _t:
using foo_count_t = uint32_t;
* Use new enum classes and specify size type:
enum class state : uint8_t
{
...
* Access member variables and functions always using the "this->" pointer. Do not mark member variables with a prefix/postfix pattern.
this->function_one();
this->a_member_variable = 0;
* Use Doxygen style comments for all public methods. Base class should have them and derived classes do not require it.
* Comment any code that is not obvious, in terms of what it does.
* Reference symbol should be added to the type and not the variable.
void function(const some_type& my_type);
### Best practices
* Follow SOLID & DRY principles
Keep functions small and focused. (https://en.wikipedia.org/wiki/SOLID)
* Before writing new code to support a feature, follow these steps:
1. Check the C++ std library algorithms etc.
2. If not in std library then look at boost.
3. If boost can't help then consult with the Bluzelle team, third party libraries
4. If you can't find a third party library then consider implementing your own.
* #includes should use <path/header_file.hpp> and not "header_file.hpp"
#include <include/boost_asio_beast.hpp>
#include <node/node_base.hpp>
#include <node/session_base.hpp>
#include <options/options_base.hpp>
* Preferred include ordering:
1. global project headers
2. current lib/code headers
3. other project lib headers
4. third_party lib headers
5. standard headers
* Use functional style as apposed to raw loops such has std::find_if, std::remove_if etc.
* Use exceptions only when the code can not function with out "something". Typically this would be during construction of a class.
* Long functions are difficult to change and difficult to understand. Each function should attempt to do exactly one thing. You should be able to sum it up in one sentence (and the method name should be a summary of that sentence). If you find a function is getting too long, split it into sensible parts.
* Functions taking large numbers of parameters (ie: more than six) are a generally a bad idea and are indicative of either a function trying to do too much or poor class organization. Split the function up into sensible parts.
* Conditionals and loops should not be nested more than three deep. Any such code needs to be refactored. Either pull the inner parts of the code into separate methods or pull the complex conditions into functions. A line of code should never exceed approximately seventy characters.
================================================
FILE: LICENSE
================================================
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.gnu.org/licenses/>.
================================================
FILE: README.md
================================================
# SwarmDB
[](https://travis-ci.org/bluzelle/swarmDB) [](https://coveralls.io/github/bluzelle/swarmDB?branch=devel) [](https://github.com/bluzelle/swarmDB/blob/devel/LICENSE) [](https://twitter.com/BluzelleHQ) [](https://gitter.im/bluzelle)
## ABOUT SWARMDB
Bluzelle brings together the sharing economy and token economy. Bluzelle enables people to rent out their computer storage space to earn a token while dApp developers pay with a token to have their data stored and managed in the most efficient way.
## Getting started with Docker
If you want to deploy your swarm immediately you can use our docker-compose quickstart instructions:
### Install Docker
[Docker Installation Guide](https://docs.docker.com/install/)
1. Setup a local docker-compose swarm with the instructions found [here](https://github.com/bluzelle/docker-swarm-deploy)
2. Run `docker-compose up` in the same directory of your docker-compose.yml. This command will initialize the swarm within your local docker-machine. Full docker-compose documentation can be found [here](https://docs.docker.com/compose/)
3. Nodes are available on localhost port 51010-51012
4. [Connect a test websocket client](https://github.com/bluzelle/swarmDB#testing-locally)
5. Create a node server application using our node.js [library](https://github.com/bluzelle/bluzelle-js)
6. `CTRL-C` to terminate the docker-compose swarm
## Getting started building from source
### Installation - Ubuntu
**CMake (Ver. 3.10 or greater) etc.**
On Ubuntu 18.04 and newer, you can simply install via `apt`.
```text
$ sudo apt-get install cmake
```
If your system packages don't have a new enough version, you can install a
different CMake into `~/mycmake/` to avoid overwriting your system's `cmake`.
```text
$ sudo apt-get install curl libcurl4-openssl-dev
$ mkdir -p ~/mycmake
$ curl -L http://cmake.org/files/v3.11/cmake-3.11.0-Linux-x86_64.tar.gz | tar -xz -C ~/mycmake --strip-components=1
```
You would then use `~/mycmake/bin/cmake ..` instead of `cmake ..` in further
instructions.
**Protobuf \(Ver. 3 or greater\) etc.**
```text
$ sudo apt-add-repository ppa:maarten-fonville/protobuf
$ sudo apt-get update
$ sudo apt-get install pkg-config protobuf-compiler libprotobuf-dev libsnappy-dev libbz2-dev
```
**ccache \(Optional\)**
If available, cmake will attempt to use ccache \([https://ccache.samba.org](https://ccache.samba.org)\) to _drastically_ speed up compilation.
```text
$ sudo apt-get install ccache
```
**Git LFS \(Optional\)**
Git LFS is currently being used to speed up builds if available.
```text
$ sudo apt-get install git-lfs
$ git lfs install
```
### Building the Daemon from Command Line Interface \(CLI\)
**Note**: Git LFS is used by default. If you do not have it set up, you must
build the dependencies by setting `BUILD_DEPEND=YES` in your `cmake` call, e.g.
`cmake .. -DBUILD_DEPEND=YES`, and omit the `git lfs` commands.
Here are the steps to build the Daemon and unit test application from the command line:
```text
$ mkdir build
$ cd build
$ cmake ..
$ git lfs install
$ git lfs pull
$ sudo make install
```
### Deploying the Daemons
#### The Bluzelle Configuration File
The Bluzelle daemon is configured by setting the properties of a JSON
configuration file provided by the user. This file is usually called
*bluzelle.json* and resides in the current working directory. To specify a
different configuration file the daemon can be executed with the -c command
line argument:
$ swarm -c peer0.json
The configuration file is a JSON format file, as seen in the following example:
{
"listener_address" : "127.0.0.1",
"listener_port" : 50000,
"bootstrap_file" : "/home/isabel/swarmdb/local/nodes/peers.json",
"debug_logging" : true,
"log_to_stdout" : true,
"use_pbft": true,
"bootstrap_file": "./peers.json",
"stack" : "testnet-dev"
}
The complete documentation of the options available for this file is given by
$ swarm --help
but the properties likely useful for a minimal swarm are summarized here:
- "bootstrap_file" - path to peers file (see below)
- "debug_logging" - show more log info
- "listener_address" - the ip address that SwarmDB will listen on (this should be "127.0.0.1" unless you are doing something fancy)
- "listener_port" - the port that SwarmDB will listen on (each node running on the same host should use a different port)
- "log_to_stdout" (optional) - log to stdout as well as log file
- "uuid" - the universally unique identifier that this instance of SwarmDB will use to uniquely identify itself. This should be specified if and only if node cryptography is disabled (the default) - otherwise, nodes use their private keys as their identifier.
- "stack" - software stack used by swarm
#### The Bluzelle Bootstrap File
The bootstrap file, identified in the config file by the "bootstrap_file"
parameter, see above, provides a list of nodes in the the swarm that the
local instance of the SwarmDB daemon can communicate with. If the membership
of the swarm has changed, these nodes will be used to introduce the node to
the current swarm and catch it up to the current state, and the bootstrap file
acts as a "starting peers list".
If you are running a static testnet (i.e., nodes do not join or leave the swarm)
then every node should have the same bootstrap_file, and it should include
an entry for every node. Thus, each node will appear in its own bootstrap file.
If a node is not already in the swarm when it starts (i.e., it should dynamically join
the swarm) then it should not be in its own bootstrap file.
The booststrap file format is a JSON array, containing JSON objects describing
nodes as seen in the following example:
[
{
"host": "127.0.0.1",
"name": "peer0",
"port": 49152,
"uuid": "d6707510-8ac6-43c1-b9a5-160cf54c99f5"
},
{
"host": "127.0.0.1",
"name": "peer1",
"port": 49153,
"uuid": "5c63dfdc-e251-4b9c-8c36-404972c9b4ec"
},
...
{
"host": "127.0.0.1",
"name": "peer1",
"port": 49153,
"uuid": "ce4bfdc-63c7-5b9d-1c37-567978e9b893a"
}
]
where the Peer object parameters are (ALL PARAMETERS MUST MATCH THE PEER CONFIGURATION):
- "host" - the IP address associated with the external node
- "name" - the human readable name that the external node uses
- "port" - the socket address that the external node will listen for protobuf and web socket requests. (listen_port in the config file)
- "uuid" - the universally unique identifier that the external node uses to uniquely identify itself. This is required to be unique per node and consistent between the peerlist and the config.
Note that if node cryptography is enabled (see swarmdb --help), node uuids are their public keys.
#### Steps to setup and run Daemon:
1. Create each of the JSON files as described above in swarmDB/build/output/, where the swarm executable resides. \(bluzelle.json, bluzelle2.json, bluzelle3.json, bluzelle4.json, peers.json\).
2. Create an account with Etherscan: [https://etherscan.io/register](https://etherscan.io/register)
3. Create an Etherscan API KEY by clicking Developers -> API-KEYs.
4. Add your Etherscan API KEY Token to the configuration files.
5. Modify the `ethereum` address to be an Ethereum mainnet address that contains tokens or use the sample address provided above.
6. Ensure that each swarmdb instance is configured to listen on a different port and has a different uuid, and that the peers file contains correct uuids and addresses for all nodes
7. Deploy your swarm of Daemons. From the swarmDB/build/output/ directory, run:
```text
$ ./swarm -c bluzelle.json
$ ./swarm -c bluzelle2.json
$ ./swarm -c bluzelle3.json
```
## Integration Tests With Bluzelle's Javascript Client
### Installation - macOSX
#### Homebrew
```text
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
#### Node
```text
$ brew install node
```
#### Yarn
```text
$ brew install yarn
```
### Installation - Ubuntu
#### NPM
```text
$ sudo apt-get install npm
```
#### Update NPM
```text
$ sudo npm install npm@latest -g
```
#### Yarn
```text
$ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
$ sudo apt-get update && sudo apt-get install yarn
```
### Running Integration Tests
Script to clone _bluzelle-js_ repository and copy template configuration files or run tests with your configuration files.
```text
$ qa/integration-tests setup // Sets up template configuration files
```
```text
$ qa/integration-tests // Runs tests with configuration files you've created
```
## Testing Locally
```text
$ cd scripts
Follow instructions in readme.md
```
#### Connectivity Test
```text
$ ./crud -s <SWARM-ID> -n localhost:49154 status
Client: crud-script-0
Sending:
swarm_id: "<SWARM-ID>"
sender: "crud-script-0"
status_request: ""
------------------------------------------------------------
Response:
swarm_version: "0.3.1443"
swarm_git_commit: "0.3.1096-41-g91cef89"
uptime: "1 days, 17 hours, 29 minutes"
module_status_json: ...
pbft_enabled: true
Response:
{
"module" :
[
{
"name" : "pbft",
"status" :
{
"is_primary" : false,
"latest_checkpoint" :
{
"hash" : "",
"sequence_number" : 3800
},
"latest_stable_checkpoint" :
{
"hash" : "",
"sequence_number" : 3800
},
"next_issued_sequence_number" : 1,
"outstanding_operations_count" : 98,
"peer_index" :
[
{
"host" : "127.0.0.1",
"name" : "node_0",
"port" : 50000,
"uuid" : "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/HIPqL97zXbPN8CW609Dddu4vSKx/xnS1sle0FTgyzaDil1UmmQkrlTsQQqpU7N/kVMbAY+/la3Rawfw6VjVpA=="
},
{
"host" : "127.0.0.1",
"name" : "node_1",
"port" : 50001,
"uuid" : "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELUJ3AivScRn6sfBgBsBi3I18mpOC5NZ552ma0QTFSHVdPGj98OBMhxMkyKRI6UhAeuUTDf/mCFM5EqsSRelSQw=="
},
{
"host" : "127.0.0.1",
"name" : "node_2",
"port" : 50002,
"uuid" : "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEg+lS+GZNEOqhftj041jCjLabPrOxkkpTHSWgf6RNjyGKenwlsdYF9Xg1UH1FZCpNVkHhCLi2PZGk6EYMQDXqUg=="
}
],
"primary" :
{
"host" : "127.0.0.1",
"host_port" : 50001,
"name" : "node_1",
"uuid" : "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELUJ3AivScRn6sfBgBsBi3I18mpOC5NZ552ma0QTFSHVdPGj98OBMhxMkyKRI6UhAeuUTDf/mCFM5EqsSRelSQw=="
},
"unstable_checkpoints_count" : 0,
"view" : 1
}
}
]
}
------------------------------------------------------------
```
#### Create database
```text
./crud -s <SWARM-ID> -n localhost:50000 create-db -u myuuid
Client: crud-script-0
------------------------------------------------------------
Response:
header {
db_uuid: "myuuid"
nonce: 2998754133578549919
}
------------------------------------------------------------
```
#### Create
```text
$ ./crud -s <SWARM-ID> -n localhost:50000 create -u myuuid -k mykey -v myvalue
Client: crud-script-0
------------------------------------------------------------
Response:
header {
db_uuid: "myuuid"
nonce: 9167923913779064632
}
------------------------------------------------------------
```
#### Read
```text
$ ./crud -s <SWARM-ID> -n localhost:50000 read -u myuuid -k mykey
Client: crud-script-0
------------------------------------------------------------
Response:
header {
db_uuid: "myuuid"
nonce: 1298794800698891064
}
read {
key: "mykey"
value: "myvalue"
}
------------------------------------------------------------
```
#### Update
```text
$ ./crud -s <SWARM-ID> -n localhost:50000 update -u myuuid -k mykey -v mynewvalue
Client: crud-script-0
------------------------------------------------------------
Response:
header {
db_uuid: "myuuid"
nonce: 9006453024945657757
}
------------------------------------------------------------
```
#### Delete
```text
$ ./crud -s <SWARM-ID> -n localhost:50000 delete -u myuuid -k mykey
Client: crud-script-0
------------------------------------------------------------
Response:
header {
db_uuid: "myuuid"
nonce: 7190311901863172254
}
------------------------------------------------------------
```
#### Subscribe
```text
$ ./crud -s <SWARM-ID> -n localhost:50000 subscribe -u myuuid -k mykey
Client: crud-script-0
------------------------------------------------------------
Response:
header {
db_uuid: "myuuid"
nonce: 8777225851310409007
}
------------------------------------------------------------
Waiting....
Response:
header {
db_uuid: "myuuid"
nonce: 8777225851310409007
}
subscription_update {
key: "mykey"
value: "myvalue"
}
------------------------------------------------------------
Waiting....
```
#### Delete database
```text
./crud -s <SWARM-ID> -n localhost:50000 delete-db -u myuuid
Client: crud-script-0
------------------------------------------------------------
Response:
header {
db_uuid: "myuuid"
nonce: 1540670102065057350
}
------------------------------------------------------------
```
#### Adding or Removing A Peer
Dynamically adding and removing peers is not supported in this release. This functionality will be available in a subsequent version of swarmDB.
#### Help & Options
```text
$ ./crud --help
usage: crud [-h] [-p] [-i ID] -n NODE
{status,create-db,delete-db,has-db,writers,add-writer,remove-writer,create,read,update,delete,has,keys,size,subscribe}
...
crud
positional arguments:
{status,create-db,delete-db,has-db,writers,add-writer,remove-writer,create,read,update,delete,has,keys,size,subscribe}
status Status
create-db Create database
delete-db Delete database
has-db Has database
writers Database writers
add-writer Add database writers
remove-writer Remove database writers
create Create k/v
read Read k/v
update Update k/v
delete Delete k/v
has Determine whether a key exists within a DB by UUID
keys Get all keys for a DB by UUID
size Determine the size of the DB by UUID
subscribe Subscribe and monitor changes for a key
optional arguments:
-h, --help show this help message and exit
-i ID, --id ID Crud script sender id (default 0)
-s <SWARM-ID>, Swarm id
--swarm_id <SWARM-ID>
required arguments:
-n NODE, --node NODE node's address (ex. 127.0.0.1:51010)
================================================
FILE: SUMMARY.md
================================================
# Table of contents
* [SwarmDB](README.md)
* [Python CRUD Test App](scripts-1.md)
================================================
FILE: audit/CMakeLists.txt
================================================
add_library(audit
audit_base.hpp
audit.hpp
audit.cpp
../mocks/mock_pbft_base.hpp)
target_link_libraries(audit utils proto)
add_dependencies(audit boost jsoncpp)
target_include_directories(audit PRIVATE ${BLUZELLE_STD_INCLUDES})
add_subdirectory(test)
================================================
FILE: audit/audit.cpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <audit/audit.hpp>
#include <boost/beast/core/detail/base64.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/format.hpp>
#include <boost/system/error_code.hpp>
#include <utils/bytes_to_debug_string.hpp>
using namespace bzn;
audit::audit(std::shared_ptr<bzn::asio::io_context_base> io_context
, std::shared_ptr<bzn::node_base> node
, size_t mem_size
, std::shared_ptr<bzn::monitor_base> monitor
)
: node(std::move(node))
, io_context(std::move(io_context))
, primary_alive_timer(this->io_context->make_unique_steady_timer())
, mem_size(mem_size)
, monitor(std::move(monitor))
{
}
void
audit::start()
{
std::call_once(this->start_once, [this]()
{
this->node->register_for_message(bzn_envelope::kAudit,
std::bind(&audit::handle, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
LOG(debug) << "starting primary alive timer";
this->reset_primary_alive_timer();
});
}
void
audit::reset_primary_alive_timer()
{
this->primary_dead_count = 0;
this->primary_alive_timer->cancel();
this->primary_alive_timer->expires_from_now(this->primary_timeout);
this->primary_alive_timer->async_wait(std::bind(&audit::handle_primary_alive_timeout, shared_from_this(), std::placeholders::_1));
}
void
audit::handle_primary_alive_timeout(const boost::system::error_code& ec)
{
if (ec && ec != boost::system::errc::operation_canceled)
{
LOG(trace) << "primary alive timeout canceled " << ec.message();
return;
}
if (ec == boost::system::errc::operation_canceled)
{
LOG(trace) << "primary still alive";
return;
}
this->monitor->send_counter(bzn::statistic::pbft_no_primary);
this->primary_alive_timer->expires_from_now(this->primary_timeout);
this->primary_alive_timer->async_wait(std::bind(&audit::handle_primary_alive_timeout, shared_from_this(), std::placeholders::_1));
}
void
audit::handle(const bzn_envelope& env, std::shared_ptr<bzn::session_base> /*session*/)
{
audit_message message;
if (!message.ParseFromString(env.audit()))
{
LOG(error) << "failed to parse audit message from " << env.sender();
}
LOG(trace) << "got audit message" << message.DebugString();
if (message.has_pbft_commit())
{
this->handle_pbft_commit(message.pbft_commit());
}
else if (message.has_primary_status())
{
this->handle_primary_status(message.primary_status());
}
else if (message.has_failure_detected())
{
this->handle_failure_detected(message.failure_detected());
}
else
{
LOG(error) << "got an unknown audit message? " << message.DebugString();
}
}
void audit::handle_primary_status(const primary_status& primary_status)
{
std::lock_guard<std::mutex> lock(this->audit_lock);
if (this->recorded_primaries.count(primary_status.view()) == 0)
{
LOG(info) << "observed primary of view " << primary_status.view() << " to be '" << primary_status.primary() << "'";
this->monitor->send_counter(bzn::statistic::pbft_primary_alive);
this->recorded_primaries[primary_status.view()] = primary_status.primary();
this->trim();
}
else if (this->recorded_primaries[primary_status.view()] != primary_status.primary())
{
std::string err = str(boost::format(
"Conflicting primary detected! '%1%' is the recorded primary of view %2%, but '%3%' claims to be the primary of the same view.")
% this->recorded_primaries[primary_status.view()]
% primary_status.view()
% primary_status.primary());
this->monitor->send_counter(bzn::statistic::pbft_primary_conflict);
}
this->reset_primary_alive_timer();
}
void
audit::handle_pbft_commit(const pbft_commit_notification& commit)
{
std::lock_guard<std::mutex> lock(this->audit_lock);
this->monitor->send_counter(bzn::statistic::pbft_commit);
if (this->recorded_pbft_commits.count(commit.sequence_number()) == 0)
{
LOG(debug) << "observed that message '" << bytes_to_debug_string(commit.operation()) << "' is committed at sequence " << commit.sequence_number();
this->recorded_pbft_commits[commit.sequence_number()] = commit.operation();
this->trim();
}
else if (this->recorded_pbft_commits[commit.sequence_number()] != commit.operation())
{
std::string err = str(boost::format(
"Conflicting commit detected! '%1%' is the recorded entry at sequence %2%, but '%3%' has been committed with the same sequence.")
% this->recorded_pbft_commits[commit.sequence_number()]
% commit.sequence_number()
% commit.operation());
this->monitor->send_counter(bzn::statistic::pbft_commit_conflict);
}
}
void
audit::handle_failure_detected(const failure_detected& /*failure*/)
{
std::lock_guard<std::mutex> lock(this->audit_lock);
this->monitor->send_counter(bzn::statistic::pbft_failure_detected);
}
size_t
audit::current_memory_size()
{
return this->recorded_pbft_commits.size() + this->recorded_primaries.size();
}
void
audit::trim()
{
// Here we're removing the lowest term/log index entries, which is sort of like the oldest entries. I'd rather
// remove entries at random, but that's not straightforward to do with STL containers without making some onerous
// performance compromise.
while(this->recorded_primaries.size() > this->mem_size)
{
this->recorded_primaries.erase(this->recorded_primaries.begin());
}
while(this->recorded_pbft_commits.size() > this->mem_size)
{
this->recorded_pbft_commits.erase(this->recorded_pbft_commits.begin());
}
}
================================================
FILE: audit/audit.hpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <audit/audit_base.hpp>
#include <node/node_base.hpp>
#include <monitor/monitor_base.hpp>
#include <include/boost_asio_beast.hpp>
#include <boost/asio/ip/udp.hpp>
#include <mutex>
#include <optional>
namespace bzn
{
class audit : public audit_base, public std::enable_shared_from_this<audit>
{
public:
audit(std::shared_ptr<bzn::asio::io_context_base>
, std::shared_ptr<bzn::node_base> node
, size_t mem_size
, std::shared_ptr<bzn::monitor_base> monitor
);
void handle(const bzn_envelope& message, std::shared_ptr<bzn::session_base> session) override;
void handle_pbft_commit(const pbft_commit_notification&) override;
void handle_primary_status(const primary_status&) override;
void handle_failure_detected(const failure_detected&) override;
size_t current_memory_size();
void start() override;
private:
void handle_primary_alive_timeout(const boost::system::error_code& ec);
void reset_primary_alive_timer();
void report_error(const std::string& metric_name, const std::string& error_description);
void send_to_monitor(const std::string& stat);
void handle_leader_data(const leader_status&);
void handle_leader_made_progress(const leader_status&);
void trim();
std::list<std::string> recorded_errors;
const std::shared_ptr<bzn::node_base> node;
const std::shared_ptr<bzn::asio::io_context_base> io_context;
uint primary_dead_count = 0;
std::map<uint64_t, bzn::uuid_t> recorded_primaries;
std::map<uint64_t, std::string> recorded_pbft_commits;
std::once_flag start_once;
std::mutex audit_lock;
std::unique_ptr<bzn::asio::steady_timer_base> primary_alive_timer;
// TODO: Make this configurable
std::chrono::milliseconds primary_timeout{std::chrono::milliseconds(30000)};
size_t forgotten_error_count = 0;
size_t mem_size;
std::shared_ptr<bzn::monitor_base> monitor;
};
}
================================================
FILE: audit/audit_base.hpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <string>
#include <list>
#include <memory>
#include <include/bluzelle.hpp>
#include <node/node_base.hpp>
#include <node/session_base.hpp>
#include <proto/audit.pb.h>
namespace bzn
{
class audit_base
{
public:
virtual ~audit_base() = default;
virtual void start() = 0;
virtual void handle(const bzn_envelope& msg, std::shared_ptr<bzn::session_base> session) = 0;
virtual void handle_pbft_commit(const pbft_commit_notification&) = 0;
virtual void handle_primary_status(const primary_status&) = 0;
virtual void handle_failure_detected(const failure_detected&) = 0;
};
}
================================================
FILE: audit/test/CMakeLists.txt
================================================
set(test_srcs audit_test.cpp)
set(test_libs audit proto ${Protobuf_LIBRARIES})
add_gmock_test(audit)
================================================
FILE: audit/test/audit_test.cpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the views of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <audit/audit.hpp>
#include <mocks/mock_node_base.hpp>
#include <mocks/mock_boost_asio_beast.hpp>
#include <boost/range/irange.hpp>
#include <boost/asio/buffer.hpp>
#include <mocks/mock_monitor.hpp>
using namespace ::testing;
class audit_test : public Test
{
public:
std::shared_ptr<bzn::asio::mock_io_context_base> mock_io_context = std::make_shared<NiceMock<bzn::asio::mock_io_context_base>>();
std::shared_ptr<bzn::mock_node_base> mock_node = std::make_shared<NiceMock<bzn::mock_node_base>>();
std::unique_ptr<bzn::asio::mock_steady_timer_base> primary_alive_timer =
std::make_unique<NiceMock<bzn::asio::mock_steady_timer_base>>();
bzn::asio::wait_handler primary_alive_timer_callback;
std::shared_ptr<bzn::mock_monitor> mock_monitor = std::make_shared<StrictMock<bzn::mock_monitor>>();
std::shared_ptr<bzn::audit> audit;
size_t mem_size = 1000;
audit_test()
{
EXPECT_CALL(*(this->mock_io_context), make_unique_steady_timer())
.WillOnce(Invoke(
[&](){return std::move(this->primary_alive_timer);}
));
EXPECT_CALL(*(this->primary_alive_timer), async_wait(_))
.WillRepeatedly(Invoke(
[&](auto handler){this->primary_alive_timer_callback = handler;}
));
}
void build_audit()
{
// We cannot construct this during our constructor because doing so invalidates our timer pointers,
// which prevents tests from setting expectations on them
this->audit = std::make_shared<bzn::audit>(this->mock_io_context, this->mock_node, this->mem_size, this->mock_monitor);
this->audit->start();
}
};
TEST_F(audit_test, audit_throws_error_when_primaries_conflict)
{
this->build_audit();
primary_status a, b, c;
a.set_primary("fred");
a.set_view(1);
b.set_primary("smith");
b.set_view(2);
c.set_primary("francheskitoria");
c.set_view(1);
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_primary_alive, 1)).Times(AnyNumber());
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_primary_conflict, 1));
this->audit->handle_primary_status(a);
this->audit->handle_primary_status(b);
this->audit->handle_primary_status(c);
this->audit->handle_primary_status(b);
}
TEST_F(audit_test, audit_throws_error_when_pbft_commits_conflict)
{
this->build_audit();
pbft_commit_notification a, b, c;
a.set_operation("do something");
a.set_sequence_number(1);
b.set_operation("do a different thing");
b.set_sequence_number(2);
c.set_operation("do something else");
c.set_sequence_number(1);
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_commit, 1)).Times(AnyNumber());
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_commit_conflict, 1));
this->audit->handle_pbft_commit(a);
this->audit->handle_pbft_commit(b);
this->audit->handle_pbft_commit(c);
this->audit->handle_pbft_commit(b);
}
TEST_F(audit_test, audit_throws_error_when_no_primary_alive)
{
EXPECT_CALL(*(this->primary_alive_timer), expires_from_now(_)).Times(AtLeast(1));
this->build_audit();
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_no_primary, 1));
this->primary_alive_timer_callback(boost::system::error_code());
}
TEST_F(audit_test, audit_resets_primary_alive_on_message)
{
bool reset;
EXPECT_CALL(*(this->primary_alive_timer), cancel()).WillRepeatedly(Invoke(
[&](){reset = true;}
));
this->build_audit();
primary_status ls1;
ls1.set_primary("fred");
reset = false;
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_primary_alive, 1)).Times(AnyNumber());
this->audit->handle_primary_status(ls1);
EXPECT_TRUE(reset);
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_no_primary, 1));
this->primary_alive_timer_callback(boost::system::error_code());
}
TEST_F(audit_test, audit_forgets_old_data)
{
this->mem_size = 10;
this->build_audit();
primary_status ls1;
ls1.set_primary("joe");
primary_status ls2;
ls2.set_primary("alfred");
pbft_commit_notification com;
com.set_operation("Do some stuff!!");
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_commit, 1)).Times(AnyNumber());
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_primary_alive, 1)).Times(AnyNumber());
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_primary_conflict, 1)).Times(Exactly(100));
for(auto i : boost::irange(0, 100))
{
// Trigger an error, a primary elected, and a commit notification every iteration
ls1.set_view(i);
ls2.set_view(i);
com.set_sequence_number(i);
this->audit->handle_primary_status(ls1);
this->audit->handle_primary_status(ls2);
this->audit->handle_pbft_commit(com);
}
// It's allowed to have mem size each of commits, primaries, and
EXPECT_LE(this->audit->current_memory_size(), 2*this->mem_size);
}
TEST_F(audit_test, audit_still_detects_new_errors_after_forgetting_old_data)
{
this->mem_size = 10;
this->build_audit();
primary_status ls1;
ls1.set_primary("joe");
pbft_commit_notification com;
com.set_operation("do exciting things and stuff");
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_commit, 1)).Times(AnyNumber());
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_primary_alive, 1)).Times(AnyNumber());
for (auto i : boost::irange(0, 100))
{
ls1.set_view(i);
com.set_sequence_number(i);
this->audit->handle_primary_status(ls1);
this->audit->handle_pbft_commit(com);
}
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_commit_conflict, 1));
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_primary_conflict, 1));
ls1.set_primary("not joe");
com.set_operation("don't do anything");
this->audit->handle_primary_status(ls1);
this->audit->handle_pbft_commit(com);
}
TEST_F(audit_test, audit_sends_monitor_message_when_primary_conflict)
{
this->build_audit();
primary_status ls1;
ls1.set_primary("joe");
primary_status ls2 = ls1;
ls2.set_primary("francine");
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_primary_alive, 1)).Times(AnyNumber());
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_primary_conflict, 1));
this->audit->handle_primary_status(ls1);
this->audit->handle_primary_status(ls2);
}
TEST_F(audit_test, audit_sends_monitor_message_when_commit_conflict)
{
this->build_audit();
pbft_commit_notification com1;
com1.set_sequence_number(2);
com1.set_operation("the first thing");
pbft_commit_notification com2 = com1;
com2.set_operation("the second thing");
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_commit, 1)).Times(AnyNumber());
EXPECT_CALL(*(this->mock_monitor), send_counter(bzn::statistic::pbft_commit_conflict, 1));
this->audit->handle_pbft_commit(com1);
this->audit->handle_pbft_commit(com2);
}
================================================
FILE: chaos/CMakeLists.txt
================================================
add_library(chaos
chaos.hpp
chaos.cpp
chaos_base.hpp
)
target_link_libraries(chaos options)
target_include_directories(chaos PRIVATE ${BLUZELLE_STD_INCLUDES})
add_dependencies(chaos boost openssl)
add_subdirectory(test)
================================================
FILE: chaos/chaos.cpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <random>
#include <boost/format.hpp>
#include <chaos/chaos.hpp>
#include <options/simple_options.hpp>
#include <include/boost_asio_beast.hpp>
#include <include/bluzelle.hpp>
using namespace bzn;
using namespace bzn::option_names;
chaos::chaos(std::shared_ptr<bzn::asio::io_context_base> io_context, std::shared_ptr<bzn::options_base> options)
: io_context(std::move(io_context))
, options(std::move(options))
, crash_timer(this->io_context->make_unique_steady_timer())
{
// We don't need cryptographically secure randomness here, but it does need to be of reasonable quality and differ across processes
std::random_device rd;
this->random.seed(rd());
}
void
chaos::start()
{
if (this->enabled())
{
std::call_once(
this->start_once,
[this]()
{
this->start_crash_timer();
}
);
}
}
void
chaos::start_crash_timer()
{
std::weibull_distribution<double> distribution(
this->options->get_simple_options().get<double>(CHAOS_NODE_FAILURE_SHAPE),
this->options->get_simple_options().get<double>(CHAOS_NODE_FAILURE_SCALE));
double hours_until_crash = distribution(this->random);
LOG(info) << boost::format("Chaos module will trigger this node crashing in %1$.2f hours") % hours_until_crash;
auto time_until_crash = std::chrono::duration<double, std::chrono::hours::period>(hours_until_crash);
this->crash_timer->expires_from_now(std::chrono::duration_cast<std::chrono::milliseconds>(time_until_crash));
// Doing this with this timer means that crashes will only occur at times where boost schedules
// a new callback to take place, rather than truly at random.
this->crash_timer->async_wait(std::bind(&chaos::handle_crash_timer, shared_from_this(), std::placeholders::_1));
}
void
chaos::handle_crash_timer(const boost::system::error_code& /*ec*/)
{
LOG(fatal) << "Chaos module triggering node crash";
// Intentionally crashing abruptly
std::abort();
}
bool
chaos::enabled()
{
return this->options->get_simple_options().get<bool>(CHAOS_ENABLED);
}
bool
chaos::is_message_delayed()
{
const bool result = this->enabled() &&
this->options->get_simple_options().get<double>(CHAOS_MESSAGE_DELAY_CHANCE) > this->random_float(this->random);
if (result)
{
LOG(debug) << "Chaos module delaying message";
}
return result;
}
bool
chaos::is_message_dropped()
{
bool result = this->enabled() &&
this->options->get_simple_options().get<double>(CHAOS_MESSAGE_DROP_CHANCE) > this->random_float(this->random);
if (result)
{
LOG(debug) << "Chaos module dropping message";
}
return result;
}
void
chaos::reschedule_message(chaos_delay_callback callback) const
{
std::shared_ptr<bzn::asio::steady_timer_base> timer = this->io_context->make_unique_steady_timer();
auto delay = std::chrono::milliseconds(this->options->get_simple_options().get<uint>(CHAOS_MESSAGE_DELAY_TIME));
timer->expires_from_now(delay);
timer->async_wait(
[timer, callback](auto /*error*/)
{
LOG(debug) << "Chaos module retrying delayed message";
callback();
});
}
================================================
FILE: chaos/chaos.hpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <mutex>
#include <options/options_base.hpp>
#include <include/boost_asio_beast.hpp>
#include <chaos/chaos_base.hpp>
#include <random>
namespace bzn
{
class chaos : public chaos_base, public std::enable_shared_from_this<chaos>
{
public:
chaos(std::shared_ptr<bzn::asio::io_context_base> io_context, std::shared_ptr<bzn::options_base> options);
void start() override;
bool is_message_dropped() override;
bool is_message_delayed() override;
void reschedule_message(chaos_delay_callback callback) const override;
private:
void start_crash_timer();
void handle_crash_timer(const boost::system::error_code&);
bool enabled();
std::once_flag start_once;
const std::shared_ptr<bzn::asio::io_context_base> io_context;
const std::shared_ptr<bzn::options_base> options;
std::unique_ptr<bzn::asio::steady_timer_base> crash_timer;
std::mt19937 random;
std::uniform_real_distribution<> random_float{0.0, 1.0};
};
}
================================================
FILE: chaos/chaos_base.hpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <functional>
namespace bzn
{
class chaos_base
{
public:
/*
* start the node death timer (if enabled)
*/
virtual void start() = 0;
/*
* Randomly determine if a message should be dropped, according to settings
*/
virtual bool is_message_dropped() = 0;
/*
* Randomly determine if a message should be delayed, according to settings
*/
virtual bool is_message_delayed() = 0;
using chaos_delay_callback = std::function<void()>;
/*
* Schedule a delayed callback according to settings
* @param callback callback for sending message when delay expires
*/
virtual void reschedule_message(chaos_delay_callback callback) const = 0;
virtual ~chaos_base() = default;
};
}
================================================
FILE: chaos/test/CMakeLists.txt
================================================
set(test_srcs chaos_test.cpp)
set(test_libs chaos options)
add_gmock_test(chaos)
================================================
FILE: chaos/test/chaos_test.cpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <chaos/chaos.hpp>
#include <mocks/mock_boost_asio_beast.hpp>
#include <gtest/gtest.h>
#include <options/options.hpp>
using namespace ::testing;
class chaos_test : public Test
{
public:
std::shared_ptr<bzn::options> options;
std::shared_ptr<bzn::asio::mock_io_context_base> mock_io_context = std::make_shared<NiceMock<bzn::asio::mock_io_context_base>>();
std::unique_ptr<bzn::asio::mock_steady_timer_base> node_crash_timer =
std::make_unique<NiceMock<bzn::asio::mock_steady_timer_base>>();
std::unique_ptr<bzn::asio::mock_steady_timer_base> second_timer =
std::make_unique<NiceMock<bzn::asio::mock_steady_timer_base>>();
bzn::asio::wait_handler node_crash_handler;
bzn::asio::wait_handler second_timer_handler;
std::shared_ptr<bzn::chaos> chaos;
size_t timer_waited = 0;
// This pattern copied from audit test
chaos_test()
{
EXPECT_CALL(*(this->mock_io_context), make_unique_steady_timer())
.Times(AnyNumber())
.WillOnce(Invoke(
[&](){return std::move(this->node_crash_timer);}
)).WillOnce(Invoke(
[&](){return std::move(this->second_timer);}
));
EXPECT_CALL(*(this->node_crash_timer), async_wait(_))
.Times(AnyNumber())
.WillRepeatedly(Invoke(
[&](auto handler)
{
this->node_crash_handler = handler;
this->timer_waited++;
}
));
EXPECT_CALL(*(this->second_timer), async_wait(_))
.Times(AnyNumber())
.WillRepeatedly(Invoke(
[&](auto handler)
{
this->second_timer_handler = handler;
}
));
this->options = std::make_shared<bzn::options>();
this->options->get_mutable_simple_options().set(bzn::option_names::CHAOS_ENABLED, "true");
this->options->get_mutable_simple_options().set(bzn::option_names::CHAOS_MESSAGE_DELAY_CHANCE, "0.5");
this->options->get_mutable_simple_options().set(bzn::option_names::CHAOS_MESSAGE_DROP_CHANCE, "0.5");
}
void build_chaos()
{
this->chaos = std::make_shared<bzn::chaos>(this->mock_io_context, this->options);
this->chaos->start();
}
};
using chaos_test_DeathTest = chaos_test; // https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#death-test-naming
TEST_F(chaos_test_DeathTest, test_crash_scheduled_and_executed)
{
this->build_chaos();
EXPECT_EQ(this->timer_waited, 1u);
ASSERT_DEATH(this->node_crash_handler(boost::system::error_code()), "");
}
TEST_F(chaos_test, test_messages_never_dropped_or_delayed_when_disabled)
{
this->build_chaos();
this->options->get_mutable_simple_options().set(bzn::option_names::CHAOS_ENABLED, "false");
for (int i=0; i<10000; i++)
{
ASSERT_FALSE(this->chaos->is_message_dropped());
ASSERT_FALSE(this->chaos->is_message_delayed());
}
}
TEST_F(chaos_test, test_messages_sometimes_dropped_or_delayed_sometimes_not)
{
this->build_chaos();
uint dropped_count = 0;
uint delayed_count = 0;
uint not_dropped_count = 0;
uint not_delayed_count = 0;
for (int i=0; i<10000; i++)
{
if (this->chaos->is_message_dropped())
{
dropped_count ++;
}
else
{
not_dropped_count ++;
}
if (this->chaos->is_message_delayed())
{
delayed_count++;
}
else
{
not_delayed_count++;
}
if (dropped_count>0 && not_dropped_count>0 && delayed_count>0 && not_delayed_count>0)
{
return;
}
}
FAIL();
}
TEST_F(chaos_test, reschedule_retries_message)
{
this->build_chaos();
bool called = false;
this->chaos->reschedule_message([&](){called = true;});
this->second_timer_handler(boost::system::error_code());
ASSERT_TRUE(called);
}
================================================
FILE: cmake/add_gmock_test.cmake
================================================
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
include(GoogleTest)
function(add_gmock_test target)
set(target ${target}_tests)
add_executable(${target} ${test_srcs})
add_dependencies(${target} boost googletest jsoncpp ${test_deps})
target_link_libraries(${target} ${test_libs} ${OPENSSL_LIBRARIES} ${GMOCK_BOTH_LIBRARIES} ${Boost_LIBRARIES} ${JSONCPP_LIBRARIES} ${test_link} pthread)
target_include_directories(${target} PRIVATE ${BLUZELLE_STD_INCLUDES})
gtest_discover_tests(${target})
unset(test_srcs)
unset(test_libs)
unset(test_deps)
unset(test_link)
endfunction()
================================================
FILE: cmake/boost.cmake
================================================
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
include(ExternalProject)
include(ProcessorCount)
set(REQUIRED_BOOST "1.70.0")
set(BOOST_URL_HASH "882b48708d211a5f48e60b0124cf5863c1534cd544ecd0664bb534a4b5d506e9")
message(STATUS "Boost: ${REQUIRED_BOOST}")
set(BOOST_TARBALL "boost_${REQUIRED_BOOST}")
string(REPLACE "." "_" BOOST_TARBALL ${BOOST_TARBALL})
string(APPEND BOOST_TARBALL ".tar.gz")
set(BOOST_LIBS "chrono,program_options,random,regex,system,thread,log,serialization")
# Prevent travis gcc crashes...
if (DEFINED ENV{TRAVIS})
set(BUILD_FLAGS -j8)
else()
ProcessorCount(N)
if(NOT N EQUAL 0)
set(BUILD_FLAGS -j${N})
endif()
endif()
ExternalProject_Add(boost
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/boost"
URL "https://dl.bintray.com/boostorg/release/${REQUIRED_BOOST}/source/${BOOST_TARBALL}"
URL_HASH SHA256=${BOOST_URL_HASH}
TIMEOUT 120
INSTALL_COMMAND ""
CONFIGURE_COMMAND "${CMAKE_CURRENT_BINARY_DIR}/boost/src/boost/bootstrap.sh" "--with-libraries=${BOOST_LIBS}"
BUILD_COMMAND "${CMAKE_CURRENT_BINARY_DIR}/boost/src/boost/b2" link=static visibility=global "${BUILD_FLAGS} "
BUILD_IN_SOURCE true
DOWNLOAD_NO_PROGRESS true
)
set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM ${CMAKE_CURRENT_BINARY_DIR}/boost)
ExternalProject_Get_Property(boost source_dir)
set(Boost_INCLUDE_DIRS ${source_dir})
set(Boost_LIBRARIES
${source_dir}/stage/lib/libboost_log.a
${source_dir}/stage/lib/libboost_program_options.a
${source_dir}/stage/lib/libboost_system.a
${source_dir}/stage/lib/libboost_thread.a
pthread
${source_dir}/stage/lib/libboost_serialization.a
${source_dir}/stage/lib/libboost_date_time.a
${source_dir}/stage/lib/libboost_log_setup.a
${source_dir}/stage/lib/libboost_filesystem.a
${source_dir}/stage/lib/libboost_regex.a
${source_dir}/stage/lib/libboost_chrono.a
${source_dir}/stage/lib/libboost_atomic.a
)
================================================
FILE: cmake/git_commit.cmake
================================================
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
set(SWARM_GIT_COMMIT "unknown")
find_program(GIT_EXECUTABLE NAMES git)
if (GIT_EXECUTABLE)
execute_process(COMMAND git describe --always --tags --dirty OUTPUT_VARIABLE SWARM_GIT_COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
endif()
configure_file(${CMAKE_CURRENT_LIST_DIR}/swarm_git_commit.hpp.in ${PROJECT_BINARY_DIR}/swarm_git_commit.hpp.tmp)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/swarm_git_commit.hpp.tmp ${PROJECT_BINARY_DIR}/swarm_git_commit.hpp)
execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${PROJECT_BINARY_DIR}/swarm_git_commit.hpp.tmp)
================================================
FILE: cmake/googletest.cmake
================================================
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
include(ExternalProject)
ExternalProject_Add(googletest
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/googletest"
URL https://github.com/google/googletest/archive/release-1.8.0.tar.gz
URL_HASH SHA256=58a6f4277ca2bc8565222b3bbd58a177609e9c488e8a72649359ba51450db7d8
TIMEOUT 30
INSTALL_COMMAND ""
DOWNLOAD_NO_PROGRESS true
)
set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM
"${CMAKE_CURRENT_BINARY_DIR}/googletest")
ExternalProject_Get_Property(googletest source_dir)
include_directories(${source_dir}/googlemock/include ${source_dir}/googletest/include)
ExternalProject_Get_Property(googletest binary_dir)
link_directories(${binary_dir}/googlemock)
set(GMOCK_BOTH_LIBRARIES gmock_main gmock)
================================================
FILE: cmake/jsoncpp.cmake
================================================
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
include(ExternalProject)
ExternalProject_Add(jsoncpp
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/jsoncpp"
URL https://github.com/open-source-parsers/jsoncpp/archive/1.8.4.tar.gz
URL_HASH SHA256=c49deac9e0933bcb7044f08516861a2d560988540b23de2ac1ad443b219afdb6
TIMEOUT 30
INSTALL_COMMAND ""
CMAKE_ARGS -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF -DJSONCPP_WITH_TESTS=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
DOWNLOAD_NO_PROGRESS true
)
set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM
"${CMAKE_CURRENT_BINARY_DIR}/jsoncpp")
ExternalProject_Get_Property(jsoncpp source_dir)
set(JSONCPP_INCLUDE_DIRS ${source_dir}/include)
include_directories(${JSONCPP_INCLUDE_DIRS})
ExternalProject_Get_Property(jsoncpp binary_dir)
link_directories(${binary_dir}/src/lib_json/)
set(JSONCPP_LIBRARIES ${binary_dir}/src/lib_json/libjsoncpp.a)
================================================
FILE: cmake/openssl.cmake
================================================
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
include(ExternalProject)
include(ProcessorCount)
# Prevent travis gcc crashes...
if (DEFINED ENV{TRAVIS})
set(BUILD_FLAGS -j8)
else()
ProcessorCount(N)
if(NOT N EQUAL 0)
set(BUILD_FLAGS -j${N})
endif()
endif()
# platform detection
if (APPLE)
set(OPENSSL_BUILD_PLATFORM darwin64-x86_64-cc)
else()
set(OPENSSL_BUILD_PLATFORM linux-x86_64)
endif()
ExternalProject_Add(openssl
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/openssl"
URL https://www.openssl.org/source/openssl-1.1.1.tar.gz
URL_HASH SHA256=2836875a0f89c03d0fdf483941512613a50cfb421d6fd94b9f41d7279d586a3d
TIMEOUT 30
INSTALL_COMMAND ""
DOWNLOAD_NO_PROGRESS true
CONFIGURE_COMMAND "${CMAKE_CURRENT_BINARY_DIR}/openssl/src/openssl/Configure" ${OPENSSL_BUILD_PLATFORM}
BUILD_COMMAND make ${BUILD_FLAGS}
)
set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM
"${CMAKE_CURRENT_BINARY_DIR}/openssl")
ExternalProject_Get_Property(openssl source_dir)
ExternalProject_Get_Property(openssl binary_dir)
set(OPENSSL_INCLUDE_DIR ${source_dir}/include ${binary_dir}/include)
set(OPENSSL_LIBRARIES ${binary_dir}/libcrypto.a ${binary_dir}/libssl.a dl pthread)
================================================
FILE: cmake/rocksdb.cmake
================================================
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
include(ExternalProject)
include(ProcessorCount)
include(FindZLIB)
# find snappy...
find_path(SNAPPY_INCLUDE_DIR
NAMES snappy.h
HINTS ${SNAPPY_ROOT_DIR}/include)
find_library(SNAPPY_LIBRARIES
NAMES snappy
HINTS ${SNAPPY_ROOT_DIR}/lib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Snappy DEFAULT_MSG
SNAPPY_LIBRARIES
SNAPPY_INCLUDE_DIR)
mark_as_advanced(
SNAPPY_ROOT_DIR
SNAPPY_LIBRARIES
SNAPPY_INCLUDE_DIR)
# find bzip2...
find_path(BZIP2_INCLUDE_DIR
NAMES bzlib.h
HINTS ${BZIP2_ROOT_DIR}/include)
find_library(BZIP2_LIBRARIES
NAMES bz2
HINTS ${BZIP2_ROOT_DIR}/lib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Bzip2 DEFAULT_MSG
BZIP2_LIBRARIES
BZIP2_INCLUDE_DIR)
mark_as_advanced(
BZIP2_ROOT_DIR
BZIP2_LIBRARIES
BZIP2_INCLUDE_DIR)
# Prevent travis gcc crashes...
if (DEFINED ENV{TRAVIS})
set(BUILD_FLAGS -j8)
else()
ProcessorCount(N)
if(NOT N EQUAL 0)
set(BUILD_FLAGS -j${N})
endif()
endif()
ExternalProject_Add(rocksdb
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/rocksdb"
URL https://github.com/facebook/rocksdb/archive/v5.14.3.tar.gz
URL_HASH SHA256=c7019a645fc23df0adfe97ef08e793a36149bff2f57ef3b6174cbb0c8c9867b1
TIMEOUT 30
INSTALL_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND PORTABLE=1 make -e DISABLE_JEMALLOC=1 static_lib ${BUILD_FLAGS}
BUILD_IN_SOURCE true
DOWNLOAD_NO_PROGRESS true
)
set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM
"${CMAKE_CURRENT_BINARY_DIR}/rocksdb")
ExternalProject_Get_Property(rocksdb source_dir)
set(ROCKSDB_INCLUDE_DIRS ${source_dir}/include)
ExternalProject_Get_Property(rocksdb binary_dir)
link_directories(${binary_dir}/)
set(ROCKSDB_LIBRARIES ${binary_dir}/librocksdb.a ${SNAPPY_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES})
if (APPLE)
find_library(LZ4_LIBRARY NAMES liblz4.a)
message(STATUS ${LZ4_LIBRARY})
list(APPEND ROCKSDB_LIBRARIES ${LZ4_LIBRARY})
# rocksdb may of found these libraries...
find_library(ZSTD_LIBRARY NAMES libzstd.a)
if (ZSTD_LIBRARY)
message(STATUS ${ZSTD_LIBRARY})
list(APPEND ROCKSDB_LIBRARIES ${ZSTD_LIBRARY})
endif()
find_library(TBB_LIBRARY NAMES libtbb.a)
if (TBB_LIBRARY)
message(STATUS ${TBB_LIBRARY})
list(APPEND ROCKSDB_LIBRARIES ${TBB_LIBRARY})
endif()
endif()
================================================
FILE: cmake/static_analysis.cmake
================================================
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
add_custom_target(static_analysis)
# copy paste detection...
if (NOT DEFINED "PMD_EXE")
find_program(PMD_EXE NAMES pmd run.sh)
endif()
message(STATUS "pmd: ${PMD_EXE}")
if (PMD_EXE)
add_custom_target(cpd COMMAND ${CMAKE_SOURCE_DIR}/cmake/static_analysis.sh cpd ${PMD_EXE} ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
add_dependencies(static_analysis cpd)
endif()
# complexity analysis...
find_program(PMCCABE_EXE NAMES pmccabe)
message(STATUS "pmccabe: ${PMCCABE_EXE}")
if (PMCCABE_EXE)
add_custom_target(pmccabe COMMAND ${CMAKE_SOURCE_DIR}/cmake/static_analysis.sh pmccabe ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
add_dependencies(static_analysis pmccabe)
endif()
================================================
FILE: cmake/static_analysis.sh
================================================
#!/usr/bin/env bash
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# set -x
TEMP_FILE=$(mktemp)
case "$1" in
cpd)
find "$3" -not \( -path "$4" -prune \) -name "*.cpp" -not -name "*_test.cpp" -o -name "*.hpp" > $TEMP_FILE
$2 cpd --minimum-tokens 115 --language cpp --filelist $TEMP_FILE
;;
pmccabe)
echo "Modified McCabe Cyclomatic Complexity"
echo "| Traditional McCabe Cyclomatic Complexity"
echo "| | # Statements in function"
echo "| | | First line of function"
echo "| | | | # lines in function"
echo "| | | | | filename(definition line number):function"
echo "| | | | | |"
pmccabe $(find "$2" -not \( -path "$3" -prune \) -name "*.cpp" -not -name "*_test.cpp" -o -name "*.hpp") 2> $TEMP_FILE | sort -nr
echo "-----------------------------------------------------------------------------"
echo Parse errors:
echo
cat $TEMP_FILE
;;
esac
rm $TEMP_FILE
================================================
FILE: cmake/swarm_git_commit.hpp.in
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#define SWARM_GIT_COMMIT "@SWARM_GIT_COMMIT@"
================================================
FILE: cmake/swarm_version.cmake
================================================
# Copyright (C) 2018 Bluzelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# version for swarm
set(PROJECT_VERSION_MAJOR 0 CACHE STRING "Set the project major version")
set(PROJECT_VERSION_MINOR 0 CACHE STRING "Set the project minor version")
set(PROJECT_VERSION_PATCH "0-desk" CACHE STRING "Set the project patch version")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" CACHE STRING "")
================================================
FILE: cmake/swarm_version.hpp.in
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#define SWARM_VERSION "@PROJECT_VERSION@"
================================================
FILE: crud/CMakeLists.txt
================================================
add_library(crud STATIC
crud_base.hpp
subscription_manager.cpp
subscription_manager.hpp
subscription_manager_base.hpp
crud.cpp
crud.hpp
)
target_link_libraries(crud proto policy)
add_dependencies(crud boost jsoncpp openssl)
target_include_directories(crud PRIVATE ${BLUZELLE_STD_INCLUDES})
add_subdirectory(test)
================================================
FILE: crud/crud.cpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <crud/crud.hpp>
#include <policy/random.hpp>
#include <policy/volatile_ttl.hpp>
#include <utils/make_endpoint.hpp>
#include <functional>
#include <boost/algorithm/string/trim_all.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>
using namespace bzn;
using namespace std::placeholders;
namespace
{
const std::string PERMISSION_UUID{"PERMS"};
const std::string OWNER_KEY{"OWNER"};
const std::string WRITERS_KEY{"WRITERS"};
const std::string MAX_SIZE_KEY{"MAX_SIZE"};
const std::string EVICTION_POLICY_KEY{"EVICTION_POLICY"};
const std::string TTL_UUID{"TTL"};
const std::chrono::seconds TTL_TICK{5}; // not too aggressive
inline bzn::key_t generate_expire_key(const bzn::uuid_t& uuid, const bzn::key_t& key)
{
Json::Value value;
value["uuid"] = uuid;
value["key"] = key;
return value.toStyledString();
}
inline std::pair<bzn::uuid_t, bzn::key_t> extract_uuid_key(const bzn::key_t& key)
{
Json::CharReaderBuilder rbuilder;
std::unique_ptr<Json::CharReader> const reader(rbuilder.newCharReader());
std::string parse_errors;
Json::Value json;
if (!reader->parse(key.c_str(), key.c_str() + key.size(), &json, &parse_errors))
{
throw std::runtime_error("Failed to parse database json ttl data: " + parse_errors);
}
return std::make_pair(json["uuid"].asString(), json["key"].asString());
}
}
crud::crud(std::shared_ptr<bzn::asio::io_context_base> io_context,
std::shared_ptr<bzn::storage_base> storage,
std::shared_ptr<bzn::subscription_manager_base> subscription_manager,
std::shared_ptr<bzn::node_base> node, bzn::key_t owner_public_key)
: storage(std::move(storage))
, subscription_manager(std::move(subscription_manager))
, node(std::move(node))
, expire_timer(io_context->make_unique_steady_timer())
, message_handlers{
{database_msg::kCreate, std::bind(&crud::handle_create, this, _1, _2, _3)},
{database_msg::kRead, std::bind(&crud::handle_read, this, _1, _2, _3)},
{database_msg::kUpdate, std::bind(&crud::handle_update, this, _1, _2, _3)},
{database_msg::kDelete, std::bind(&crud::handle_delete, this, _1, _2, _3)},
{database_msg::kHas, std::bind(&crud::handle_has, this, _1, _2, _3)},
{database_msg::kKeys, std::bind(&crud::handle_keys, this, _1, _2, _3)},
{database_msg::kSize, std::bind(&crud::handle_size, this, _1, _2, _3)},
{database_msg::kSubscribe, std::bind(&crud::handle_subscribe, this, _1, _2, _3)},
{database_msg::kUnsubscribe, std::bind(&crud::handle_unsubscribe, this, _1, _2, _3)},
{database_msg::kCreateDb, std::bind(&crud::handle_create_db, this, _1, _2, _3)},
{database_msg::kUpdateDb, std::bind(&crud::handle_update_db, this, _1, _2, _3)},
{database_msg::kDeleteDb, std::bind(&crud::handle_delete_db, this, _1, _2, _3)},
{database_msg::kHasDb, std::bind(&crud::handle_has_db, this, _1, _2, _3)},
{database_msg::kWriters, std::bind(&crud::handle_writers, this, _1, _2, _3)},
{database_msg::kAddWriters, std::bind(&crud::handle_add_writers, this, _1, _2, _3)},
{database_msg::kRemoveWriters, std::bind(&crud::handle_remove_writers, this, _1, _2, _3)},
{database_msg::kQuickRead, std::bind(&crud::handle_read, this, _1, _2, _3)},
{database_msg::kTtl, std::bind(&crud::handle_ttl, this, _1, _2, _3)},
{database_msg::kPersist, std::bind(&crud::handle_persist, this, _1, _2, _3)},
{database_msg::kExpire, std::bind(&crud::handle_expire, this, _1, _2, _3)}}
, owner_public_key(std::move(owner_public_key))
{
}
void
crud::start(std::shared_ptr<bzn::pbft_base> pbft, const size_t max_swarm_storage)
{
std::call_once(this->start_once,
[this, pbft, max_swarm_storage]()
{
this->pbft = std::move(pbft);
this->max_swarm_storage = max_swarm_storage;
this->subscription_manager->start();
this->expire_timer->expires_from_now(TTL_TICK);
this->expire_timer->async_wait(std::bind(&crud::check_key_expiration, shared_from_this(), std::placeholders::_1));
});
}
void
crud::handle_request(const bzn::caller_id_t& caller_id, const database_msg& request, const std::shared_ptr<bzn::session_base> session)
{
if (auto it = this->message_handlers.find(request.msg_case()); it != this->message_handlers.end())
{
LOG(debug) << "processing message: " << uint32_t(request.msg_case());
it->second(caller_id, request, session);
return;
}
LOG(error) << "unknown request: " << uint32_t(request.msg_case());
}
void
crud::send_response(const database_msg& request, const bzn::storage_result result,
database_response&& response, std::shared_ptr<bzn::session_base>& session)
{
*response.mutable_header() = request.header();
if (result != bzn::storage_result::ok)
{
if (bzn::storage_result_msg.count(result))
{
// special response error case...
if (request.msg_case() == database_msg::kQuickRead)
{
response.mutable_quick_read()->set_error(bzn::storage_result_msg.at(result));
}
else
{
response.mutable_error()->set_message(bzn::storage_result_msg.at(result));
}
}
else
{
LOG(error) << "unknown error code: " << uint32_t(result);
}
}
bzn_envelope env;
env.set_database_response(response.SerializeAsString());
if (session)
{
// special response case that does not require signing...
if (request.msg_case() == database_msg::kQuickRead)
{
session->send_message(std::make_shared<bzn::encoded_message >(env.SerializeAsString()));
}
else
{
LOG(trace) << "Sending response via session";
session->send_signed_message(std::make_shared<bzn_envelope>(env));
}
}
else
{
LOG(warning) << "session not set - response for the " << uint32_t(request.msg_case()) << " operation not sent via session";
}
if (this->node && !response.header().point_of_contact().empty())
{
LOG(trace) << "Sending response via PoC: " << response.header().point_of_contact();
try
{
this->node->send_signed_message(response.header().point_of_contact(), std::make_shared<bzn_envelope>(env));
}
catch(const std::runtime_error& err)
{
LOG(error) << err.what();
}
}
else
{
LOG(warning) << "Unable to send response for the " << uint32_t(request.msg_case()) << " operation to point of contact - node not set in crud module";
}
}
void
crud::handle_create(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::db_not_found};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (db_exists)
{
if (!this->is_caller_a_writer(caller_id, perms))
{
result = bzn::storage_result::access_denied;
}
else
{
// bail on key value pairs that are too large right away!
if (this->max_database_size(perms) && request.create().key().length() + request.create().value().length() > this->max_database_size(perms))
{
this->send_response(request, bzn::storage_result::value_too_large, database_response(), session);
return;
}
if (this->expired(request.header().db_uuid(), request.create().key()))
{
this->send_response(request, bzn::storage_result::delete_pending, database_response(), session);
return;
}
if (this->operation_exceeds_available_space(request, perms))
{
if (!this->do_eviction(request, this->max_database_size(perms)))
{
this->send_response(request, bzn::storage_result::db_full, database_response(), session);
return;
}
}
result = this->storage->create(request.header().db_uuid(), request.create().key(), request.create().value());
if (result == bzn::storage_result::ok)
{
this->update_expiration_entry(generate_expire_key(request.header().db_uuid(), request.create().key()),
request.create().expire());
this->subscription_manager->inspect_commit(request);
}
}
}
this->send_response(request, result, database_response(), session);
}
void
crud::handle_read(const bzn::caller_id_t& /*caller_id*/, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
std::shared_lock<std::shared_mutex> lock(this->crud_lock); // lock for read access
if (!this->storage->has(PERMISSION_UUID, request.header().db_uuid()))
{
this->send_response(request, bzn::storage_result::db_not_found, database_response(), session);
return;
}
const bzn::key_t key = (request.msg_case() == database_msg::kRead) ? request.read().key() : request.quick_read().key();
// expired?
if (this->expired(request.header().db_uuid(), key))
{
this->send_response(request, bzn::storage_result::delete_pending, database_response(), session);
return;
}
const auto result = this->storage->read(request.header().db_uuid(), key);
database_response response;
if (result)
{
if (request.msg_case() == database_msg::kRead)
{
response.mutable_read()->set_key(key);
response.mutable_read()->set_value(*result);
}
else
{
response.mutable_quick_read()->set_key(key);
response.mutable_quick_read()->set_value(*result);
}
}
this->send_response(request, (result) ? bzn::storage_result::ok : bzn::storage_result::not_found, std::move(response), session);
}
void
crud::handle_update(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::db_not_found};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
const auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (db_exists)
{
if (!this->is_caller_a_writer(caller_id, perms))
{
result = bzn::storage_result::access_denied;
}
else
{
// bail on key value pairs that are too large right away!
if (this->max_database_size(perms) && request.create().key().length() + request.create().value().length() > this->max_database_size(perms))
{
this->send_response(request, bzn::storage_result::value_too_large, database_response(), session);
return;
}
// expired?
if (this->expired(request.header().db_uuid(), request.update().key()))
{
this->send_response(request, bzn::storage_result::delete_pending, database_response(), session);
return;
}
if (this->operation_exceeds_available_space(request, perms))
{
// let's try evicting some key/value pairs
if (!this->do_eviction(request, this->max_database_size(perms)))
{
this->send_response(request, bzn::storage_result::db_full, database_response(), session);
return;
}
}
result = this->storage->update(request.header().db_uuid(), request.update().key(), request.update().value());
if (result == bzn::storage_result::ok)
{
this->update_expiration_entry(generate_expire_key(request.header().db_uuid(), request.update().key()), request.update().expire());
this->subscription_manager->inspect_commit(request);
}
}
}
this->send_response(request, result, database_response(), session);
}
void
crud::handle_delete(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::db_not_found};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
const auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (db_exists)
{
if (!this->is_caller_a_writer(caller_id, perms))
{
result = bzn::storage_result::access_denied;
}
else
{
result = this->storage->remove(request.header().db_uuid(), request.delete_().key());
if (result == bzn::storage_result::ok)
{
this->subscription_manager->inspect_commit(request);
this->remove_expiration_entry(generate_expire_key(request.header().db_uuid(), request.delete_().key()));
}
}
}
this->send_response(request, result, database_response(), session);
}
void
crud::handle_ttl(const bzn::caller_id_t& /*caller_id*/, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
std::shared_lock<std::shared_mutex> lock(this->crud_lock); // lock for read access
bool has = this->storage->has(request.header().db_uuid(), request.ttl().key());
// exists and expired?
if (has && this->expired(request.header().db_uuid(), request.ttl().key()))
{
this->send_response(request, bzn::storage_result::delete_pending, database_response(), session);
return;
}
database_response response;
if (has)
{
const auto ttl = this->get_ttl(request.header().db_uuid(), request.ttl().key());
if (ttl)
{
response.mutable_ttl()->set_key(request.ttl().key());
response.mutable_ttl()->set_ttl(*ttl);
}
else
{
has = false; // we don't have a ttl value for this key
}
}
this->send_response(request, (has) ? bzn::storage_result::ok : bzn::storage_result::ttl_not_found, std::move(response), session);
}
void
crud::handle_persist(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::db_not_found};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
const auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (db_exists)
{
if (!this->is_caller_a_writer(caller_id, perms))
{
result = bzn::storage_result::access_denied;
}
else
{
const auto generated_key = generate_expire_key(request.header().db_uuid(), request.persist().key());
const bool has = this->storage->has(TTL_UUID, generated_key);
// expired?
if (has && this->expired(request.header().db_uuid(), request.persist().key()))
{
this->send_response(request, bzn::storage_result::delete_pending, database_response(), session);
return;
}
if (has)
{
this->remove_expiration_entry(generated_key);
result = bzn::storage_result::ok;
}
else
{
result = bzn::storage_result::ttl_not_found;
}
}
}
this->send_response(request, result, database_response(), session);
}
void
crud::handle_expire(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::db_not_found};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
const auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (db_exists)
{
if (!this->is_caller_a_writer(caller_id, perms))
{
result = bzn::storage_result::access_denied;
}
else
{
const auto generated_key = generate_expire_key(request.header().db_uuid(), request.expire().key());
const bool has = this->storage->has(TTL_UUID, generated_key);
// expired?
if (has && this->expired(request.header().db_uuid(), request.expire().key()))
{
this->send_response(request, bzn::storage_result::delete_pending, database_response(), session);
return;
}
// do not allow zero expires...
if (request.expire().expire() == 0)
{
result = bzn::storage_result::invalid_argument;
}
else
{
result = bzn::storage_result::not_found;
// assume if ttl entry exists so does the db entry...
if (has)
{
this->remove_expiration_entry(generated_key);
result = bzn::storage_result::ok;
this->update_expiration_entry(generated_key, request.expire().expire());
}
else
{
if (this->storage->has(request.header().db_uuid(), request.expire().key()))
{
result = bzn::storage_result::ok;
this->update_expiration_entry(generated_key, request.expire().expire());
}
else
{
result = bzn::storage_result::not_found;
}
}
}
}
}
this->send_response(request, result, database_response(), session);
}
void
crud::handle_has(const bzn::caller_id_t& /*caller_id*/, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::ok};
std::shared_lock<std::shared_mutex> lock(this->crud_lock); // lock for read access
database_response response;
response.mutable_has()->set_key(request.has().key());
if (this->expired(request.header().db_uuid(), request.has().key()))
{
response.mutable_has()->set_has(false);
}
else
{
if (this->storage->has(PERMISSION_UUID, request.header().db_uuid()))
{
response.mutable_has()->set_has(this->storage->has(request.header().db_uuid(), request.has().key()));
}
else
{
result = bzn::storage_result::db_not_found;
}
}
this->send_response(request, result, std::move(response), session);
}
void
crud::handle_keys(const bzn::caller_id_t& /*caller_id*/, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::ok};
std::shared_lock<std::shared_mutex> lock(this->crud_lock); // lock for read access
database_response response;
if (this->storage->has(PERMISSION_UUID, request.header().db_uuid()))
{
const auto keys = this->storage->get_keys(request.header().db_uuid());
response.mutable_keys();
for (const auto& key : keys)
{
if (!this->expired(request.header().db_uuid(), key))
{
response.mutable_keys()->add_keys(key);
}
}
}
else
{
result = bzn::storage_result::db_not_found;
}
this->send_response(request, result, std::move(response), session);
}
void
crud::handle_size(const bzn::caller_id_t& /*caller_id*/, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
std::shared_lock<std::shared_mutex> lock(this->crud_lock); // lock for read access
const auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (!db_exists)
{
this->send_response(request, bzn::storage_result::db_not_found, database_response(), session);
return;
}
const auto [keys, size] = this->storage->get_size(request.header().db_uuid());
database_response response;
response.mutable_size()->set_keys(keys);
response.mutable_size()->set_bytes(size);
if (const auto max_size = this->max_database_size(perms); max_size)
{
response.mutable_size()->set_remaining_bytes((size < max_size) ? (max_size - size) : (0));
response.mutable_size()->set_max_size(max_size);
}
this->send_response(request, bzn::storage_result::ok, std::move(response), session);
}
void
crud::handle_subscribe(const bzn::caller_id_t& /*caller_id*/, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
if (session)
{
database_response response;
this->subscription_manager->subscribe(request.header().db_uuid(), request.subscribe().key(),
request.header().nonce(), response, session);
this->send_response(request, bzn::storage_result::ok, std::move(response), session);
return;
}
LOG(warning) << "session no longer available. SUBSCRIBE not executed.";
}
void
crud::handle_unsubscribe(const bzn::caller_id_t& /*caller_id*/, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
if (session)
{
database_response response;
this->subscription_manager->unsubscribe(request.header().db_uuid(), request.unsubscribe().key(),
request.unsubscribe().nonce(), response, session);
this->send_response(request, bzn::storage_result::ok, std::move(response), session);
return;
}
// subscription manager will cleanup stale sessions...
LOG(warning) << "session no longer available. UNSUBSCRIBE not executed.";
}
void
crud::handle_create_db(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::ok};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
if (!this->owner_public_key.empty() && (this->owner_public_key != caller_id))
{
result = bzn::storage_result::access_denied;
}
else if (this->storage->has(PERMISSION_UUID, request.header().db_uuid()))
{
result = bzn::storage_result::db_exists;
}
else
{
const Json::Value perms = this->create_permission_data(caller_id, request.create_db());
// Check max_database_size and if requested database is set to unlimited!
if ((request.create_db().max_size() == 0) && this->max_swarm_storage)
{
LOG(debug) << "attempting to create a database with no limits (max_swarm_storage = " << this->max_swarm_storage << ")";
result = bzn::storage_result::invalid_size;
}
else
{
if (!this->operation_exceeds_available_space(request, perms))
{
result = this->storage->create(PERMISSION_UUID, request.header().db_uuid(), perms.toStyledString());
}
else
{
result = bzn::storage_result::db_full;
}
}
}
this->send_response(request, result, database_response(), session);
}
void
crud::handle_update_db(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::db_not_found};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (db_exists)
{
if (!this->is_caller_owner(caller_id, perms))
{
result = bzn::storage_result::access_denied;
}
else
{
// Check max_database_size and if requested database is set to unlimited!
if ((request.update_db().max_size() == 0) && this->max_swarm_storage)
{
LOG(debug) << "attempting to update a database with no limits (max_swarm_storage = " << this->max_swarm_storage << ")";
result = bzn::storage_result::invalid_size;
}
else
{
// only check if max size has grown...
if (request.update_db().max_size() > perms[MAX_SIZE_KEY].asUInt64())
{
auto new_perms = perms;
new_perms[MAX_SIZE_KEY] = request.update_db().max_size();
if (this->operation_exceeds_available_space(request, new_perms))
{
this->send_response(request, bzn::storage_result::db_full, database_response(), session);
return;
}
}
result = this->storage->update(PERMISSION_UUID, request.header().db_uuid(),
this->update_permission_data(perms, request.update_db()));
}
}
}
this->send_response(request, result, database_response(), session);
}
void
crud::handle_delete_db(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::db_not_found};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
const auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (!this->owner_public_key.empty() && (this->owner_public_key != caller_id))
{
result = bzn::storage_result::access_denied;
}
else if (db_exists)
{
if (!this->is_caller_owner(caller_id, perms))
{
result = bzn::storage_result::access_denied;
}
else
{
result = this->storage->remove(PERMISSION_UUID, request.header().db_uuid());
this->storage->remove(request.header().db_uuid());
this->flush_expiration_entries(request.header().db_uuid());
}
}
this->send_response(request, result, database_response(), session);
}
void
crud::handle_has_db(const bzn::caller_id_t& /*caller_id*/, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
std::shared_lock<std::shared_mutex> lock(this->crud_lock); // lock for read access
database_response response;
response.mutable_has_db()->set_uuid(request.header().db_uuid());
response.mutable_has_db()->set_has(this->storage->has(PERMISSION_UUID, request.header().db_uuid()));
this->send_response(request, bzn::storage_result::ok, std::move(response), session);
}
void
crud::handle_writers(const bzn::caller_id_t& /*caller_id*/, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::not_found};
std::shared_lock<std::shared_mutex> lock(this->crud_lock); // lock for read access
const auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (db_exists)
{
database_response resp;
resp.mutable_writers()->set_owner(perms[OWNER_KEY].asString());
for(const auto& writer : perms[WRITERS_KEY])
{
resp.mutable_writers()->add_writers(writer.asString());
}
this->send_response(request, bzn::storage_result::ok, std::move(resp), session);
return;
}
else
{
this->send_response(request, result, database_response(), session);
}
}
void
crud::handle_add_writers(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::db_not_found};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (db_exists)
{
if (!this->is_caller_owner(caller_id, perms))
{
result = bzn::storage_result::access_denied;
}
else
{
this->add_writers(request, perms);
LOG(debug) << "updating db perms: " << perms.toStyledString().substr(0, MAX_MESSAGE_SIZE) << "...";
if (result = this->storage->update(PERMISSION_UUID, request.header().db_uuid(), perms.toStyledString()); result != bzn::storage_result::ok)
{
throw std::runtime_error("Failed to update database permissions: " + bzn::storage_result_msg.at(result));
}
}
}
this->send_response(request, result, database_response(), session);
}
void
crud::handle_remove_writers(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)
{
bzn::storage_result result{bzn::storage_result::db_not_found};
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
auto [db_exists, perms] = this->get_database_permissions(request.header().db_uuid());
if (db_exists)
{
if (!this->is_caller_owner(caller_id, perms))
{
result = bzn::storage_result::access_denied;
}
else
{
this->remove_writers(request, perms);
LOG(debug) << "updating db perms: " << perms.toStyledString().substr(0, MAX_MESSAGE_SIZE) << "...";
if (result = this->storage->update(PERMISSION_UUID, request.header().db_uuid(), perms.toStyledString()); result != bzn::storage_result::ok)
{
throw std::runtime_error("Failed to update database permissions: " + bzn::storage_result_msg.at(result));
}
}
}
this->send_response(request, result, database_response(), session);
}
std::pair<bool, Json::Value>
crud::get_database_permissions(const bzn::uuid_t& uuid) const
{
// does the db exist?
if (this->storage->has(PERMISSION_UUID, uuid))
{
auto perms_data = this->storage->read(PERMISSION_UUID, uuid);
if (!perms_data)
{
throw std::runtime_error("Failed to read database permission data!");
}
Json::CharReaderBuilder rbuilder;
std::unique_ptr<Json::CharReader> const reader(rbuilder.newCharReader());
std::string parse_errors;
Json::Value json;
if (!reader->parse((*perms_data).c_str(), (*perms_data).c_str() + (*perms_data).size(), &json, &parse_errors))
{
throw std::runtime_error("Failed to parse database json permission data: " + parse_errors);
}
return {true, json};
}
return {false, Json::Value()};
}
Json::Value
crud::create_permission_data(const bzn::caller_id_t& caller_id, const database_create_db& request) const
{
Json::Value json;
json[OWNER_KEY] = boost::trim_copy(caller_id);
json[WRITERS_KEY] = Json::Value(Json::arrayValue);
json[MAX_SIZE_KEY] = request.max_size();
json[EVICTION_POLICY_KEY] = uint16_t(request.eviction_policy());
LOG(debug) << "created db perms: " << json.toStyledString();
return json;
}
bzn::value_t
crud::update_permission_data(Json::Value& perms, const database_create_db& request) const
{
perms[MAX_SIZE_KEY] = request.max_size();
perms[EVICTION_POLICY_KEY] = uint16_t(request.eviction_policy());
LOG(debug) << "update db perms: " << perms.toStyledString();
return perms.toStyledString();
}
bool
crud::is_caller_owner(const bzn::caller_id_t& caller_id, const Json::Value& perms) const
{
return perms[OWNER_KEY] == boost::trim_copy(caller_id);
}
bool
crud::is_caller_a_writer(const bzn::caller_id_t& caller_id, const Json::Value& perms) const
{
for (const auto& writer_id : perms[WRITERS_KEY])
{
if (writer_id == boost::trim_copy(caller_id))
{
return true;
}
}
// A node may be issuing an operation such as delete for key expiration...
// TODO: this may need to compare against all recent peers, not just current ones
for (const auto& peer_uuid : *this->pbft->peers()->current())
{
if (peer_uuid.uuid == boost::trim_copy(caller_id))
{
return true;
}
}
return this->is_caller_owner(caller_id, perms);
}
std::shared_ptr<policy::eviction_base>
crud::get_eviction_policy(const Json::Value& perms)
{
// TODO: As we add more policies we may want to turn this into the strategy pattern and use
// a registry based approach here
if (perms[EVICTION_POLICY_KEY] == database_create_db::RANDOM)
{
return std::make_shared<policy::random>(this->storage);
}
else if (perms[EVICTION_POLICY_KEY] == database_create_db::VOLATILE_TTL)
{
return std::make_shared<policy::volatile_ttl>(this->storage);
}
return nullptr;
}
uint64_t
crud::max_database_size(const Json::Value& perms) const
{
return boost::lexical_cast<uint64_t>(perms[MAX_SIZE_KEY]);
}
void
crud::add_writers(const database_msg& request, Json::Value& perms)
{
const std::string owner = perms[OWNER_KEY].asString();
std::set<std::string> current_writers;
for (const auto& writer : perms[WRITERS_KEY])
{
current_writers.emplace(writer.asString());
}
for (const auto& writer : request.add_writers().writers())
{
// owner never should be in the writers list...
if (writer != owner)
{
current_writers.insert(writer);
}
}
perms[WRITERS_KEY].clear();
for (auto&& writer : current_writers)
{
perms[WRITERS_KEY].append(std::move(writer));
}
}
void
crud::remove_writers(const database_msg& request, Json::Value& perms)
{
std::set<std::string> current_writers;
for (auto& writer : perms[WRITERS_KEY])
{
current_writers.emplace(writer.asString());
}
for (const auto& writer : request.remove_writers().writers())
{
current_writers.erase(writer);
}
perms[WRITERS_KEY].clear();
for (auto&& writer : current_writers)
{
perms[WRITERS_KEY].append(std::move(writer));
}
}
bool
crud::save_state()
{
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
return this->storage->create_snapshot();
}
std::shared_ptr<std::string>
crud::get_saved_state()
{
std::shared_lock<std::shared_mutex> lock(this->crud_lock); // lock for read access
return this->storage->get_snapshot();
}
bool
crud::load_state(const std::string& state)
{
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
return this->storage->load_snapshot(state);
}
void
crud::update_expiration_entry(const bzn::key_t& generated_key, uint64_t expire)
{
if (expire)
{
// now + expire seconds...
const auto expires = boost::lexical_cast<std::string>(
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count() + expire);
auto result = this->storage->create(TTL_UUID, generated_key, expires);
if (result == bzn::storage_result::ok)
{
LOG(debug) << "created ttl entry [" << expires << "] for: " << generated_key;
return;
}
result = this->storage->update(TTL_UUID, generated_key, expires);
if (result != bzn::storage_result::ok)
{
throw std::runtime_error("Failed to update ttl entry for: " + generated_key);
}
return;
}
LOG(debug) << "removing old entry for: " << generated_key;
this->remove_expiration_entry(generated_key);
}
void
crud::remove_expiration_entry(const bzn::key_t& generated_key)
{
this->storage->remove(TTL_UUID, generated_key);
}
bool
crud::expired(const bzn::uuid_t& uuid, const bzn::key_t& key)
{
auto result = this->storage->read(TTL_UUID, generate_expire_key(uuid, key));
if (result)
{
const uint64_t now = uint64_t(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count());
const uint64_t expire = boost::lexical_cast<uint64_t>(*result);
return (expire <= now);
}
return false;
}
std::optional<uint64_t>
crud::get_ttl(const bzn::uuid_t& uuid, const bzn::key_t& key) const
{
const auto result = this->storage->read(TTL_UUID, generate_expire_key(uuid, key));
if (result)
{
const uint64_t now = uint64_t(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count());
const uint64_t expire = boost::lexical_cast<uint64_t>(*result);
if (expire > now)
{
return {boost::lexical_cast<uint64_t>(*result) -
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count()};
}
return {0};
}
return {};
}
void
crud::check_key_expiration(const boost::system::error_code& ec)
{
if (!ec)
{
std::lock_guard<std::shared_mutex> lock(this->crud_lock); // lock for write access
const uint64_t now = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
for (const auto& generated_key : this->storage->get_keys(TTL_UUID))
{
auto result = this->storage->read(TTL_UUID, generated_key);
if (result)
{
const auto [uuid, key] = extract_uuid_key(generated_key);
// has entry expired?
if (now >= boost::lexical_cast<uint64_t>(*result))
{
LOG(debug) << "removing expired ttl entry and key for: " << uuid << ":" << key;
// Issue delete using pbft...
database_msg request;
request.mutable_header()->set_db_uuid(uuid);
request.mutable_delete_()->set_key(key);
bzn_envelope msg;
msg.set_sender(this->pbft->get_uuid());
msg.set_database_msg(request.SerializeAsString());
this->pbft->handle_database_message(msg, nullptr);
}
else
{
// if key no longer exists, then remove the entry...
if (!this->storage->has(uuid, key))
{
LOG(debug) << "removing stale ttl entry for: " << uuid << ":" << key;
this->storage->remove(TTL_UUID, generated_key);
}
}
}
else
{
std::runtime_error("Failed to read TTL value for: " + generated_key);
}
}
this->expire_timer->expires_from_now(TTL_TICK);
this->expire_timer->async_wait(std::bind(&crud::check_key_expiration, shared_from_this(), std::placeholders::_1));
}
}
void
crud::flush_expiration_entries(const bzn::uuid_t& uuid)
{
for (const auto& generated_key : this->storage->get_keys(TTL_UUID))
{
const auto [db_uuid, key] = extract_uuid_key(generated_key);
if (db_uuid == uuid)
{
this->storage->remove(TTL_UUID, generated_key);
LOG(debug) << "removing ttl entry for: " << db_uuid << ":" << key;
}
}
}
bool
crud::operation_exceeds_available_space(const database_msg& request, const Json::Value& perms)
{
const auto request_type = request.msg_case();
const auto max_size = this->max_database_size(perms);
if (request_type == database_msg::kCreateDb || request_type == database_msg::kUpdateDb)
{
if (!this->max_swarm_storage)
{
LOG(debug) << "max storage zero, ignoring: " << request.msg_case();
return false;
}
if (request_type == database_msg::kCreateDb)
{
return (this->get_swarm_storage_usage() + max_size > this->max_swarm_storage);
}
if (request_type == database_msg::kUpdateDb)
{
Json::Value prev_perms;
std::tie(std::ignore, prev_perms) = this->get_database_permissions(request.header().db_uuid());
return (this->get_swarm_storage_usage() - this->max_database_size(prev_perms) + max_size > this->max_swarm_storage);
}
}
// any max size set?
if (max_size)
{
uint64_t size;
std::tie(std::ignore, size) = this->storage->get_size(request.header().db_uuid());
// test create
if (request_type == database_msg::kCreate)
{
return (size + request.create().key().size() + request.create().value().size() > max_size);
}
// test update
if (request_type == database_msg::kUpdate)
{
const auto prev_kv_size = this->storage->get_key_size(request.header().db_uuid(),
request.update().key());
if (prev_kv_size)
{
return (size - *prev_kv_size + request.update().key().size() + request.update().value().size() > max_size);
}
}
}
return false;
}
size_t
crud::get_swarm_storage_usage()
{
const auto databases = this->storage->get_keys(PERMISSION_UUID);
size_t current_database_max_sizes{};
for(const auto& database : databases)
{
auto const result = this->storage->read(PERMISSION_UUID, database);
if (result)
{
Json::CharReaderBuilder rbuilder;
std::unique_ptr<Json::CharReader> const reader(rbuilder.newCharReader());
std::string parse_errors;
Json::Value json;
if (!reader->parse(result.value().c_str(), result.value().c_str() + result.value().size(), &json, &parse_errors))
{
throw std::runtime_error("Failed to parse database json uuid data: " + parse_errors);
}
const auto max_size = this->max_database_size(json);
LOG(debug) << "database: " << database << " " << result.value();
current_database_max_sizes += max_size;
}
}
return current_database_max_sizes;
}
bool
crud::do_eviction(const database_msg& request, size_t max_size)
{
const auto PERMS{this->get_database_permissions(request.header().db_uuid()).second};
if (auto eviction_policy = this->get_eviction_policy(PERMS))
{
auto keys_to_evict {eviction_policy->keys_to_evict(request, max_size)};
if (keys_to_evict.empty())
{
return false;
}
std::for_each( keys_to_evict.begin(), keys_to_evict.end(),
[&](const auto& key)
{
this->storage->remove(request.header().db_uuid(), key);
});
return true;
}
return false;
}
std::string
crud::get_name()
{
return "crud";
}
bzn::json_message
crud::get_status()
{
bzn::json_message status;
std::shared_lock<std::shared_mutex> lock(this->crud_lock); // lock for read access
status["max_swarm_storage"] = uint64_t(this->max_swarm_storage);
status["swarm_storage_usage"] = uint64_t(this->get_swarm_storage_usage());
return status;
}
================================================
FILE: crud/crud.hpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <crud/crud_base.hpp>
#include <crud/subscription_manager_base.hpp>
#include <include/bluzelle.hpp>
#include <include/boost_asio_beast.hpp>
#include <node/node_base.hpp>
#include <options/options_base.hpp>
#include <pbft/pbft_base.hpp>
#include <policy/eviction_base.hpp>
#include <status/status_provider_base.hpp>
#include <storage/storage_base.hpp>
#include <shared_mutex>
#include <gtest/gtest_prod.h>
namespace bzn
{
class crud final : public bzn::crud_base, public bzn::status_provider_base, public std::enable_shared_from_this<crud>
{
public:
crud(std::shared_ptr<bzn::asio::io_context_base> io_context, std::shared_ptr<bzn::storage_base> storage
, std::shared_ptr<bzn::subscription_manager_base> subscription_manager
, std::shared_ptr<bzn::node_base> node, bzn::key_t owner_public_key = "");
void handle_request(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session) override;
void start(std::shared_ptr<bzn::pbft_base> pbft, size_t max_storage = 0) override;
bool save_state() override;
std::shared_ptr<std::string> get_saved_state() override;
bool load_state(const std::string& state) override;
bzn::json_message get_status() override;
std::string get_name() override;
private:
void handle_create_db(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_update_db(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_delete_db(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_has_db(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_create(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_read(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_update(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_delete(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_ttl(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_persist(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_expire(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_has(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_keys(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_size(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_subscribe(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_unsubscribe(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_writers(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_add_writers(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void handle_remove_writers(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session);
void send_response(const database_msg& request, bzn::storage_result result, database_response&& response, std::shared_ptr<bzn::session_base>& session);
// permission...
std::pair<bool, Json::Value> get_database_permissions(const bzn::uuid_t& uuid) const;
Json::Value create_permission_data(const bzn::caller_id_t& caller_id, const database_create_db& request) const;
bzn::value_t update_permission_data(Json::Value& perms, const database_create_db& request) const;
size_t get_swarm_storage_usage();
bool is_caller_owner(const bzn::caller_id_t& caller_id, const Json::Value& perms) const;
bool is_caller_a_writer(const bzn::caller_id_t& caller_id, const Json::Value& perms) const;
void add_writers(const database_msg& request, Json::Value& perms);
void remove_writers(const database_msg& request, Json::Value& perms);
uint64_t max_database_size(const Json::Value& perms) const;
bool operation_exceeds_available_space(const database_msg& request, const Json::Value& perms);
// expiration...
void check_key_expiration(const boost::system::error_code& ec);
bool expired(const bzn::uuid_t& uuid, const bzn::key_t& key);
void update_expiration_entry(const bzn::uuid_t& generated_key, uint64_t expire);
void remove_expiration_entry(const bzn::key_t& generated_key);
void flush_expiration_entries(const bzn::uuid_t& uuid);
std::optional<uint64_t> get_ttl(const bzn::uuid_t& uuid, const bzn::key_t& key) const;
// cache replacement policy
std::shared_ptr<policy::eviction_base> get_eviction_policy(const Json::Value& perms);
bool do_eviction(const database_msg& request, size_t max_size);
std::shared_ptr<bzn::storage_base> storage;
std::shared_ptr<bzn::subscription_manager_base> subscription_manager;
std::shared_ptr<bzn::node_base> node;
std::shared_ptr<bzn::pbft_base> pbft; // required for expiration
std::unique_ptr<bzn::asio::steady_timer_base> expire_timer;
using message_handler_t = std::function<void(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session)>;
std::unordered_map<database_msg::MsgCase, message_handler_t> message_handlers;
std::once_flag start_once;
std::shared_mutex crud_lock; // for multi-reader and single writer access
const bzn::key_t owner_public_key;
size_t max_swarm_storage{}; // maximum size of swarm database (unlimited when zero)
};
} // namespace bzn
================================================
FILE: crud/crud_base.hpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <include/bluzelle.hpp>
#include <node/session_base.hpp>
#include <proto/database.pb.h>
namespace bzn
{
class pbft_base;
class crud_base
{
public:
virtual ~crud_base() = default;
virtual void handle_request(const bzn::caller_id_t& caller_id, const database_msg& request, std::shared_ptr<bzn::session_base> session) = 0;
virtual void start(std::shared_ptr<bzn::pbft_base> pbft, size_t max_storage) = 0;
virtual bool save_state() = 0;
virtual std::shared_ptr<std::string> get_saved_state() = 0;
virtual bool load_state(const std::string& state) = 0;
};
} // namespace bzn
================================================
FILE: crud/subscription_manager.cpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <crud/subscription_manager.hpp>
#include <algorithm>
using namespace bzn;
namespace
{
const std::chrono::seconds DEFAULT_DEAD_SESSION_CHECK{15};
}
subscription_manager::subscription_manager(std::shared_ptr<bzn::asio::io_context_base> io_context)
: purge_timer(io_context->make_unique_steady_timer())
{
}
void
subscription_manager::start()
{
std::call_once(this->start_once,
[this]()
{
this->purge_timer->expires_from_now(DEFAULT_DEAD_SESSION_CHECK);
this->purge_timer->async_wait(std::bind(&subscription_manager::purge_closed_sessions, shared_from_this(), std::placeholders::_1));
});
}
void
subscription_manager::subscribe(const bzn::uuid_t& uuid, const bzn::key_t& key, uint64_t transaction_id, database_response& response, std::shared_ptr<bzn::session_base> session)
{
LOG(debug) << "session [" << session->get_session_id() << "] subscription request: " << uuid << ":" << transaction_id << ":" << key;
std::lock_guard<std::mutex> lock(this->subscribers_lock);
if (auto database_it = this->subscribers.find(uuid); database_it != this->subscribers.end())
{
if (auto key_it = database_it->second.find(key); key_it == database_it->second.end())
{
// add new key and subscriber...
database_it->second[key][session->get_session_id()][transaction_id] = std::move(session);
this->key_seq_number[uuid][key] = 0;
return;
}
else
{
// find existing session...
auto session_it = database_it->second[key].find(session->get_session_id());
if (session_it == database_it->second[key].end() || session_it->second.find(transaction_id) == session_it->second.end())
{
// add new key and subscriber...
database_it->second[key][session->get_session_id()][transaction_id] = std::move(session);
return;
}
}
// session already subscribed to this key...
response.mutable_error()->set_message(MSG_DUPLICATE_SUB);
LOG(debug) << "session [" << session->get_session_id() << "] has already subscribed to: " << uuid << ":" << transaction_id << ":" << key;
return;
}
// create a new entry...
this->subscribers[uuid][key][session->get_session_id()][transaction_id] = std::move(session);
}
void
subscription_manager::unsubscribe(const bzn::uuid_t& uuid, const bzn::key_t& key, uint64_t transaction_id, database_response& response, std::shared_ptr<bzn::session_base> session)
{
LOG(debug) << "session [" << session->get_session_id() << "] unsubscribe request: " << uuid << ":" << key << ":" << transaction_id;
std::lock_guard<std::mutex> lock(this->subscribers_lock);
auto database_it = this->subscribers.find(uuid);
if (database_it == this->subscribers.end())
{
response.mutable_error()->set_message(MSG_INVALID_UUID);
LOG(debug) << "session [" << session->get_session_id() << "] unknown database & key: " << uuid << ":" << key << ":" << transaction_id;
return;
}
auto key_it = database_it->second.find(key);
if (key_it == database_it->second.end())
{
response.mutable_error()->set_message(MSG_INVALID_KEY);
LOG(debug) << "session [" << session->get_session_id() << "] unknown key: " << uuid << ":" << key << ":" << transaction_id;
return;
}
// check to see if session is already in the list...
if (auto session_it = database_it->second[key].find(session->get_session_id()); session_it == key_it->second.end())
{
response.mutable_error()->set_message(MSG_INVALID_SUB);
LOG(debug) << "session [" << session->get_session_id() << "] not subscribed to: " << uuid << ":" << key << ":" << transaction_id;
return;
}
else
{
// remove subscription...
if (auto sub_it = session_it->second.find(transaction_id); sub_it != session_it->second.end())
{
session_it->second.erase(sub_it);
return;
}
response.mutable_error()->set_message(MSG_INVALID_SUB);
LOG(debug) << "session [" << session->get_session_id() << "] not subscribed to: " << uuid << ":" << key << ":" << transaction_id;
}
}
void
subscription_manager::notify_sessions(const bzn::uuid_t& uuid, const bool update, const bzn::key_t& key, const std::string& value)
{
std::lock_guard<std::mutex> lock(this->subscribers_lock);
if (auto database_it = this->subscribers.find(uuid); database_it != this->subscribers.end())
{
if (auto key_it = database_it->second.find(key); key_it != database_it->second.end())
{
std::once_flag once;
for (const auto& sessions : key_it->second)
{
std::call_once(once, [&]{++this->key_seq_number[uuid][key];});
for (const auto& subscription : sessions.second)
{
if (auto session_shared_ptr = subscription.second.lock())
{
database_response resp;
resp.mutable_header()->set_db_uuid(uuid);
resp.mutable_header()->set_nonce(subscription.first);
resp.mutable_subscription_update()->set_key(key);
resp.mutable_subscription_update()->set_seq(this->key_seq_number[uuid][key]);
if (!value.empty())
{
resp.mutable_subscription_update()->set_value(value);
}
if (update)
{
resp.mutable_subscription_update()->set_operation(database_subscription_update::UPDATE);
}
else
{
resp.mutable_subscription_update()->set_operation(database_subscription_update::DELETE);
}
LOG(debug) << "notifying session [" << session_shared_ptr->get_session_id() << "] : " << uuid
<< ":" << key << ":" << subscription.first << ":" << this->key_seq_number[uuid][key] << ":"
<< value.substr(0, MAX_MESSAGE_SIZE);
session_shared_ptr->send_message(std::make_shared<std::string>(resp.SerializeAsString()));
}
}
}
}
}
}
void
subscription_manager::inspect_commit(const database_msg& msg)
{
switch (msg.msg_case())
{
case database_msg::kCreate:
this->notify_sessions(msg.header().db_uuid(), true, msg.create().key(), msg.create().value());
break;
case database_msg::kUpdate:
this->notify_sessions(msg.header().db_uuid(), true, msg.update().key(), msg.update().value());
break;
case database_msg::kDelete:
this->notify_sessions(msg.header().db_uuid(), false, msg.delete_().key(), "");
break;
default:
// nothing to do...
break;
}
}
void
subscription_manager::purge_closed_sessions(const boost::system::error_code& ec)
{
if (!ec)
{
std::lock_guard<std::mutex> lock(this->subscribers_lock);
auto database_it = this->subscribers.begin();
while (database_it != this->subscribers.end())
{
size_t purged{};
auto key_it = database_it->second.begin();
while (key_it != database_it->second.end())
{
auto session_it = key_it->second.begin();
while (session_it != key_it->second.end())
{
auto subscribers_it = session_it->second.begin();
while (subscribers_it != session_it->second.end())
{
if (auto session_shared_ptr = subscribers_it->second.lock())
{
++subscribers_it;
continue;
}
LOG(debug) << "purged closed session [" << session_it->first << "] for: " << database_it->first;
++purged;
subscribers_it = session_it->second.erase(subscribers_it);
}
if (session_it->second.empty())
{
session_it = key_it->second.erase(session_it);
continue;
}
++session_it;
}
if (key_it->second.empty())
{
key_it = database_it->second.erase(key_it);
continue;
}
++key_it;
}
if (purged)
{
LOG(info) << "purged " << purged << " closed sessions for database: " << database_it->first;
}
if (database_it->second.empty())
{
database_it = this->subscribers.erase(database_it);
continue;
}
++database_it;
}
// reschedule...
this->purge_timer->expires_from_now(DEFAULT_DEAD_SESSION_CHECK);
this->purge_timer->async_wait(std::bind(&subscription_manager::purge_closed_sessions, shared_from_this(), std::placeholders::_1));
}
}
================================================
FILE: crud/subscription_manager.hpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <crud/subscription_manager_base.hpp>
#include <include/boost_asio_beast.hpp>
#include <unordered_map>
#include <mutex>
#include <list>
namespace bzn
{
class subscription_manager final : public bzn::subscription_manager_base, public std::enable_shared_from_this<subscription_manager>
{
public:
subscription_manager(std::shared_ptr<bzn::asio::io_context_base> io_context);
void start() override;
void subscribe(const bzn::uuid_t& uuid, const bzn::key_t& key, uint64_t transaction_id, database_response& response, std::shared_ptr<bzn::session_base> session) override;
void unsubscribe(const bzn::uuid_t& uuid, const bzn::key_t& key, uint64_t transaction_id, database_response& response, std::shared_ptr<bzn::session_base> session) override;
void inspect_commit(const database_msg& msg) override;
private:
void purge_closed_sessions(const boost::system::error_code& ec);
void notify_sessions(const bzn::uuid_t& uuid, bool update, const bzn::key_t& key, const std::string& value);
std::unordered_map<bzn::uuid_t, std::unordered_map<bzn::key_t, std::unordered_map<bzn::session_id, std::unordered_map<uint64_t, std::weak_ptr<bzn::session_base>>>>> subscribers;
std::unordered_map<bzn::uuid_t, std::unordered_map<bzn::key_t, uint64_t>> key_seq_number;
std::mutex subscribers_lock;
std::unique_ptr<bzn::asio::steady_timer_base> purge_timer;
std::once_flag start_once;
};
} // namespace bzn
================================================
FILE: crud/subscription_manager_base.hpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <include/bluzelle.hpp>
#include <node/session_base.hpp>
#include <proto/database.pb.h>
namespace bzn
{
const std::string MSG_INVALID_UUID = "INVALID_UUID";
const std::string MSG_INVALID_KEY = "INVALID_KEY";
const std::string MSG_INVALID_SUB = "INVALID_SUB";
const std::string MSG_DUPLICATE_SUB = "DUPLICATE_SUB";
class subscription_manager_base
{
public:
virtual ~subscription_manager_base() = default;
virtual void start() = 0;
virtual void subscribe(const bzn::uuid_t& uuid, const bzn::key_t& key, uint64_t transaction_id, database_response& response, std::shared_ptr<bzn::session_base> session) = 0;
virtual void unsubscribe(const bzn::uuid_t& uuid, const bzn::key_t& key, uint64_t transaction_id, database_response& response, std::shared_ptr<bzn::session_base> session) = 0;
virtual void inspect_commit(const database_msg& msg) = 0;
};
} // namespace bzn
================================================
FILE: crud/test/CMakeLists.txt
================================================
set(test_srcs crud_test.cpp subscription_manager_test.cpp)
set(test_libs crud pbft pbft_operations node storage peers_beacon proto smart_mocks ${Protobuf_LIBRARIES})
add_gmock_test(crud)
================================================
FILE: crud/test/crud_test.cpp
================================================
// Copyright (C) 2018 Bluzelle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <crud/crud.hpp>
#include <storage/mem_storage.hpp>
#include <mocks/mock_session_base.hpp>
#include <mocks/mock_subscription_manager_base.hpp>
#include <mocks/mock_node_base.hpp>
#include <mocks/mock_pbft_base.hpp>
#include <mocks/mock_boost_asio_beast.hpp>
#include <algorithm>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/format.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/lexical_cast.hpp>
gitextract_w88obzzf/
├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── CONTRIBUTOR.md
├── LICENSE
├── README.md
├── SUMMARY.md
├── audit/
│ ├── CMakeLists.txt
│ ├── audit.cpp
│ ├── audit.hpp
│ ├── audit_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── audit_test.cpp
├── chaos/
│ ├── CMakeLists.txt
│ ├── chaos.cpp
│ ├── chaos.hpp
│ ├── chaos_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── chaos_test.cpp
├── cmake/
│ ├── add_gmock_test.cmake
│ ├── boost.cmake
│ ├── git_commit.cmake
│ ├── googletest.cmake
│ ├── jsoncpp.cmake
│ ├── openssl.cmake
│ ├── rocksdb.cmake
│ ├── static_analysis.cmake
│ ├── static_analysis.sh
│ ├── swarm_git_commit.hpp.in
│ ├── swarm_version.cmake
│ └── swarm_version.hpp.in
├── crud/
│ ├── CMakeLists.txt
│ ├── crud.cpp
│ ├── crud.hpp
│ ├── crud_base.hpp
│ ├── subscription_manager.cpp
│ ├── subscription_manager.hpp
│ ├── subscription_manager_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ ├── crud_test.cpp
│ └── subscription_manager_test.cpp
├── crypto/
│ ├── CMakeLists.txt
│ ├── crypto.cpp
│ ├── crypto.hpp
│ ├── crypto_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── crypto_test.cpp
├── depend/
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── boost/
│ │ ├── CMakeLists.txt
│ │ └── package/
│ │ ├── .gitattributes
│ │ └── CMakeLists.txt
│ ├── googletest/
│ │ ├── CMakeLists.txt
│ │ └── package/
│ │ ├── .gitattributes
│ │ └── CMakeLists.txt
│ ├── jsoncpp/
│ │ ├── CMakeLists.txt
│ │ └── package/
│ │ ├── .gitattributes
│ │ └── CMakeLists.txt
│ ├── openssl/
│ │ ├── CMakeLists.txt
│ │ └── package/
│ │ ├── .gitattributes
│ │ └── CMakeLists.txt
│ └── rocksdb/
│ ├── CMakeLists.txt
│ └── package/
│ ├── .gitattributes
│ └── CMakeLists.txt
├── include/
│ ├── bluzelle.hpp
│ ├── boost_asio_beast.hpp
│ └── system_clock.hpp
├── mocks/
│ ├── CMakeLists.txt
│ ├── mock_boost_asio_beast.hpp
│ ├── mock_chaos_base.hpp
│ ├── mock_crud_base.hpp
│ ├── mock_crypto_base.hpp
│ ├── mock_monitor.hpp
│ ├── mock_node_base.hpp
│ ├── mock_options_base.hpp
│ ├── mock_pbft_base.hpp
│ ├── mock_pbft_failure_detector.hpp
│ ├── mock_pbft_service_base.hpp
│ ├── mock_peers_beacon_base.hpp
│ ├── mock_session_base.hpp
│ ├── mock_status_provider_base.hpp
│ ├── mock_storage_base.hpp
│ ├── mock_subscription_manager_base.hpp
│ ├── mock_system_clock.hpp
│ ├── mock_utils_interface.hpp
│ ├── smart_mock_io.cpp
│ ├── smart_mock_io.hpp
│ ├── smart_mock_node.cpp
│ ├── smart_mock_node.hpp
│ ├── smart_mock_peers_beacon.cpp
│ └── smart_mock_peers_beacon.hpp
├── monitor/
│ ├── CMakeLists.txt
│ ├── monitor.cpp
│ ├── monitor.hpp
│ ├── monitor_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── monitor_test.cpp
├── node/
│ ├── CMakeLists.txt
│ ├── node.cpp
│ ├── node.hpp
│ ├── node_base.hpp
│ ├── session.cpp
│ ├── session.hpp
│ ├── session_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ ├── node_test.cpp
│ └── session_test.cpp
├── options/
│ ├── CMakeLists.txt
│ ├── options.cpp
│ ├── options.hpp
│ ├── options_base.hpp
│ ├── simple_options.cpp
│ ├── simple_options.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── options_test.cpp
├── pbft/
│ ├── CMakeLists.txt
│ ├── database_pbft_service.cpp
│ ├── database_pbft_service.hpp
│ ├── dummy_pbft_service.cpp
│ ├── dummy_pbft_service.hpp
│ ├── operations/
│ │ ├── CMakeLists.txt
│ │ ├── pbft_memory_operation.cpp
│ │ ├── pbft_memory_operation.hpp
│ │ ├── pbft_operation.cpp
│ │ ├── pbft_operation.hpp
│ │ ├── pbft_operation_manager.cpp
│ │ ├── pbft_operation_manager.hpp
│ │ ├── pbft_persistent_operation.cpp
│ │ ├── pbft_persistent_operation.hpp
│ │ └── test/
│ │ ├── CMakeLists.txt
│ │ ├── pbft_operation_manager_test.cpp
│ │ ├── pbft_operation_test_common.cpp
│ │ └── pbft_persistent_operation_test.cpp
│ ├── pbft.cpp
│ ├── pbft.hpp
│ ├── pbft_base.hpp
│ ├── pbft_checkpoint_manager.cpp
│ ├── pbft_checkpoint_manager.hpp
│ ├── pbft_persistent_state.cpp
│ ├── pbft_persistent_state.hpp
│ ├── pbft_service_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ ├── database_pbft_service_test.cpp
│ ├── pbft_audit_test.cpp
│ ├── pbft_catchup_test.cpp
│ ├── pbft_checkpoint_tests.cpp
│ ├── pbft_newview_test.cpp
│ ├── pbft_peer_change_test.cpp
│ ├── pbft_persistent_state_test.cpp
│ ├── pbft_proto_test.cpp
│ ├── pbft_proto_test.hpp
│ ├── pbft_test.cpp
│ ├── pbft_test_common.cpp
│ ├── pbft_test_common.hpp
│ ├── pbft_timestamp_test.cpp
│ └── pbft_viewchange_test.cpp
├── peers_beacon/
│ ├── CMakeLists.txt
│ ├── peer_address.hpp
│ ├── peers_beacon.cpp
│ ├── peers_beacon.hpp
│ ├── peers_beacon_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── peers_beacon_tests.cpp
├── pkg/
│ ├── CMakeLists.txt
│ └── debian/
│ ├── CMakeLists.txt
│ ├── postinst
│ └── postrm
├── policy/
│ ├── CMakeLists.txt
│ ├── eviction_base.hpp
│ ├── random.cpp
│ ├── random.hpp
│ ├── test/
│ │ ├── CMakeLists.txt
│ │ └── eviction_test.cpp
│ ├── volatile_ttl.cpp
│ └── volatile_ttl.hpp
├── proto/
│ ├── CMakeLists.txt
│ ├── audit.proto
│ ├── bluzelle.proto
│ ├── database.proto
│ ├── pbft.proto
│ └── status.proto
├── qa/
│ └── integration-tests.sh
├── scripts/
│ ├── crud
│ ├── generate-key
│ └── sign_uuid.sh
├── scripts-1.md
├── status/
│ ├── CMakeLists.txt
│ ├── status.cpp
│ ├── status.hpp
│ ├── status_provider_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── status_test.cpp
├── storage/
│ ├── CMakeLists.txt
│ ├── mem_storage.cpp
│ ├── mem_storage.hpp
│ ├── rocksdb_storage.cpp
│ ├── rocksdb_storage.hpp
│ ├── storage_base.hpp
│ └── test/
│ ├── CMakeLists.txt
│ └── storage_test.cpp
├── swarm/
│ ├── CMakeLists.txt
│ └── main.cpp
├── utils/
│ ├── CMakeLists.txt
│ ├── blacklist.cpp
│ ├── blacklist.hpp
│ ├── bytes_to_debug_string.cpp
│ ├── bytes_to_debug_string.hpp
│ ├── crypto.cpp
│ ├── crypto.hpp
│ ├── esr_peer_info.cpp
│ ├── http_req.cpp
│ ├── make_endpoint.cpp
│ ├── make_endpoint.hpp
│ ├── test/
│ │ ├── CMakeLists.txt
│ │ ├── make_endpoint_test.cpp
│ │ └── utils_test.cpp
│ ├── utils_interface.hpp
│ └── utils_interface_base.hpp
└── valgrind/
├── bluzelle.supp
├── create_suppressions.sh
└── parse_valgrind_suppressions.sh
SYMBOL INDEX (723 symbols across 121 files)
FILE: audit/audit.hpp
type bzn (line 27) | namespace bzn
class audit (line 30) | class audit : public audit_base, public std::enable_shared_from_this<a...
FILE: audit/audit_base.hpp
type bzn (line 26) | namespace bzn
class audit_base (line 28) | class audit_base
FILE: audit/test/audit_test.cpp
class audit_test (line 24) | class audit_test : public Test
method audit_test (line 41) | audit_test()
method build_audit (line 54) | void build_audit()
function TEST_F (line 63) | TEST_F(audit_test, audit_throws_error_when_primaries_conflict)
function TEST_F (line 86) | TEST_F(audit_test, audit_throws_error_when_pbft_commits_conflict)
function TEST_F (line 110) | TEST_F(audit_test, audit_throws_error_when_no_primary_alive)
function TEST_F (line 120) | TEST_F(audit_test, audit_resets_primary_alive_on_message)
function TEST_F (line 141) | TEST_F(audit_test, audit_forgets_old_data)
function TEST_F (line 175) | TEST_F(audit_test, audit_still_detects_new_errors_after_forgetting_old_d...
function TEST_F (line 208) | TEST_F(audit_test, audit_sends_monitor_message_when_primary_conflict)
function TEST_F (line 225) | TEST_F(audit_test, audit_sends_monitor_message_when_commit_conflict)
FILE: chaos/chaos.hpp
type bzn (line 23) | namespace bzn
class chaos (line 25) | class chaos : public chaos_base, public std::enable_shared_from_this<c...
FILE: chaos/chaos_base.hpp
type bzn (line 18) | namespace bzn
class chaos_base (line 20) | class chaos_base
FILE: chaos/test/chaos_test.cpp
class chaos_test (line 22) | class chaos_test : public Test
method chaos_test (line 41) | chaos_test()
method build_chaos (line 77) | void build_chaos()
function TEST_F (line 87) | TEST_F(chaos_test_DeathTest, test_crash_scheduled_and_executed)
function TEST_F (line 96) | TEST_F(chaos_test, test_messages_never_dropped_or_delayed_when_disabled)
function TEST_F (line 108) | TEST_F(chaos_test, test_messages_sometimes_dropped_or_delayed_sometimes_...
function TEST_F (line 145) | TEST_F(chaos_test, reschedule_retries_message)
FILE: crud/crud.cpp
function generate_expire_key (line 40) | inline bzn::key_t generate_expire_key(const bzn::uuid_t& uuid, const bzn...
function extract_uuid_key (line 50) | inline std::pair<bzn::uuid_t, bzn::key_t> extract_uuid_key(const bzn::ke...
FILE: crud/crud.hpp
type bzn (line 30) | namespace bzn
class crud (line 32) | class crud final : public bzn::crud_base, public bzn::status_provider_...
FILE: crud/crud_base.hpp
type bzn (line 21) | namespace bzn
class pbft_base (line 23) | class pbft_base
class crud_base (line 25) | class crud_base
FILE: crud/subscription_manager.hpp
type bzn (line 24) | namespace bzn
class subscription_manager (line 26) | class subscription_manager final : public bzn::subscription_manager_ba...
FILE: crud/subscription_manager_base.hpp
type bzn (line 22) | namespace bzn
class subscription_manager_base (line 29) | class subscription_manager_base
FILE: crud/test/crud_test.cpp
function parse_env_to_db_resp (line 39) | bool
function expect_signed_response (line 46) | void expect_signed_response(const std::shared_ptr<bzn::mock_session_base...
function expect_response (line 84) | void expect_response(const std::shared_ptr<bzn::mock_session_base>& sess...
function initialize_crud (line 125) | std::shared_ptr<bzn::crud>
function generate_random_hash (line 152) | std::string
function database_msg (line 159) | database_msg
function database_msg (line 170) | database_msg
function database_msg (line 184) | database_msg
function database_msg (line 199) | database_msg
function database_msg (line 208) | database_msg
function database_msg (line 217) | database_msg
function create_test_database (line 225) | void
function remove_test_database (line 244) | void
function create_key_value (line 262) | void
function update_key_value (line 283) | void
function get_database_size (line 304) | std::pair<std::size_t, std::size_t>
function get_database_keys (line 333) | std::set<std::string>
function do_quickread (line 360) | std::string
function make_key (line 386) | std::string
function make_value (line 392) | std::string
function fill_database (line 398) | size_t
function TEST (line 429) | TEST(crud, test_that_create_sends_proper_response)
function TEST (line 534) | TEST(crud, test_that_point_of_contact_create_sends_proper_response)
function TEST (line 674) | TEST(crud, test_that_read_sends_proper_response)
function TEST (line 792) | TEST(crud, test_that_point_of_contact_read_sends_proper_response)
function TEST (line 909) | TEST(crud, test_that_update_sends_proper_response)
function TEST (line 993) | TEST(crud, test_that_point_of_contact_update_sends_proper_response)
function TEST (line 1082) | TEST(crud, test_that_delete_sends_proper_response)
function TEST (line 1143) | TEST(crud, test_that_point_of_contact_delete_sends_proper_response)
function TEST (line 1223) | TEST(crud, test_that_has_sends_proper_response)
function TEST (line 1304) | TEST(crud, test_that_point_of_contact_has_sends_proper_response)
function TEST (line 1385) | TEST(crud, test_that_keys_sends_proper_response)
function TEST (line 1461) | TEST(crud, test_that_point_of_contact_keys_sends_proper_response)
function TEST (line 1552) | TEST(crud, test_that_size_sends_proper_response)
function TEST (line 1617) | TEST(crud, test_that_point_of_contact_size_sends_proper_response)
function TEST (line 1697) | TEST(crud, test_that_subscribe_request_calls_subscription_manager)
function TEST (line 1740) | TEST(crud, test_that_unsubscribe_request_calls_subscription_manager)
function TEST (line 1783) | TEST(crud, test_that_create_db_request_sends_proper_response)
function TEST (line 1821) | TEST(crud, test_that_point_of_contact_create_db_request_sends_proper_res...
function TEST (line 1877) | TEST(crud, test_that_has_db_request_sends_proper_response)
function TEST (line 1933) | TEST(crud, test_that_point_of_contact_has_db_request_sends_proper_response)
function TEST (line 1998) | TEST(crud, test_that_delete_db_sends_proper_response)
function TEST (line 2065) | TEST(crud, test_that_point_of_contact_delete_db_sends_proper_response)
function TEST (line 2142) | TEST(crud, test_that_state_can_be_saved_and_retrieved)
function TEST (line 2157) | TEST(crud, test_that_writers_sends_proper_response)
function TEST (line 2189) | TEST(crud, test_that_point_of_contact_writers_sends_proper_response)
function TEST (line 2227) | TEST(crud, test_that_add_writers_sends_proper_response)
function TEST (line 2277) | TEST(crud, test_that_point_of_contact_add_writers_sends_proper_response)
function TEST (line 2350) | TEST(crud, test_that_remove_writers_sends_proper_response)
function TEST (line 2390) | TEST(crud, test_that_point_of_contact_remove_writers_sends_proper_response)
function TEST (line 2447) | TEST(crud, test_that_key_with_expire_set_is_deleted_by_timer_callback)
function TEST (line 2518) | TEST(crud, test_that_key_with_expiration_can_be_made_persistent)
function TEST (line 2578) | TEST(crud, test_that_create_db_uses_bluzelle_key_to_validate)
function TEST (line 2614) | TEST(crud, test_that_create_db_with_incorrect_bluzelle_key_fails_to_vali...
function TEST (line 2649) | TEST(crud, test_that_delete_db_uses_bluzelle_key_to_validate)
function TEST (line 2705) | TEST(crud, test_that_delete_db_with_incorrect_bluzelle_key_fails_to_vali...
function TEST (line 2761) | TEST(crud, test_assumption_that_boost_random_mt19937_produces_the_same_v...
function TEST (line 2777) | TEST(crud, test_that_create_and_updates_which_exceed_db_limit_send_prope...
function TEST (line 2840) | TEST(crud, test_random_eviction_policy_randomly_removes_a_key_value_pair...
function TEST (line 2894) | TEST(crud, test_random_eviction_policy_with_large_value_requiring_many_e...
function TEST (line 2936) | TEST(crud, test_random_eviction_policy_edge_case_of_create_with_value_la...
function TEST (line 2966) | TEST(crud, test_random_eviction_policy_randomly_removes_a_single_key_val...
function TEST (line 3015) | TEST(crud, test_random_eviction_policy_randomly_removes_many_key_value_p...
function TEST (line 3065) | TEST(crud, test_that_two_cruds_evict_the_same_key_value_pairs_using_the_...
function TEST (line 3161) | TEST(crud, test_that_two_cruds_evict_the_same_key_value_pairs_using_the_...
function TEST (line 3260) | TEST(crud, test_that_expire_send_proper_response)
function TEST (line 3357) | TEST(crud, test_that_create_exceeding_max_swarm_storage_sends_proper_res...
function TEST (line 3430) | TEST(crud, test_that_update_exceeding_max_swarm_stroage_sends_proper_res...
function TEST (line 3471) | TEST(crud, test_that_create_db_cannot_create_a_database_that_is_unlimite...
function TEST (line 3498) | TEST(crud, test_that_update_db_cannot_convert_a_database_to_unlimited_wh...
function TEST (line 3532) | TEST(crud, test_that_status_reports_current_usage)
FILE: crud/test/subscription_manager_test.cpp
function TEST (line 31) | TEST(subscription_manager, test_that_session_can_subscribe_and_unsubscri...
function TEST (line 139) | TEST(subscription_manager, test_that_session_cannot_unsubscribe_other_se...
function TEST (line 166) | TEST(subscription_manager, test_that_subscriber_is_notified_for_create_a...
function TEST (line 304) | TEST(subscription_manager, test_that_dead_session_is_removed_from_subscr...
FILE: crypto/crypto.hpp
type bzn (line 25) | namespace bzn
class crypto (line 27) | class crypto : public bzn::crypto_base
FILE: crypto/crypto_base.hpp
type bzn (line 19) | namespace bzn
class crypto_base (line 21) | class crypto_base
FILE: crypto/test/crypto_test.cpp
class crypto_test (line 26) | class crypto_test : public Test
method crypto_test (line 51) | crypto_test()
function TEST_F (line 80) | TEST_F(crypto_test, messages_use_my_public_key)
function TEST_F (line 142) | TEST_F(crypto_test, messages_signed_and_verified)
function TEST_F (line 151) | TEST_F(crypto_test, bad_signature_caught)
function TEST_F (line 161) | TEST_F(crypto_test, bad_sender_caught)
function TEST_F (line 172) | TEST_F(crypto_test, hash_no_collision)
function TEST_F (line 196) | TEST_F(crypto_test, hash_deterministic_but_not_identity)
FILE: include/bluzelle.hpp
type bzn (line 23) | namespace bzn
type bzn::utils (line 48) | namespace bzn::utils
function basename (line 50) | constexpr
FILE: include/boost_asio_beast.hpp
type bzn::asio (line 26) | namespace bzn::asio
class tcp_socket_base (line 40) | class tcp_socket_base
class udp_socket_base (line 54) | class udp_socket_base
class tcp_acceptor_base (line 64) | class tcp_acceptor_base
class steady_timer_base (line 76) | class steady_timer_base
class strand_base (line 92) | class strand_base
class io_context_base (line 110) | class io_context_base
class udp_socket (line 140) | class udp_socket final : public udp_socket_base
method udp_socket (line 143) | explicit udp_socket(boost::asio::io_context& io_context)
method async_send_to (line 149) | void async_send_to(const boost::asio::const_buffer& msg, boost::asio...
class tcp_socket (line 160) | class tcp_socket final : public tcp_socket_base
method tcp_socket (line 163) | explicit tcp_socket(boost::asio::io_context& io_context)
method tcp_socket (line 168) | explicit tcp_socket(bzn::asio::strand_base& ctx)
method async_connect (line 173) | void async_connect(const boost::asio::ip::tcp::endpoint& ep, bzn::as...
method remote_endpoint (line 178) | boost::asio::ip::tcp::endpoint remote_endpoint() override
class tcp_acceptor (line 194) | class tcp_acceptor final : public tcp_acceptor_base
method tcp_acceptor (line 197) | explicit tcp_acceptor(boost::asio::io_context& io_context, const boo...
method async_accept (line 202) | void async_accept(bzn::asio::tcp_socket_base& socket, bzn::asio::acc...
class steady_timer (line 218) | class steady_timer final : public steady_timer_base
method steady_timer (line 221) | explicit steady_timer(boost::asio::io_context& io_context)
method async_wait (line 226) | void async_wait(wait_handler handler) override
method expires_from_now (line 231) | std::size_t expires_from_now(const std::chrono::milliseconds& expiry...
method cancel (line 236) | void cancel() override
class strand (line 252) | class strand final : public strand_base
method strand (line 255) | explicit strand(boost::asio::io_context& io_context)
method wrap (line 260) | bzn::asio::write_handler wrap(write_handler handler) override
method wrap (line 265) | bzn::asio::close_handler wrap(close_handler handler) override
method wrap (line 270) | bzn::asio::task wrap(bzn::asio::task action) override
method post (line 275) | void post(bzn::asio::task action) override
class io_context (line 291) | class io_context final : public io_context_base
method make_unique_tcp_acceptor (line 294) | std::unique_ptr<bzn::asio::tcp_acceptor_base> make_unique_tcp_accept...
method make_unique_tcp_socket (line 299) | std::unique_ptr<bzn::asio::tcp_socket_base> make_unique_tcp_socket()...
method make_unique_tcp_socket (line 304) | std::unique_ptr<bzn::asio::tcp_socket_base> make_unique_tcp_socket(b...
method make_unique_udp_socket (line 309) | std::unique_ptr<bzn::asio::udp_socket_base> make_unique_udp_socket()...
method make_unique_steady_timer (line 314) | std::unique_ptr<bzn::asio::steady_timer_base> make_unique_steady_tim...
method make_unique_strand (line 319) | std::unique_ptr<bzn::asio::strand_base> make_unique_strand() override
method post (line 324) | void post(bzn::asio::task func) override
method run (line 329) | boost::asio::io_context::count_type run() override
method stop (line 334) | void stop() override
type bzn::beast (line 351) | namespace bzn::beast
class http_socket_base (line 362) | class http_socket_base
class http_socket (line 376) | class http_socket final : public http_socket_base
method http_socket (line 379) | explicit http_socket(boost::asio::ip::tcp::socket socket)
method async_read (line 389) | void async_read(boost::beast::flat_buffer& buffer, boost::beast::htt...
method async_write (line 394) | void async_write(boost::beast::http::response<boost::beast::http::dy...
method close (line 399) | void close() override
class websocket_stream_base (line 410) | class websocket_stream_base
class websocket_stream (line 434) | class websocket_stream final : public websocket_stream_base
method websocket_stream (line 437) | explicit websocket_stream(boost::asio::ip::tcp::socket socket)
method async_accept (line 442) | void async_accept(bzn::asio::accept_handler handler) override
method async_read (line 447) | void async_read(boost::beast::multi_buffer& buffer, bzn::asio::read_...
method async_write (line 452) | void async_write(const boost::asio::mutable_buffers_1& buffer, bzn::...
method write (line 457) | size_t write(const boost::asio::mutable_buffers_1& buffer, boost::be...
method async_close (line 462) | void async_close(boost::beast::websocket::close_code reason, bzn::be...
method async_handshake (line 467) | void async_handshake(const std::string& host, const std::string& tar...
method is_open (line 472) | bool is_open() override
method binary (line 477) | void binary(bool bin) override
class websocket_secure_stream (line 488) | class websocket_secure_stream final : public websocket_stream_base, pu...
method websocket_secure_stream (line 491) | explicit websocket_secure_stream(boost::asio::ip::tcp::socket socket...
method async_accept (line 497) | void async_accept(bzn::asio::accept_handler handler) override
method async_read (line 517) | void async_read(boost::beast::multi_buffer& buffer, bzn::asio::read_...
method async_write (line 522) | void async_write(const boost::asio::mutable_buffers_1& buffer, bzn::...
method write (line 527) | size_t write(const boost::asio::mutable_buffers_1& buffer, boost::be...
method async_close (line 532) | void async_close(boost::beast::websocket::close_code reason, bzn::be...
method async_handshake (line 537) | void async_handshake(const std::string& host, const std::string& tar...
method is_open (line 557) | bool is_open() override
method binary (line 562) | void binary(bool bin) override
class websocket_base (line 574) | class websocket_base
class websocket (line 587) | class websocket final : public websocket_base
method make_websocket_stream (line 590) | std::unique_ptr<bzn::beast::websocket_stream_base> make_websocket_st...
method make_websocket_secure_stream (line 595) | std::shared_ptr<bzn::beast::websocket_stream_base> make_websocket_se...
FILE: include/system_clock.hpp
type bzn (line 18) | namespace bzn
class system_clock_base (line 20) | class system_clock_base
class system_clock (line 28) | class system_clock : public system_clock_base
method microseconds_since_epoch (line 30) | uint64_t microseconds_since_epoch()
FILE: mocks/mock_boost_asio_beast.hpp
type bzn::asio (line 23) | namespace bzn::asio {
class mock_tcp_socket_base (line 25) | class mock_tcp_socket_base : public tcp_socket_base {
class mock_udp_socket_base (line 40) | class mock_udp_socket_base : public udp_socket_base {
class mock_tcp_acceptor_base (line 52) | class mock_tcp_acceptor_base : public tcp_acceptor_base {
class mock_steady_timer_base (line 65) | class mock_steady_timer_base : public steady_timer_base {
class mock_strand_base (line 82) | class mock_strand_base : public strand_base {
class mock_io_context_base (line 101) | class mock_io_context_base : public io_context_base {
type bzn::asio (line 38) | namespace bzn::asio {
class mock_tcp_socket_base (line 25) | class mock_tcp_socket_base : public tcp_socket_base {
class mock_udp_socket_base (line 40) | class mock_udp_socket_base : public udp_socket_base {
class mock_tcp_acceptor_base (line 52) | class mock_tcp_acceptor_base : public tcp_acceptor_base {
class mock_steady_timer_base (line 65) | class mock_steady_timer_base : public steady_timer_base {
class mock_strand_base (line 82) | class mock_strand_base : public strand_base {
class mock_io_context_base (line 101) | class mock_io_context_base : public io_context_base {
type bzn::asio (line 50) | namespace bzn::asio {
class mock_tcp_socket_base (line 25) | class mock_tcp_socket_base : public tcp_socket_base {
class mock_udp_socket_base (line 40) | class mock_udp_socket_base : public udp_socket_base {
class mock_tcp_acceptor_base (line 52) | class mock_tcp_acceptor_base : public tcp_acceptor_base {
class mock_steady_timer_base (line 65) | class mock_steady_timer_base : public steady_timer_base {
class mock_strand_base (line 82) | class mock_strand_base : public strand_base {
class mock_io_context_base (line 101) | class mock_io_context_base : public io_context_base {
type bzn::asio (line 63) | namespace bzn::asio {
class mock_tcp_socket_base (line 25) | class mock_tcp_socket_base : public tcp_socket_base {
class mock_udp_socket_base (line 40) | class mock_udp_socket_base : public udp_socket_base {
class mock_tcp_acceptor_base (line 52) | class mock_tcp_acceptor_base : public tcp_acceptor_base {
class mock_steady_timer_base (line 65) | class mock_steady_timer_base : public steady_timer_base {
class mock_strand_base (line 82) | class mock_strand_base : public strand_base {
class mock_io_context_base (line 101) | class mock_io_context_base : public io_context_base {
type bzn::asio (line 80) | namespace bzn::asio {
class mock_tcp_socket_base (line 25) | class mock_tcp_socket_base : public tcp_socket_base {
class mock_udp_socket_base (line 40) | class mock_udp_socket_base : public udp_socket_base {
class mock_tcp_acceptor_base (line 52) | class mock_tcp_acceptor_base : public tcp_acceptor_base {
class mock_steady_timer_base (line 65) | class mock_steady_timer_base : public steady_timer_base {
class mock_strand_base (line 82) | class mock_strand_base : public strand_base {
class mock_io_context_base (line 101) | class mock_io_context_base : public io_context_base {
type bzn::asio (line 99) | namespace bzn::asio {
class mock_tcp_socket_base (line 25) | class mock_tcp_socket_base : public tcp_socket_base {
class mock_udp_socket_base (line 40) | class mock_udp_socket_base : public udp_socket_base {
class mock_tcp_acceptor_base (line 52) | class mock_tcp_acceptor_base : public tcp_acceptor_base {
class mock_steady_timer_base (line 65) | class mock_steady_timer_base : public steady_timer_base {
class mock_strand_base (line 82) | class mock_strand_base : public strand_base {
class mock_io_context_base (line 101) | class mock_io_context_base : public io_context_base {
type bzn::beast (line 128) | namespace bzn::beast {
class mock_http_socket_base (line 130) | class mock_http_socket_base : public http_socket_base {
class mock_websocket_stream_base (line 147) | class mock_websocket_stream_base : public websocket_stream_base {
class mock_websocket_base (line 172) | class mock_websocket_base : public websocket_base {
type bzn::beast (line 145) | namespace bzn::beast {
class mock_http_socket_base (line 130) | class mock_http_socket_base : public http_socket_base {
class mock_websocket_stream_base (line 147) | class mock_websocket_stream_base : public websocket_stream_base {
class mock_websocket_base (line 172) | class mock_websocket_base : public websocket_base {
type bzn::beast (line 170) | namespace bzn::beast {
class mock_http_socket_base (line 130) | class mock_http_socket_base : public http_socket_base {
class mock_websocket_stream_base (line 147) | class mock_websocket_stream_base : public websocket_stream_base {
class mock_websocket_base (line 172) | class mock_websocket_base : public websocket_base {
FILE: mocks/mock_chaos_base.hpp
type bzn (line 20) | namespace bzn {
class mock_chaos_base (line 22) | class mock_chaos_base : public chaos_base {
FILE: mocks/mock_crud_base.hpp
type bzn (line 20) | namespace bzn {
class mock_crud_base (line 22) | class mock_crud_base : public crud_base {
FILE: mocks/mock_crypto_base.hpp
type bzn (line 20) | namespace bzn
class mock_crypto_base (line 22) | class mock_crypto_base : public crypto_base
FILE: mocks/mock_monitor.hpp
type bzn (line 20) | namespace bzn {
class mock_monitor (line 22) | class mock_monitor : public monitor_base {
FILE: mocks/mock_node_base.hpp
type bzn (line 23) | namespace bzn {
class mock_node_base (line 25) | class mock_node_base : public node_base {
FILE: mocks/mock_options_base.hpp
type bzn (line 21) | namespace bzn {
class mock_options_base (line 23) | class mock_options_base : public options_base {
FILE: mocks/mock_pbft_base.hpp
type bzn (line 23) | namespace bzn {
class mock_pbft_base (line 25) | class mock_pbft_base : public pbft_base {
FILE: mocks/mock_pbft_failure_detector.hpp
type bzn (line 21) | namespace bzn
class mock_pbft_failure_detector_base (line 23) | class mock_pbft_failure_detector_base : public pbft_failure_detector_base
FILE: mocks/mock_pbft_service_base.hpp
type bzn (line 21) | namespace bzn {
class mock_pbft_service_base (line 23) | class mock_pbft_service_base : public pbft_service_base {
FILE: mocks/mock_peers_beacon_base.hpp
type bzn (line 21) | namespace bzn {
class mock_peers_beacon_base (line 23) | class mock_peers_beacon_base : public peers_beacon_base
method refresh (line 38) | bool refresh()
FILE: mocks/mock_session_base.hpp
type bzn (line 23) | namespace bzn {
class mock_session_base (line 24) | class mock_session_base : public session_base {
FILE: mocks/mock_status_provider_base.hpp
type bzn (line 23) | namespace bzn {
class mock_status_provider_base (line 25) | class mock_status_provider_base : public status_provider_base {
FILE: mocks/mock_storage_base.hpp
type bzn (line 20) | namespace bzn {
class mock_storage_base (line 22) | class mock_storage_base : public storage_base {
FILE: mocks/mock_subscription_manager_base.hpp
type bzn (line 20) | namespace bzn {
class mock_subscription_manager_base (line 22) | class mock_subscription_manager_base : public subscription_manager_base {
FILE: mocks/mock_system_clock.hpp
type bzn (line 20) | namespace bzn
class mock_system_clock (line 22) | class mock_system_clock : public system_clock_base
FILE: mocks/mock_utils_interface.hpp
type bzn (line 4) | namespace bzn {
class mock_utils_interface_base (line 6) | class mock_utils_interface_base : public utils_interface_base {
method sync_req (line 15) | std::string sync_req(const std::string& url) const
FILE: mocks/smart_mock_io.hpp
type bzn::asio (line 18) | namespace bzn::asio
class smart_mock_io (line 20) | class smart_mock_io : public mock_io_context_base
FILE: mocks/smart_mock_node.hpp
type bzn (line 20) | namespace bzn
class smart_mock_node (line 22) | class smart_mock_node : public mock_node_base
FILE: mocks/smart_mock_peers_beacon.hpp
type bzn (line 18) | namespace bzn
FILE: monitor/monitor.hpp
type bzn (line 25) | namespace bzn
class monitor (line 27) | class monitor : public monitor_base
FILE: monitor/monitor_base.hpp
type bzn (line 20) | namespace bzn
type statistic (line 22) | enum class statistic
class monitor_base (line 47) | class monitor_base
FILE: monitor/test/monitor_test.cpp
class monitor_test (line 29) | class monitor_test : public Test
method monitor_test (line 45) | monitor_test()
method parse_counter (line 92) | std::pair<std::string, uint64_t> parse_counter(const std::string& mess...
method parse_timer (line 103) | std::pair<std::string, uint64_t> parse_timer(const std::string& message)
function TEST_F (line 115) | TEST_F(monitor_test, test_that_counters_emit_metric)
function TEST_F (line 124) | TEST_F(monitor_test, test_that_timers_emit_metric)
function TEST_F (line 135) | TEST_F(monitor_test, test_concurrent_timers)
function TEST_F (line 151) | TEST_F(monitor_test, test_timer_with_duplicate_triggers)
function TEST_F (line 167) | TEST_F(monitor_test, test_no_endpoint)
function TEST_F (line 181) | TEST_F(monitor_test, test_timers_cleanup)
function TEST_F (line 193) | TEST_F(monitor_test, test_send_fails)
function TEST_F (line 203) | TEST_F(monitor_test, test_collate_no_messages_sent_before_time_passes)
function TEST_F (line 213) | TEST_F(monitor_test, test_collate_all_messages_sent)
FILE: node/node.cpp
function ep_key_t (line 255) | ep_key_t
FILE: node/node.hpp
type bzn (line 32) | namespace bzn
class node (line 36) | class node final : public bzn::node_base, public std::enable_shared_fr...
FILE: node/node_base.hpp
type bzn (line 23) | namespace bzn
class pbft_base (line 25) | class pbft_base
class node_base (line 27) | class node_base
FILE: node/session.hpp
type bzn (line 32) | namespace bzn
class session (line 34) | class session final : public bzn::session_base, public std::enable_sha...
method get_session_id (line 59) | bzn::session_id get_session_id() override { return this->session_id; }
FILE: node/session_base.hpp
type bzn (line 22) | namespace bzn
class session_base (line 25) | class session_base
class session_base (line 31) | class session_base
FILE: node/test/node_test.cpp
class node_test2 (line 45) | class node_test2 : public Test
method node_test2 (line 58) | node_test2()
type bzn (line 70) | namespace bzn
function TEST (line 73) | TEST(node, test_that_node_constructed_with_invalid_address_throws)
function TEST_F (line 88) | TEST_F(node_test2, test_accept_incoming_connection)
function TEST_F (line 100) | TEST_F(node_test2, test_make_new_connection)
function TEST_F (line 110) | TEST_F(node_test2, test_reuse_connection)
function TEST_F (line 126) | TEST_F(node_test2, new_session_for_new_ep)
function TEST_F (line 142) | TEST_F(node_test2, DISABLED_test_replace_dead_session)
function TEST (line 161) | TEST(node, test_that_registering_message_handler_can_only_be_done_once)
function TEST (line 181) | TEST(node, test_that_node_doesnt_call_error_handler_on_successful_conn...
function TEST (line 203) | TEST(node, test_that_node_calls_error_handler_on_no_connect)
function TEST (line 227) | TEST(node, test_that_wrongly_signed_messages_are_dropped)
FILE: node/test/session_test.cpp
class session_test (line 40) | class session_test : public Test
method session_test (line 49) | session_test()
class session_test2 (line 87) | class session_test2 : public Test
method session_test2 (line 100) | session_test2()
method yield (line 105) | void yield()
type bzn (line 117) | namespace bzn
function TEST_F (line 120) | TEST_F(session_test, test_that_when_session_starts_it_accepts_and_read...
function TEST_F (line 141) | TEST_F(session_test2, session_sets_swarm_id_when_sending_a_message)
function TEST_F (line 154) | TEST_F(session_test2, message_queued_before_handshake_gets_sent)
function TEST_F (line 168) | TEST_F(session_test2, idle_timeout_closes_session)
function TEST_F (line 183) | TEST_F(session_test2, no_idle_timeout_when_connect_rejected)
function TEST_F (line 197) | TEST_F(session_test2, additional_shutdown_handlers_can_be_added_to_ses...
FILE: options/options.cpp
function simple_options (line 32) | const simple_options&
function simple_options (line 38) | simple_options&
FILE: options/options.hpp
type bzn (line 21) | namespace bzn
class options (line 23) | class options final : public bzn::options_base
FILE: options/options_base.hpp
type bzn (line 28) | namespace bzn
type utils (line 31) | namespace utils
class options_base (line 40) | class options_base
FILE: options/simple_options.hpp
type bzn::option_names (line 23) | namespace bzn::option_names
type bzn (line 83) | namespace bzn
class simple_options (line 85) | class simple_options
method T (line 99) | T
FILE: options/test/options_test.cpp
function compose_config_data (line 58) | std::string compose_config_data(const std::string& a, const std::string& b)
function config_text_to_json (line 66) | void config_text_to_json(bzn::json_message& json)
class options_file_test (line 86) | class options_file_test : public Test
method options_file_test (line 92) | options_file_test()
method save_file (line 105) | void save_file(const std::string& filename, const std::string& content)
method save_options_file (line 123) | void
function TEST_F (line 130) | TEST_F(options_file_test, test_that_missing_arguments_fail)
function TEST_F (line 140) | TEST_F(options_file_test, test_that_loading_of_default_config_file)
function TEST (line 193) | TEST(options, test_that_missing_default_config_throws_exception)
function TEST_F (line 201) | TEST_F(options_file_test, test_max_storage_parsing)
function TEST_F (line 242) | TEST_F(options_file_test, test_enable_whitlelist_temporary)
function TEST_F (line 263) | TEST_F(options_file_test, test_that_command_line_options_work)
function TEST_F (line 284) | TEST_F(options_file_test, test_that_no_monitor_endpoint_when_not_specified)
function TEST_F (line 302) | TEST_F(options_file_test, test_that_endpoint_built)
function TEST_F (line 327) | TEST_F(options_file_test, test_that_pubkey_used_for_uuid)
function TEST_F (line 349) | TEST_F(options_file_test, test_that_uuid_and_pubkey_conflict)
function TEST_F (line 356) | TEST_F(options_file_test, test_set_option_at_runtime)
FILE: pbft/database_pbft_service.hpp
type bzn (line 25) | namespace bzn
class database_pbft_service (line 27) | class database_pbft_service final : public bzn::pbft_service_base, pub...
FILE: pbft/dummy_pbft_service.hpp
type bzn (line 21) | namespace bzn
class dummy_pbft_service (line 27) | class dummy_pbft_service : public bzn::pbft_service_base
FILE: pbft/operations/pbft_memory_operation.cpp
function bzn_envelope (line 45) | const bzn_envelope&
function pbft_config_msg (line 56) | const pbft_config_msg&
function database_msg (line 67) | const database_msg&
function pbft_operation_stage (line 190) | pbft_operation_stage
function bzn_envelope (line 196) | bzn_envelope
FILE: pbft/operations/pbft_memory_operation.hpp
type bzn (line 20) | namespace bzn
class pbft_memory_operation (line 22) | class pbft_memory_operation : public pbft_operation
FILE: pbft/operations/pbft_operation.cpp
function operation_key_t (line 26) | operation_key_t
function hash_t (line 63) | const hash_t&
FILE: pbft/operations/pbft_operation.hpp
type bzn (line 22) | namespace bzn
type pbft_operation_stage (line 30) | enum class pbft_operation_stage
class pbft_operation (line 35) | class pbft_operation
FILE: pbft/operations/pbft_operation_manager.hpp
type bzn (line 24) | namespace bzn
class pbft_operation_manager (line 26) | class pbft_operation_manager
FILE: pbft/operations/pbft_persistent_operation.cpp
function pbft_operation_stage (line 133) | pbft_operation_stage
function bzn_envelope (line 287) | const bzn_envelope&
function pbft_config_msg (line 298) | const pbft_config_msg&
function database_msg (line 310) | const database_msg&
function bzn_envelope (line 327) | bzn_envelope
FILE: pbft/operations/pbft_persistent_operation.hpp
type bzn (line 21) | namespace bzn
class pbft_persistent_operation (line 23) | class pbft_persistent_operation : public pbft_operation
FILE: pbft/operations/test/pbft_operation_manager_test.cpp
function make_prepared (line 32) | void make_prepared(const std::shared_ptr<bzn::pbft_operation>& op)
function TEST (line 57) | TEST(pbft_operation_manager_test, returned_operation_matches_key)
function TEST (line 66) | TEST(pbft_operation_manager_test, returns_same_operation_instance)
function TEST (line 77) | TEST(pbft_operation_manager_test, prepared_operations_since_only_prepare...
function TEST (line 90) | TEST(pbft_operation_manager_test, prepared_operations_since_prefers_prep...
function TEST (line 102) | TEST(pbft_operation_manager_test, prepared_operations_since_no_duplicates)
function TEST (line 118) | TEST(pbft_operation_manager_test, delete_clears_operations)
FILE: pbft/operations/test/pbft_operation_test_common.cpp
class pbft_operation_test_common (line 43) | class pbft_operation_test_common : public Test
method pbft_operation_test_common (line 65) | pbft_operation_test_common()
function TEST_F (line 77) | TEST_F(pbft_operation_test_common, initially_unprepared)
function TEST_F (line 85) | TEST_F(pbft_operation_test_common, prepared_after_all_msgs)
function TEST_F (line 103) | TEST_F(pbft_operation_test_common, not_prepared_without_request)
function TEST_F (line 121) | TEST_F(pbft_operation_test_common, not_prepared_without_preprepare)
function TEST_F (line 137) | TEST_F(pbft_operation_test_common, not_prepared_with_2f)
function TEST_F (line 155) | TEST_F(pbft_operation_test_common, prepared_with_2f_PLUS_1)
function TEST_F (line 173) | TEST_F(pbft_operation_test_common, remembers_preprepare)
function TEST_F (line 185) | TEST_F(pbft_operation_test_common, remembers_multiple_distinct_prepares)
function TEST_F (line 204) | TEST_F(pbft_operation_test_common, ignores_duplicate_prepares)
FILE: pbft/operations/test/pbft_persistent_operation_test.cpp
function record_pbft_messages (line 34) | void record_pbft_messages(int from, int until, pbft_msg_type type, std::...
function record_request (line 53) | void record_request(std::shared_ptr<bzn::pbft_operation> op, uint64_t no...
class persistent_operation_test (line 66) | class persistent_operation_test : public Test
function TEST_F (line 82) | TEST_F(persistent_operation_test, remembers_state_after_rehydrate)
function TEST_F (line 102) | TEST_F(persistent_operation_test, remembers_request_after_rehydrate)
function TEST_F (line 117) | TEST_F(persistent_operation_test, continue_progressing_state_after_rehyd...
function TEST_F (line 143) | TEST_F(persistent_operation_test, no_contamination_from_different_request)
function TEST_F (line 167) | TEST_F(persistent_operation_test, remembers_messages_after_rehydrate)
function TEST_F (line 184) | TEST_F(persistent_operation_test, test_prepared_in_range)
function TEST_F (line 203) | TEST_F(persistent_operation_test, test_remove_range)
FILE: pbft/pbft.cpp
function pbft_msg (line 668) | pbft_msg
function bzn_envelope (line 810) | bzn_envelope
function bzn_envelope (line 821) | bzn_envelope
function bzn_envelope (line 829) | bzn_envelope
function bzn_envelope (line 837) | bzn_envelope
function pbft_msg (line 1345) | pbft_msg
function pbft_msg (line 1370) | pbft_msg
function peer_address_t (line 1673) | const peer_address_t&
function timestamp_t (line 1688) | timestamp_t
function checkpoint_t (line 1821) | checkpoint_t
FILE: pbft/pbft.hpp
type bzn (line 57) | namespace bzn
type test (line 59) | namespace test
class pbft_test_database_response_is_forwarded_to_session_Test (line 62) | class pbft_test_database_response_is_forwarded_to_session_Test
class pbft_test_add_session_to_sessions_waiting_can_add_a_session_and_shutdown_handler_removes_session_from_sessions_waiting_Test (line 63) | class pbft_test_add_session_to_sessions_waiting_can_add_a_session_an...
class pbft_test_pbft_wrap_message_sets_swarm_id_Test (line 64) | class pbft_test_pbft_wrap_message_sets_swarm_id_Test
class pbft_test_ensure_save_all_requests_records_requests_Test (line 65) | class pbft_test_ensure_save_all_requests_records_requests_Test
class pbft (line 71) | class pbft final : public bzn::pbft_base, public bzn::status_provider_...
FILE: pbft/pbft_base.hpp
type bzn (line 26) | namespace bzn
class pbft_base (line 30) | class pbft_base
FILE: pbft/pbft_checkpoint_manager.cpp
function checkpoint_t (line 51) | checkpoint_t
function checkpoint_t (line 58) | checkpoint_t
FILE: pbft/pbft_checkpoint_manager.hpp
type bzn (line 23) | namespace bzn
class pbft_checkpoint_manager (line 35) | class pbft_checkpoint_manager : public std::enable_shared_from_this<pb...
FILE: pbft/pbft_persistent_state.cpp
function bzn_envelope (line 242) | bzn_envelope
FILE: pbft/pbft_persistent_state.hpp
type bzn (line 33) | namespace bzn
class persist_base (line 37) | class persist_base
class persistent (line 84) | class persistent : public persist_base
method persistent (line 90) | persistent(std::shared_ptr<bzn::storage_base> persist_storage, const...
method persistent (line 133) | explicit persistent(const T& value)
method persistent (line 138) | persistent()
method destroy (line 167) | void destroy()
method T (line 181) | const T& value() const
method T (line 202) | static T from_string(const std::string& /*value*/)
method to_string (line 208) | static std::string to_string(const T& /*value*/)
method initialize (line 216) | static void
method initialize (line 241) | static void
method init_kv_container (line 265) | static void
method init_kv_container2 (line 277) | static void
method extract_subkeys (line 288) | static std::tuple<A, B>
method generate_key (line 317) | static std::string generate_key()
method generate_key (line 323) | static std::string generate_key(K k, Rest... rest)
method validate (line 328) | void validate() const
FILE: pbft/pbft_service_base.hpp
type bzn (line 22) | namespace bzn
class pbft_service_base (line 26) | class pbft_service_base
FILE: pbft/test/database_pbft_service_test.cpp
function TEST (line 32) | TEST(database_pbft_service, test_that_on_construction_if_next_request_se...
function TEST (line 44) | TEST(database_pbft_service, test_that_on_construction_if_next_request_se...
function TEST (line 55) | TEST(database_pbft_service, test_that_on_construction_if_next_request_se...
function TEST (line 66) | TEST(database_pbft_service, test_that_failed_storing_of_operation_does_n...
function TEST (line 87) | TEST(database_pbft_service, test_that_executed_operation_fires_callback_...
function TEST (line 128) | TEST(database_pbft_service, test_that_apply_operation_now_is_handled)
function TEST (line 167) | TEST(database_pbft_service, test_that_stored_operation_is_executed_in_or...
type test (line 258) | namespace test
function do_operation (line 260) | void do_operation(uint64_t seq, bzn::database_pbft_service &dps)
function database_msg_seq (line 275) | uint64_t database_msg_seq(const database_msg& msg)
function TEST (line 281) | TEST(database_pbft_service, test_that_set_state_catches_up_backlogged_op...
FILE: pbft/test/pbft_audit_test.cpp
type bzn::test (line 16) | namespace bzn::test
function TEST_F (line 18) | TEST_F(pbft_test, test_local_commit_sends_audit_messages)
function TEST_F (line 47) | TEST_F(pbft_test, primary_sends_primary_status)
function TEST_F (line 59) | TEST_F(pbft_test, nonprimary_does_not_send_primary_status)
FILE: pbft/test/pbft_catchup_test.cpp
type bzn (line 20) | namespace bzn
type test (line 22) | namespace test
function pbft_membership_msg (line 24) | pbft_membership_msg
function is_get_state (line 34) | bool
function is_set_state (line 44) | bool
class pbft_catchup_test (line 56) | class pbft_catchup_test : public pbft_proto_test
method send_get_state_request (line 60) | void send_get_state_request(uint64_t sequence)
method bzn_envelope (line 71) | bzn_envelope
method bzn_envelope (line 91) | bzn_envelope
function TEST_F (line 108) | TEST_F(pbft_catchup_test, node_requests_state_after_unknown_checkpoint)
function TEST_F (line 135) | TEST_F(pbft_catchup_test, node_doesnt_request_state_after_known_checkp...
function TEST_F (line 153) | TEST_F(pbft_catchup_test, primary_provides_state)
function TEST_F (line 172) | TEST_F(pbft_catchup_test, node_adopts_requested_checkpoint)
function TEST_F (line 206) | TEST_F(pbft_catchup_test, node_doesnt_adopt_wrong_checkpoint)
FILE: pbft/test/pbft_checkpoint_tests.cpp
type bzn::test (line 26) | namespace bzn::test
class pbft_checkpoint_test (line 28) | class pbft_checkpoint_test : public Test
method send_checkpoint_messages (line 39) | void send_checkpoint_messages(const checkpoint_t& cp, size_t count =...
function TEST_F (line 60) | TEST_F(pbft_checkpoint_test, test_checkpoint_messages_sent_on_execute)
function TEST_F (line 70) | TEST_F(pbft_checkpoint_test, no_checkpoint_on_message_before_local_state)
function TEST_F (line 78) | TEST_F(pbft_checkpoint_test, unstable_checkpoint_on_local_state_before...
function TEST_F (line 89) | TEST_F(pbft_checkpoint_test, stable_checkpoint_on_message_after_local_...
function TEST_F (line 98) | TEST_F(pbft_checkpoint_test, stable_checkpoint_on_local_state_after_me...
function TEST_F (line 107) | TEST_F(pbft_checkpoint_test, unstable_checkpoint_does_not_discard_stab...
function TEST_F (line 118) | TEST_F(pbft_checkpoint_test, stable_checkpoint_discards_old_stable_che...
function TEST_F (line 126) | TEST_F(pbft_checkpoint_test, initial_checkpoint_matches)
FILE: pbft/test/pbft_newview_test.cpp
type bzn (line 21) | namespace bzn
class pbft_newview_test (line 24) | class pbft_newview_test : public pbft_proto_test
method build_pft_with_mock_crypto (line 28) | std::shared_ptr<mock_crypto_base>
method generate_checkpoint_at_sequence_100 (line 37) | void
method run_transaction_through_primary_times (line 60) | void
method max_faulty_replicas_allowed (line 70) | size_t
function TEST_F (line 76) | TEST_F(pbft_newview_test, make_newview)
function TEST_F (line 106) | TEST_F(pbft_newview_test, test_get_primary)
FILE: pbft/test/pbft_peer_change_test.cpp
class changeover_test (line 63) | class changeover_test : public bzn::test::pbft_test, public testing::Wit...
method changeover_test (line 68) | changeover_test()
method switch_here (line 81) | void switch_here()
method this_change_point (line 91) | unsigned int this_change_point()
method max_change_point (line 96) | unsigned int max_change_point()
method before_list (line 101) | bzn::peers_list_t before_list()
method after_list (line 107) | bzn::peers_list_t after_list()
method do_switch (line 116) | void do_switch()
method set_up_beacon (line 121) | void set_up_beacon()
class changeover_test_operations (line 169) | class changeover_test_operations : public changeover_test
function TEST_P (line 172) | TEST_P(changeover_test_operations, perform_pbft_operation)
class changeover_test_checkpoints (line 211) | class changeover_test_checkpoints : public changeover_test
function TEST_P (line 214) | TEST_P(changeover_test_checkpoints, perform_checkpoinnt)
FILE: pbft/test/pbft_persistent_state_test.cpp
type bzn (line 25) | namespace bzn
class persistent_state_test (line 27) | class persistent_state_test : public Test
function TEST_F (line 33) | TEST_F(persistent_state_test, test_assignment)
function TEST_F (line 42) | TEST_F(persistent_state_test, test_no_storage_generates_exception)
function TEST_F (line 50) | TEST_F(persistent_state_test, no_conversion_generates_exception)
function TEST_F (line 60) | TEST_F(persistent_state_test, uninitialized_map_generates_exception)
function TEST_F (line 66) | TEST_F(persistent_state_test, test_initialize)
function TEST_F (line 80) | TEST_F(persistent_state_test, test_initialize_nested)
function TEST_F (line 94) | TEST_F(persistent_state_test, test_escaping)
function TEST_F (line 125) | TEST_F(persistent_state_test, test_physical_storage)
function TEST_F (line 159) | TEST_F(persistent_state_test, test_conversions)
function TEST_F (line 195) | TEST_F(persistent_state_test, test_forked_alias_generates_exception)
FILE: pbft/test/pbft_proto_test.cpp
type bzn (line 25) | namespace bzn
function checkpoint_msg (line 167) | checkpoint_msg
function TEST_F (line 242) | TEST_F(pbft_proto_test, test_primary_full_checkpoint)
function TEST_F (line 254) | TEST_F(pbft_proto_test, test_primary_quick_checkpoint)
function TEST_F (line 267) | TEST_F(pbft_proto_test, test_backup_full_checkpoint)
function TEST_F (line 280) | TEST_F(pbft_proto_test, test_backup_quick_checkpoint)
FILE: pbft/test/pbft_proto_test.hpp
type bzn (line 18) | namespace bzn
class pbft_proto_test (line 22) | class pbft_proto_test : public pbft_test
method now (line 68) | uint64_t now()
method handle_request (line 72) | void handle_request(const bzn_envelope& msg, const std::shared_ptr<s...
FILE: pbft/test/pbft_test.cpp
type bzn::test (line 22) | namespace bzn::test
function TEST_F (line 25) | TEST_F(pbft_test, test_requests_create_operations)
function TEST_F (line 34) | TEST_F(pbft_test, test_requests_fire_preprepare)
function TEST_F (line 43) | TEST_F(pbft_test, test_forwarded_to_primary_when_not_primary)
function save_sequences (line 62) | void
function TEST_F (line 71) | TEST_F(pbft_test, test_different_requests_get_different_sequences)
function TEST_F (line 86) | TEST_F(pbft_test, test_preprepare_triggers_prepare)
function TEST_F (line 95) | TEST_F(pbft_test, test_wrong_view_preprepare_rejected)
function TEST_F (line 106) | TEST_F(pbft_test, test_no_duplicate_prepares_same_sequence_number)
function TEST_F (line 118) | TEST_F(pbft_test, test_commit_messages_sent)
function TEST_F (line 135) | TEST_F(pbft_test, test_commits_applied)
function TEST_F (line 155) | TEST_F(pbft_test, dummy_pbft_service_does_not_crash)
function TEST_F (line 162) | TEST_F(pbft_test, client_request_does_not_result_in_message_ack)
function TEST_F (line 172) | TEST_F(pbft_test, database_response_is_forwarded_to_session)
function TEST_F (line 188) | TEST_F(pbft_test, add_session_to_sessions_waiting_can_add_a_session_an...
function TEST_F (line 213) | TEST_F(pbft_test, client_request_executed_results_in_message_response)
function TEST_F (line 233) | TEST_F(pbft_test, request_redirect_attaches_session)
function TEST_F (line 257) | TEST_F(pbft_test, late_request_redirect_attaches_session)
function TEST_F (line 283) | TEST_F(pbft_test, bzn_envelope_has_repeated_request_body_field)
function TEST_F (line 309) | TEST_F(pbft_test, ensure_save_all_requests_records_requests)
function TEST_F (line 341) | TEST_F(pbft_test, test_admission_control)
function TEST_F (line 373) | TEST_F(pbft_test, too_big_request_generates_error)
FILE: pbft/test/pbft_test_common.cpp
type bzn::test (line 16) | namespace bzn::test
function now (line 242) | uint64_t now()
function pbft_msg (line 248) | pbft_msg
function pbft_membership_msg (line 256) | pbft_membership_msg
function extract_sender (line 264) | std::string
function bzn_envelope (line 272) | bzn_envelope
function bzn_envelope (line 281) | bzn_envelope
function is_preprepare (line 290) | bool
function is_prepare (line 303) | bool
function is_commit (line 316) | bool
function is_checkpoint (line 329) | bool
function is_join (line 342) | bool
function is_audit (line 355) | bool
function is_viewchange (line 362) | bool
function is_newview (line 370) | bool
function is_swarm_error (line 378) | bool
function bzn_envelope (line 385) | bzn_envelope
function bzn_envelope (line 393) | bzn_envelope
FILE: pbft/test/pbft_test_common.hpp
type bzn::test (line 40) | namespace bzn::test
class pbft_test (line 65) | class pbft_test : public Test
FILE: pbft/test/pbft_timestamp_test.cpp
type bzn (line 21) | namespace bzn
function TEST_F (line 25) | TEST_F(pbft_proto_test, repeated_request_doesnt_generate_preprepare)
function TEST_F (line 54) | TEST_F(pbft_proto_test, similar_request_generates_preprepare)
function TEST_F (line 98) | TEST_F(pbft_proto_test, same_request_from_different_client_generates_p...
function TEST_F (line 127) | TEST_F(pbft_proto_test, old_request_is_rejected)
function TEST_F (line 150) | TEST_F(pbft_proto_test, range_test)
FILE: pbft/test/pbft_viewchange_test.cpp
type bzn (line 23) | namespace bzn
class pbft_viewchange_test (line 25) | class pbft_viewchange_test : public pbft_proto_test
method build_pft_with_mock_crypto (line 30) | std::shared_ptr<mock_crypto_base>
method run_transaction_through_primary_times (line 39) | void
method generate_checkpoint_at_sequence_100 (line 49) | void
function TEST_F (line 64) | TEST_F(pbft_viewchange_test, test_fill_in_missing_pre_prepares)
function TEST_F (line 89) | TEST_F(pbft_viewchange_test, pbft_with_invalid_view_drops_messages)
function TEST_F (line 116) | TEST_F(pbft_viewchange_test, test_is_peer)
function TEST_F (line 129) | TEST_F(pbft_viewchange_test, validate_and_extract_checkpoint_hashes)
function TEST_F (line 170) | TEST_F(pbft_viewchange_test, test_is_valid_viewchange_message)
function TEST_F (line 190) | TEST_F(pbft_viewchange_test, make_viewchange_makes_valid_message)
function TEST_F (line 210) | TEST_F(pbft_viewchange_test, pbft_handle_failure_causes_invalid_view_s...
function TEST_F (line 234) | TEST_F(pbft_viewchange_test, test_prepared_operations_since_last_check...
function TEST_F (line 259) | TEST_F(pbft_viewchange_test, test_save_checkpoint)
function TEST_F (line 283) | TEST_F(pbft_viewchange_test, test_handle_viewchange)
function TEST_F (line 408) | TEST_F(pbft_viewchange_test, is_valid_viewchange_does_not_throw_if_no_...
FILE: peers_beacon/peer_address.hpp
type bzn (line 20) | namespace bzn
type peer_address_t (line 22) | struct peer_address_t
method peer_address_t (line 24) | peer_address_t(std::string host, uint16_t port, std::string name, st...
type std (line 49) | namespace std
type hash<bzn::peer_address_t> (line 51) | struct hash<bzn::peer_address_t>
FILE: peers_beacon/peers_beacon.cpp
function peers_list_t (line 293) | peers_list_t
FILE: peers_beacon/peers_beacon.hpp
type bzn (line 23) | namespace bzn
class peers_beacon (line 25) | class peers_beacon : public peers_beacon_base, public std::enable_shar...
FILE: peers_beacon/peers_beacon_base.hpp
type bzn (line 21) | namespace bzn
class peers_beacon_base (line 26) | class peers_beacon_base
FILE: peers_beacon/test/peers_beacon_tests.cpp
class peers_beacon_test (line 44) | class peers_beacon_test : public Test
method peers_beacon_test (line 53) | peers_beacon_test()
method set_peers_file (line 65) | void set_peers_file(const std::string& peers_data)
function TEST_F (line 78) | TEST_F(peers_beacon_test, test_invalid_json)
function TEST_F (line 86) | TEST_F(peers_beacon_test, test_no_peers)
function TEST_F (line 94) | TEST_F(peers_beacon_test, test_underspecified_peer)
function TEST_F (line 102) | TEST_F(peers_beacon_test, test_bad_port)
function TEST_F (line 110) | TEST_F(peers_beacon_test, test_valid_peers)
function TEST_F (line 128) | TEST_F(peers_beacon_test, test_unnamed_peers)
function TEST_F (line 147) | TEST_F(peers_beacon_test, test_duplicate_peers)
function TEST_F (line 154) | TEST_F(peers_beacon_test, test_changed_list)
function TEST_F (line 165) | TEST_F(peers_beacon_test, test_automatic_refresh)
function TEST_F (line 178) | TEST_F(peers_beacon_test, test_url)
function TEST_F (line 189) | TEST_F(peers_beacon_test, cpr_fetch_constructs_correct_endpoint)
function TEST_F (line 202) | TEST_F(peers_beacon_test, test_esr)
function TEST_F (line 232) | TEST_F(peers_beacon_test, test_halt)
FILE: policy/eviction_base.hpp
type bzn::policy (line 22) | namespace bzn::policy
class eviction_base (line 25) | class eviction_base
method eviction_base (line 28) | eviction_base(std::shared_ptr<bzn::storage_base> storage) : storage{...
FILE: policy/random.cpp
type bzn::policy (line 20) | namespace bzn::policy
FILE: policy/random.hpp
type bzn::policy (line 19) | namespace bzn::policy
class random (line 21) | class random : public eviction_base
method random (line 24) | random(std::shared_ptr<bzn::storage_base> storage) : eviction_base{s...
FILE: policy/test/eviction_test.cpp
function database_msg (line 36) | database_msg
function database_msg (line 55) | database_msg
function generate_expire_key (line 76) | bzn::key_t
function insert_test_values (line 88) | size_t
function insert_ttl_values (line 101) | void
type bzn (line 115) | namespace bzn
function TEST (line 117) | TEST(policy_test, test_that_volatile_ttl_ignores_keys_with_no_ttl)
function TEST (line 138) | TEST(policy_test, test_that_volatile_ttl_returns_only_keys_with_ttl)
function TEST (line 171) | TEST(policy_test, test_that_volatile_ttl_fails_if_there_are_not_enough...
FILE: policy/volatile_ttl.cpp
type bzn::policy (line 25) | namespace bzn::policy
type ttl_item (line 27) | struct ttl_item {bzn::key_t key; size_t value_size; size_t ttl;}
FILE: policy/volatile_ttl.hpp
type bzn::policy (line 19) | namespace bzn::policy
type ttl_item (line 21) | struct ttl_item
class volatile_ttl (line 23) | class volatile_ttl : public eviction_base
method volatile_ttl (line 26) | volatile_ttl(std::shared_ptr<bzn::storage_base> storage) : eviction_...
method generate_expire_key (line 40) | bzn::key_t generate_expire_key(const bzn::uuid_t& uuid, const bzn::k...
FILE: status/status.cpp
function get_uptime (line 28) | std::string get_uptime(const std::chrono::steady_clock::time_point& star...
FILE: status/status.hpp
type bzn (line 25) | namespace bzn
class status (line 27) | class status final : public std::enable_shared_from_this<status>
FILE: status/status_provider_base.hpp
type bzn (line 20) | namespace bzn
class status_provider_base (line 22) | class status_provider_base
FILE: status/test/status_test.cpp
function TEST (line 26) | TEST(status_test, test_that_status_registers_and_responses_to_requests)
function TEST (line 50) | TEST(status_test, test_that_status_request_queries_status_providers)
FILE: storage/mem_storage.hpp
type bzn (line 23) | namespace bzn
class mem_storage (line 25) | class mem_storage : public bzn::storage_base
FILE: storage/rocksdb_storage.cpp
function generate_key (line 28) | inline bzn::key_t generate_key(const bzn::uuid_t& uuid, const bzn::key_t...
FILE: storage/rocksdb_storage.hpp
type bzn (line 24) | namespace bzn
class rocksdb_storage (line 26) | class rocksdb_storage : public bzn::storage_base
FILE: storage/storage_base.hpp
type bzn (line 23) | namespace bzn
type storage_result (line 28) | enum class storage_result : uint8_t
class storage_base (line 63) | class storage_base
FILE: storage/test/storage_test.cpp
function generate_test_string (line 39) | std::string
class storageTest (line 72) | class storageTest : public Test
method storageTest (line 75) | storageTest()
function TYPED_TEST (line 97) | TYPED_TEST(storageTest, test_that_storage_can_create_a_record_and_read_t...
function TYPED_TEST (line 120) | TYPED_TEST(storageTest, test_that_storage_can_retieve_a_key_size)
function TYPED_TEST (line 130) | TYPED_TEST(storageTest, test_that_storage_fails_to_create_a_record_that_...
function TYPED_TEST (line 138) | TYPED_TEST(storageTest, test_that_attempting_to_read_a_record_from_stora...
function TYPED_TEST (line 144) | TYPED_TEST(storageTest, test_that_storage_can_update_an_existing_record)
function TYPED_TEST (line 161) | TYPED_TEST(storageTest, test_that_storage_can_delete_a_record)
function TYPED_TEST (line 177) | TYPED_TEST(storageTest, test_get_keys_returns_all_keys)
function TYPED_TEST (line 221) | TYPED_TEST(storageTest, test_has_returns_true_if_key_exists_false_otherw...
function TYPED_TEST (line 253) | TYPED_TEST(storageTest, test_that_storage_fails_to_create_a_value_that_e...
function TYPED_TEST (line 262) | TYPED_TEST(storageTest, test_that_storage_fails_to_update_with_a_value_t...
function TYPED_TEST (line 276) | TYPED_TEST(storageTest, test_that_storage_can_remove_all_keys_values_ass...
function TYPED_TEST (line 286) | TYPED_TEST(storageTest, test_snapshot)
function TYPED_TEST (line 309) | TYPED_TEST(storageTest, test_range_queries)
function TYPED_TEST (line 339) | TYPED_TEST(storageTest, test_predicate_queries)
function TYPED_TEST (line 379) | TYPED_TEST(storageTest, test_regex_match_queries)
FILE: swarm/main.cpp
function init_logging (line 51) | void
function get_dir_size (line 104) | boost::uintmax_t
function print_banner (line 137) | void
function start_worker_threads_and_wait (line 160) | void
function main (line 194) | int
FILE: utils/blacklist.cpp
function clean_uuid (line 24) | bzn::uuid_t
type bzn::utils::blacklist (line 34) | namespace bzn::utils::blacklist
function is_blacklisted (line 36) | bool
FILE: utils/blacklist.hpp
type bzn::utils::blacklist (line 20) | namespace bzn::utils::blacklist
FILE: utils/bytes_to_debug_string.hpp
type bzn (line 19) | namespace bzn
FILE: utils/crypto.cpp
function calculate_decode_length (line 53) | size_t
function compose_and_log_OpenSSL_error (line 66) | void
function RSA (line 82) | RSA* create_public_RSA(const std::string& key)
function RSA_verify_signature (line 109) | bool
type bzn::utils::crypto (line 158) | namespace bzn::utils::crypto
function base64_decode (line 160) | int
function verify_signature (line 201) | bool
function read_pem_file (line 227) | std::string read_pem_file(const std::string& filename, const std::stri...
FILE: utils/crypto.hpp
type bzn::utils::crypto (line 19) | namespace bzn::utils::crypto
FILE: utils/esr_peer_info.cpp
function trim_right_nulls (line 32) | void
function str_to_json (line 39) | bzn::json_message
function make_params (line 57) | bzn::json_message
function make_request (line 70) | std::string
function hex_to_char_string (line 84) | std::string
function parse_get_peers_result_to_vector (line 94) | std::vector<std::string>
function parse_get_peer_info_result_to_peer_address (line 184) | bzn::peer_address_t
function pad_str_to_mod_64 (line 295) | std::string
function size_type_to_hex (line 308) | std::string
function string_to_hex (line 318) | std::string
function data_string_for_get_peers (line 328) | const std::string
type bzn::utils::esr (line 343) | namespace bzn::utils::esr
function data_string_for_get_peer_info (line 345) | const std::string
FILE: utils/http_req.cpp
type bzn (line 45) | namespace bzn
FILE: utils/make_endpoint.hpp
type bzn (line 20) | namespace bzn
FILE: utils/test/make_endpoint_test.cpp
function TEST (line 21) | TEST(make_endpoint, test_test_valid_host_name_returns_correct_address)
function TEST (line 32) | TEST(make_endpoint, test_test_invalid_host_name_returns_nothing)
function TEST (line 42) | TEST(make_endpoint, test_test_dotted_v4_address_returns_address)
FILE: utils/test/utils_test.cpp
function TEST (line 343) | TEST(util_test, test_that_is_blacklisted_member_returns_TRUE_if_uuid_IS_...
function TEST (line 355) | TEST(util_test, test_that_is_whitelist_member_returns_FALSE_if_uuid_is_N...
function TEST (line 361) | TEST(util_test, test_that_a_poorly_formed_uuid_fails)
function TEST (line 367) | TEST(util_test, test_that_openssl_based_base64_encoding_works_correctly)
function TEST (line 377) | TEST(util_test, test_that_a_uuid_can_be_validated)
function TEST (line 384) | TEST(util_test, test_that_verifying_a_signature_with_empty_inputs_will_f...
function TEST (line 392) | TEST(util_test, test_that_esr_returns_peers_list)
function TEST (line 414) | TEST(util_test, test_that_esr_returns_peers_list_with_deletions)
function TEST (line 430) | TEST(util_test, test_that_esr_fails_nicely)
function TEST (line 446) | TEST(util_test, test_that_esr_works_with_large_swarm_id)
function TEST (line 461) | TEST(util_test, test_that_esr_returns_peer_info_with_large_node_name)
function TEST (line 477) | TEST(util_test, test_that_live_esr_returns_peer_info)
type bzn::utils::esr (line 507) | namespace bzn::utils::esr
function TEST (line 514) | TEST(util_test, test_request_data_validity)
FILE: utils/utils_interface.hpp
type bzn (line 18) | namespace bzn
class utils_interface (line 20) | class utils_interface : public utils_interface_base
FILE: utils/utils_interface_base.hpp
type bzn (line 22) | namespace bzn
class utils_interface_base (line 24) | class utils_interface_base
Condensed preview — 221 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,337K chars).
[
{
"path": ".gitignore",
"chars": 191,
"preview": ".idea/\n.state/\nbuild/\nlogs/\ncmake-build-debug/\ncmake-build-release/\nscripts/bluzelle_pb2.py\nscripts/database_pb2.py\nscri"
},
{
"path": ".travis.yml",
"chars": 6969,
"preview": "sudo: false\nlanguage: cpp\n\nenv:\n global:\n - PROJECT_VERSION_MAJOR=\"0\"\n - PROJECT_VERSION_MINOR=\"7\"\n - PROJECT_"
},
{
"path": "CMakeLists.txt",
"chars": 4201,
"preview": "cmake_minimum_required(VERSION 3.10)\n\nproject(bluzelle CXX)\n\n# ensure type is set\nif (NOT CMAKE_BUILD_TYPE)\n set(CMAK"
},
{
"path": "CONTRIBUTOR.md",
"chars": 14697,
"preview": "# Contributing to Bluzelle\n\nWelcome to wanting to contribute to Bluzelle! Thank you for taking your time to contribute. "
},
{
"path": "LICENSE",
"chars": 34520,
"preview": " GNU AFFERO GENERAL PUBLIC LICENSE\n Version 3, 19 November 2007\n\n Copyright (C)"
},
{
"path": "README.md",
"chars": 15919,
"preview": "# SwarmDB\n\n[](https://travis-ci.org/bluzelle/swa"
},
{
"path": "SUMMARY.md",
"chars": 84,
"preview": "# Table of contents\n\n* [SwarmDB](README.md)\n* [Python CRUD Test App](scripts-1.md)\n\n"
},
{
"path": "audit/CMakeLists.txt",
"chars": 280,
"preview": "add_library(audit\n audit_base.hpp\n audit.hpp\n audit.cpp\n ../mocks/mock_pbft_base.hpp)\n\ntarget_li"
},
{
"path": "audit/audit.cpp",
"chars": 6544,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "audit/audit.hpp",
"chars": 2746,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "audit/audit_base.hpp",
"chars": 1301,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "audit/test/CMakeLists.txt",
"chars": 103,
"preview": "set(test_srcs audit_test.cpp)\nset(test_libs audit proto ${Protobuf_LIBRARIES})\n\nadd_gmock_test(audit)\n"
},
{
"path": "audit/test/audit_test.cpp",
"chars": 7973,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "chaos/CMakeLists.txt",
"chars": 253,
"preview": "add_library(chaos\n chaos.hpp\n chaos.cpp\n chaos_base.hpp\n )\n\ntarget_link_libraries(chaos opti"
},
{
"path": "chaos/chaos.cpp",
"chars": 3944,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "chaos/chaos.hpp",
"chars": 1705,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "chaos/chaos_base.hpp",
"chars": 1505,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "chaos/test/CMakeLists.txt",
"chars": 82,
"preview": "set(test_srcs chaos_test.cpp)\nset(test_libs chaos options)\n\nadd_gmock_test(chaos)\n"
},
{
"path": "chaos/test/chaos_test.cpp",
"chars": 4823,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "cmake/add_gmock_test.cmake",
"chars": 1188,
"preview": "# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "cmake/boost.cmake",
"chars": 2514,
"preview": "# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "cmake/git_commit.cmake",
"chars": 1265,
"preview": "# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "cmake/googletest.cmake",
"chars": 1342,
"preview": "# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "cmake/jsoncpp.cmake",
"chars": 1513,
"preview": "# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "cmake/openssl.cmake",
"chars": 1791,
"preview": "# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "cmake/rocksdb.cmake",
"chars": 3040,
"preview": "# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "cmake/static_analysis.cmake",
"chars": 1310,
"preview": "# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "cmake/static_analysis.sh",
"chars": 1672,
"preview": "#!/usr/bin/env bash\n\n# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or mod"
},
{
"path": "cmake/swarm_git_commit.hpp.in",
"chars": 701,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "cmake/swarm_version.cmake",
"chars": 988,
"preview": "# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "cmake/swarm_version.hpp.in",
"chars": 697,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crud/CMakeLists.txt",
"chars": 342,
"preview": "add_library(crud STATIC\n crud_base.hpp\n subscription_manager.cpp\n subscription_manager.hpp\n subscription_man"
},
{
"path": "crud/crud.cpp",
"chars": 44854,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crud/crud.hpp",
"chars": 7236,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crud/crud_base.hpp",
"chars": 1306,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crud/subscription_manager.cpp",
"chars": 10170,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crud/subscription_manager.hpp",
"chars": 2174,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crud/subscription_manager_base.hpp",
"chars": 1608,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crud/test/CMakeLists.txt",
"chars": 188,
"preview": "set(test_srcs crud_test.cpp subscription_manager_test.cpp)\nset(test_libs crud pbft pbft_operations node storage peers_be"
},
{
"path": "crud/test/crud_test.cpp",
"chars": 140250,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crud/test/subscription_manager_test.cpp",
"chars": 16210,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crypto/CMakeLists.txt",
"chars": 264,
"preview": "add_library(crypto\n crypto_base.hpp\n crypto.hpp\n crypto.cpp\n )\n\ntarget_link_libraries(crypto"
},
{
"path": "crypto/crypto.cpp",
"chars": 10793,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crypto/crypto.hpp",
"chars": 2084,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crypto/crypto_base.hpp",
"chars": 1570,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "crypto/test/CMakeLists.txt",
"chars": 113,
"preview": "set(test_srcs crypto_test.cpp)\nset(test_libs crypto proto options ${Protobuf_LIBRARIES})\n\nadd_gmock_test(crypto)\n"
},
{
"path": "crypto/test/crypto_test.cpp",
"chars": 6875,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "depend/CMakeLists.txt",
"chars": 1568,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/README.md",
"chars": 3078,
"preview": "swarmDB uses several precompiled libraries for faster CI builds.\n\n##### Set the required library build number in depend/"
},
{
"path": "depend/boost/CMakeLists.txt",
"chars": 1260,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/boost/package/.gitattributes",
"chars": 556,
"preview": "boost-debug-1.68.0-linux.tar.gz filter=lfs diff=lfs merge=lfs -text\nboost-release-1.68.0-linux.tar.gz filter=lfs diff=lf"
},
{
"path": "depend/boost/package/CMakeLists.txt",
"chars": 2740,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/googletest/CMakeLists.txt",
"chars": 1054,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/googletest/package/.gitattributes",
"chars": 294,
"preview": "googletest-debug-1.8.0-linux.tar.gz filter=lfs diff=lfs merge=lfs -text\ngoogletest-release-1.8.0-linux.tar.gz filter=lfs"
},
{
"path": "depend/googletest/package/CMakeLists.txt",
"chars": 2237,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/jsoncpp/CMakeLists.txt",
"chars": 820,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/jsoncpp/package/.gitattributes",
"chars": 282,
"preview": "jsoncpp-debug-1.8.4-linux.tar.gz filter=lfs diff=lfs merge=lfs -text\njsoncpp-release-1.8.4-linux.tar.gz filter=lfs diff="
},
{
"path": "depend/jsoncpp/package/CMakeLists.txt",
"chars": 2333,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/openssl/CMakeLists.txt",
"chars": 877,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/openssl/package/.gitattributes",
"chars": 282,
"preview": "openssl-debug-1.1.1-linux.tar.gz filter=lfs diff=lfs merge=lfs -text\nopenssl-release-1.1.1-linux.tar.gz filter=lfs diff="
},
{
"path": "depend/openssl/package/CMakeLists.txt",
"chars": 2529,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/rocksdb/CMakeLists.txt",
"chars": 2305,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "depend/rocksdb/package/.gitattributes",
"chars": 286,
"preview": "rocksdb-debug-5.14.3-linux.tar.gz filter=lfs diff=lfs merge=lfs -text\nrocksdb-release-5.14.3-linux.tar.gz filter=lfs dif"
},
{
"path": "depend/rocksdb/package/CMakeLists.txt",
"chars": 2522,
"preview": "# Copyright (C) 2019 Bluzelle\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "include/bluzelle.hpp",
"chars": 1781,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "include/boost_asio_beast.hpp",
"chars": 19493,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "include/system_clock.hpp",
"chars": 1149,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/CMakeLists.txt",
"chars": 349,
"preview": "add_library(smart_mocks STATIC\n smart_mock_node.hpp\n smart_mock_node.cpp\n smart_mock_io.hpp\n "
},
{
"path": "mocks/mock_boost_asio_beast.hpp",
"chars": 6053,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_chaos_base.hpp",
"chars": 1017,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_crud_base.hpp",
"chars": 1290,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_crypto_base.hpp",
"chars": 1052,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_monitor.hpp",
"chars": 1066,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_node_base.hpp",
"chars": 2140,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_options_base.hpp",
"chars": 3033,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_pbft_base.hpp",
"chars": 1663,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_pbft_failure_detector.hpp",
"chars": 1092,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_pbft_service_base.hpp",
"chars": 1755,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_peers_beacon_base.hpp",
"chars": 1220,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_session_base.hpp",
"chars": 1643,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_status_provider_base.hpp",
"chars": 1003,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_storage_base.hpp",
"chars": 2957,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_subscription_manager_base.hpp",
"chars": 1326,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_system_clock.hpp",
"chars": 873,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/mock_utils_interface.hpp",
"chars": 778,
"preview": "#pragma once\n#include <utils/utils_interface.hpp>\n\nnamespace bzn {\n\n class mock_utils_interface_base : public utils_i"
},
{
"path": "mocks/smart_mock_io.cpp",
"chars": 8910,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/smart_mock_io.hpp",
"chars": 1914,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/smart_mock_node.cpp",
"chars": 1796,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/smart_mock_node.hpp",
"chars": 993,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/smart_mock_peers_beacon.cpp",
"chars": 1980,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "mocks/smart_mock_peers_beacon.hpp",
"chars": 909,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "monitor/CMakeLists.txt",
"chars": 257,
"preview": "add_library(monitor\n monitor_base.hpp\n monitor.hpp\n monitor.cpp\n )\n\nadd_dependencies(monitor"
},
{
"path": "monitor/monitor.cpp",
"chars": 6267,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "monitor/monitor.hpp",
"chars": 2043,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "monitor/monitor_base.hpp",
"chars": 2321,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "monitor/test/CMakeLists.txt",
"chars": 88,
"preview": "set(test_srcs monitor_test.cpp)\nset(test_libs monitor options)\n\nadd_gmock_test(monitor)\n"
},
{
"path": "monitor/test/monitor_test.cpp",
"chars": 9090,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "node/CMakeLists.txt",
"chars": 501,
"preview": "add_library(node STATIC\n ../include/bluzelle.hpp\n ../include/boost_asio_beast.hpp\n ../mocks/mock_bo"
},
{
"path": "node/node.cpp",
"chars": 12128,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "node/node.hpp",
"chars": 4465,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "node/node_base.hpp",
"chars": 5084,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "node/session.cpp",
"chars": 11679,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "node/session.hpp",
"chars": 3842,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "node/session_base.hpp",
"chars": 3047,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "node/test/CMakeLists.txt",
"chars": 143,
"preview": "set(test_srcs node_test.cpp session_test.cpp)\nset(test_libs node proto options crypto smart_mocks ${Protobuf_LIBRARIES})"
},
{
"path": "node/test/node_test.cpp",
"chars": 10756,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "node/test/session_test.cpp",
"chars": 9039,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "options/CMakeLists.txt",
"chars": 359,
"preview": "add_library(options STATIC\n ../include/bluzelle.hpp\n options.cpp\n options.hpp\n options_base."
},
{
"path": "options/options.cpp",
"chars": 6808,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "options/options.hpp",
"chars": 2836,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "options/options_base.hpp",
"chars": 7035,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "options/simple_options.cpp",
"chars": 17215,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "options/simple_options.hpp",
"chars": 5807,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "options/test/CMakeLists.txt",
"chars": 86,
"preview": "set(test_srcs options_test.cpp)\nset(test_libs options utils)\n\nadd_gmock_test(options)\n"
},
{
"path": "options/test/options_test.cpp",
"chars": 13288,
"preview": "// Copyright (c) 2017-2018 Bluzelle Networks\n//\n// This file is part of Bluzelle.\n//\n// Bluzelle is free software: you c"
},
{
"path": "pbft/CMakeLists.txt",
"chars": 516,
"preview": "add_library(pbft STATIC\n pbft_base.hpp\n pbft.hpp\n pbft.cpp\n dummy_pbft_service.cpp\n dummy_pbft_service.hp"
},
{
"path": "pbft/database_pbft_service.cpp",
"chars": 9062,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/database_pbft_service.hpp",
"chars": 2932,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/dummy_pbft_service.cpp",
"chars": 3179,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/dummy_pbft_service.hpp",
"chars": 2271,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/CMakeLists.txt",
"chars": 435,
"preview": "add_library(pbft_operations STATIC\n pbft_operation.hpp\n pbft_operation.cpp\n pbft_memory_operation.hpp\n pbft_"
},
{
"path": "pbft/operations/pbft_memory_operation.cpp",
"chars": 5982,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/pbft_memory_operation.hpp",
"chars": 2607,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/pbft_operation.cpp",
"chars": 1607,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/pbft_operation.hpp",
"chars": 5815,
"preview": "// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General "
},
{
"path": "pbft/operations/pbft_operation_manager.cpp",
"chars": 4747,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/pbft_operation_manager.hpp",
"chars": 2142,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/pbft_persistent_operation.cpp",
"chars": 15719,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/pbft_persistent_operation.hpp",
"chars": 3643,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/test/CMakeLists.txt",
"chars": 252,
"preview": "set(test_srcs\n pbft_operation_test_common.cpp\n pbft_persistent_operation_test.cpp\n pbft_operation_m"
},
{
"path": "pbft/operations/test/pbft_operation_manager_test.cpp",
"chars": 4973,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/test/pbft_operation_test_common.cpp",
"chars": 7320,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/operations/test/pbft_persistent_operation_test.cpp",
"chars": 9756,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/pbft.cpp",
"chars": 65158,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/pbft.hpp",
"chars": 14908,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/pbft_base.hpp",
"chars": 1772,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/pbft_checkpoint_manager.cpp",
"chars": 11128,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/pbft_checkpoint_manager.hpp",
"chars": 3227,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/pbft_persistent_state.cpp",
"chars": 6638,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/pbft_persistent_state.hpp",
"chars": 16437,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/pbft_service_base.hpp",
"chars": 5438,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/CMakeLists.txt",
"chars": 505,
"preview": "set(test_srcs\n pbft_test.cpp\n pbft_audit_test.cpp\n pbft_test_common.cpp\n pbft_checkpoint_tests.cpp\n pbft_"
},
{
"path": "pbft/test/database_pbft_service_test.cpp",
"chars": 12578,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_audit_test.cpp",
"chars": 2814,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_catchup_test.cpp",
"chars": 8439,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_checkpoint_tests.cpp",
"chars": 5259,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_newview_test.cpp",
"chars": 4743,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_peer_change_test.cpp",
"chars": 8657,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_persistent_state_test.cpp",
"chars": 9175,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_proto_test.cpp",
"chars": 9552,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_proto_test.hpp",
"chars": 2620,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_test.cpp",
"chars": 14389,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_test_common.cpp",
"chars": 12939,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_test_common.hpp",
"chars": 6858,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_timestamp_test.cpp",
"chars": 6415,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pbft/test/pbft_viewchange_test.cpp",
"chars": 18621,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "peers_beacon/CMakeLists.txt",
"chars": 334,
"preview": "add_library(peers_beacon STATIC\n peer_address.hpp\n peers_beacon_base.hpp\n peers_beacon.cpp\n "
},
{
"path": "peers_beacon/peer_address.hpp",
"chars": 1613,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "peers_beacon/peers_beacon.cpp",
"chars": 9895,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "peers_beacon/peers_beacon.hpp",
"chars": 2669,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "peers_beacon/peers_beacon_base.hpp",
"chars": 1431,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "peers_beacon/test/CMakeLists.txt",
"chars": 122,
"preview": "set(test_srcs peers_beacon_tests.cpp)\nset(test_libs peers_beacon utils options smart_mocks)\n\nadd_gmock_test(peers_beacon"
},
{
"path": "peers_beacon/test/peers_beacon_tests.cpp",
"chars": 8528,
"preview": "// Copyright (C) 2019 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "pkg/CMakeLists.txt",
"chars": 394,
"preview": "if (UNIX AND NOT APPLE)\n install(PROGRAMS \"${PROJECT_BINARY_DIR}/output/swarm\" DESTINATION \"/usr/bin/\")\n\n find_pr"
},
{
"path": "pkg/debian/CMakeLists.txt",
"chars": 1542,
"preview": "message( \"Building version: ${PROJECT_VERSION}...\" )\n\nset(BOOST_DEB_VERSION \"${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSIO"
},
{
"path": "pkg/debian/postinst",
"chars": 441,
"preview": "#! /bin/sh\n\nset -e\n\necho \" _____ ____ ____\"\necho \" / ___/ ______ __________ ___ /"
},
{
"path": "pkg/debian/postrm",
"chars": 40,
"preview": "#! /bin/sh\n\nset -e\n\nrm -f /usr/bin/swarm"
},
{
"path": "policy/CMakeLists.txt",
"chars": 231,
"preview": "add_library(policy STATIC\n eviction_base.hpp\n random.cpp\n volatile_ttl.cpp\n )\n\nadd_dependenc"
},
{
"path": "policy/eviction_base.hpp",
"chars": 1176,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "policy/random.cpp",
"chars": 3543,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "policy/random.hpp",
"chars": 975,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "policy/test/CMakeLists.txt",
"chars": 116,
"preview": "set(test_srcs eviction_test.cpp)\n\nset(test_libs policy proto storage ${Protobuf_LIBRARIES})\n\nadd_gmock_test(policy)\n"
},
{
"path": "policy/test/eviction_test.cpp",
"chars": 7611,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "policy/volatile_ttl.cpp",
"chars": 6396,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "policy/volatile_ttl.hpp",
"chars": 1715,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "proto/CMakeLists.txt",
"chars": 290,
"preview": "protobuf_generate_cpp(PROTO_SRC PROTO_HEADER bluzelle.proto database.proto pbft.proto audit.proto status.proto)\nadd_libr"
},
{
"path": "proto/audit.proto",
"chars": 1243,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "proto/bluzelle.proto",
"chars": 1318,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "proto/database.proto",
"chars": 4710,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "proto/pbft.proto",
"chars": 2978,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "proto/status.proto",
"chars": 886,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "qa/integration-tests.sh",
"chars": 520,
"preview": "#!/usr/bin/env bash\n\ncd ../..\n\ngit clone git@github.com:bluzelle/bluzelle-js.git\n\ncd bluzelle-js\n\nyarn\n\nif [ \"$1\" == \"se"
},
{
"path": "scripts/crud",
"chars": 18639,
"preview": "#!/usr/bin/env python2.7\n\n# Copyright (C) 2018 Bluzelle\n#\n# This program is free software: you can redistribute it and/o"
},
{
"path": "scripts/generate-key",
"chars": 453,
"preview": "#!/bin/bash\nset -e\n\nprefix=${1:-`pwd`/.state}\n\nmkdir -p $prefix\n\n# This is a very popular curve, which openssl has speci"
},
{
"path": "scripts/sign_uuid.sh",
"chars": 2282,
"preview": "#!/usr/bin/env bash\n\n\nusage()\n{\n echo \"usage: sign_uuid -k path/to/private.pem -u <uuid_of_node>\"\n echo \"The outpu"
},
{
"path": "scripts-1.md",
"chars": 664,
"preview": "# Python CRUD Test App\n\nSteps to run the Bluzelle SwarmDB test application in a Python Virtual Environment. **Ensure tha"
},
{
"path": "status/CMakeLists.txt",
"chars": 256,
"preview": "add_library(status STATIC\n status.cpp\n status.hpp\n )\n\ntarget_link_libraries(status proto)\nadd_depen"
},
{
"path": "status/status.cpp",
"chars": 3398,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "status/status.hpp",
"chars": 1590,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "status/status_provider_base.hpp",
"chars": 1085,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "status/test/CMakeLists.txt",
"chars": 99,
"preview": "set(test_srcs status_test.cpp)\nset(test_libs status ${Protobuf_LIBRARIES})\n\nadd_gmock_test(status)\n"
},
{
"path": "status/test/status_test.cpp",
"chars": 3942,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "storage/CMakeLists.txt",
"chars": 310,
"preview": "add_library(storage STATIC\n mem_storage.cpp\n mem_storage.hpp\n storage_base.hpp\n rocksdb_storage.hpp\n rock"
},
{
"path": "storage/mem_storage.cpp",
"chars": 9629,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "storage/mem_storage.hpp",
"chars": 3071,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "storage/rocksdb_storage.cpp",
"chars": 15668,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "storage/rocksdb_storage.hpp",
"chars": 3669,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "storage/storage_base.hpp",
"chars": 3964,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
},
{
"path": "storage/test/CMakeLists.txt",
"chars": 193,
"preview": "set(test_srcs storage_test.cpp)\nset(test_libs storage node)\nset(test_deps rocksdb)\nset(test_link pbft pbft_operations pr"
},
{
"path": "storage/test/storage_test.cpp",
"chars": 16101,
"preview": "// Copyright (C) 2018 Bluzelle\n//\n// This program is free software: you can redistribute it and/or modify\n// it under th"
}
]
// ... and 21 more files (download for full content)
About this extraction
This page contains the full source code of the bluzelle/swarmDB GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 221 files (2.2 MB), approximately 576.6k tokens, and a symbol index with 723 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.