Compare commits
1 Commits
br-next
...
mykaul-doc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f03bf2362 |
24
.github/CODEOWNERS
vendored
24
.github/CODEOWNERS
vendored
@@ -12,7 +12,7 @@ test/cql/cdc_* @kbr- @elcallio @piodul @jul-stas
|
||||
test/boost/cdc_* @kbr- @elcallio @piodul @jul-stas
|
||||
|
||||
# COMMITLOG / BATCHLOG
|
||||
db/commitlog/* @elcallio @eliransin
|
||||
db/commitlog/* @elcallio
|
||||
db/batch* @elcallio
|
||||
|
||||
# COORDINATOR
|
||||
@@ -25,7 +25,7 @@ compaction/* @raphaelsc @nyh
|
||||
transport/*
|
||||
|
||||
# CQL QUERY LANGUAGE
|
||||
cql3/* @tgrabiec @cvybhu @nyh
|
||||
cql3/* @tgrabiec @psarna @cvybhu
|
||||
|
||||
# COUNTERS
|
||||
counters* @jul-stas
|
||||
@@ -33,7 +33,7 @@ tests/counter_test* @jul-stas
|
||||
|
||||
# DOCS
|
||||
docs/* @annastuchlik @tzach
|
||||
docs/alternator @annastuchlik @tzach @nyh @havaker @nuivall
|
||||
docs/alternator @annastuchlik @tzach @nyh @psarna
|
||||
|
||||
# GOSSIP
|
||||
gms/* @tgrabiec @asias
|
||||
@@ -45,9 +45,9 @@ dist/docker/*
|
||||
utils/logalloc* @tgrabiec
|
||||
|
||||
# MATERIALIZED VIEWS
|
||||
db/view/* @nyh @cvybhu @piodul
|
||||
cql3/statements/*view* @nyh @cvybhu @piodul
|
||||
test/boost/view_* @nyh @cvybhu @piodul
|
||||
db/view/* @nyh @psarna
|
||||
cql3/statements/*view* @nyh @psarna
|
||||
test/boost/view_* @nyh @psarna
|
||||
|
||||
# PACKAGING
|
||||
dist/* @syuu1228
|
||||
@@ -62,9 +62,9 @@ service/migration* @tgrabiec @nyh
|
||||
schema* @tgrabiec @nyh
|
||||
|
||||
# SECONDARY INDEXES
|
||||
index/* @nyh @cvybhu @piodul
|
||||
cql3/statements/*index* @nyh @cvybhu @piodul
|
||||
test/boost/*index* @nyh @cvybhu @piodul
|
||||
db/index/* @nyh @psarna
|
||||
cql3/statements/*index* @nyh @psarna
|
||||
test/boost/*index* @nyh @psarna
|
||||
|
||||
# SSTABLES
|
||||
sstables/* @tgrabiec @raphaelsc @nyh
|
||||
@@ -74,11 +74,11 @@ streaming/* @tgrabiec @asias
|
||||
service/storage_service.* @tgrabiec @asias
|
||||
|
||||
# ALTERNATOR
|
||||
alternator/* @nyh @havaker @nuivall
|
||||
test/alternator/* @nyh @havaker @nuivall
|
||||
alternator/* @nyh @psarna
|
||||
test/alternator/* @nyh @psarna
|
||||
|
||||
# HINTED HANDOFF
|
||||
db/hints/* @piodul @vladzcloudius @eliransin
|
||||
db/hints/* @piodul @vladzcloudius
|
||||
|
||||
# REDIS
|
||||
redis/* @nyh @syuu1228
|
||||
|
||||
17
.github/workflows/docs-amplify-enhanced.yaml
vendored
17
.github/workflows/docs-amplify-enhanced.yaml
vendored
@@ -1,17 +0,0 @@
|
||||
name: "Docs / Amplify enhanced"
|
||||
|
||||
on: issue_comment
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.issue.pull_request }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Amplify enhanced
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
uses: scylladb/sphinx-scylladb-theme/.github/actions/amplify-enhanced@master
|
||||
13
.github/workflows/docs-pages.yaml
vendored
13
.github/workflows/docs-pages.yaml
vendored
@@ -2,14 +2,10 @@ name: "Docs / Publish"
|
||||
# For more information,
|
||||
# see https://sphinx-theme.scylladb.com/stable/deployment/production.html#available-workflows
|
||||
|
||||
env:
|
||||
FLAG: ${{ github.repository == 'scylladb/scylla-enterprise' && 'enterprise' || 'opensource' }}
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'enterprise'
|
||||
- master
|
||||
paths:
|
||||
- "docs/**"
|
||||
workflow_dispatch:
|
||||
@@ -28,13 +24,12 @@ jobs:
|
||||
with:
|
||||
python-version: 3.7
|
||||
- name: Set up env
|
||||
run: make -C docs FLAG="${{ env.FLAG }}" setupenv
|
||||
run: make -C docs setupenv
|
||||
- name: Build docs
|
||||
run: make -C docs FLAG="${{ env.FLAG }}" multiversion
|
||||
run: make -C docs multiversion
|
||||
- name: Build redirects
|
||||
run: make -C docs FLAG="${{ env.FLAG }}" redirects
|
||||
run: make -C docs redirects
|
||||
- name: Deploy docs to GitHub Pages
|
||||
run: ./docs/_utils/deploy.sh
|
||||
if: (github.ref_name == 'master' && env.FLAG == 'opensource') || (github.ref_name == 'enterprise' && env.FLAG == 'enterprise')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
8
.github/workflows/docs-pr.yaml
vendored
8
.github/workflows/docs-pr.yaml
vendored
@@ -2,14 +2,10 @@ name: "Docs / Build PR"
|
||||
# For more information,
|
||||
# see https://sphinx-theme.scylladb.com/stable/deployment/production.html#available-workflows
|
||||
|
||||
env:
|
||||
FLAG: ${{ github.repository == 'scylladb/scylla-enterprise' && 'enterprise' || 'opensource' }}
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- enterprise
|
||||
paths:
|
||||
- "docs/**"
|
||||
|
||||
@@ -27,6 +23,6 @@ jobs:
|
||||
with:
|
||||
python-version: 3.7
|
||||
- name: Set up env
|
||||
run: make -C docs FLAG="${{ env.FLAG }}" setupenv
|
||||
run: make -C docs setupenv
|
||||
- name: Build docs
|
||||
run: make -C docs FLAG="${{ env.FLAG }}" test
|
||||
run: make -C docs test
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -32,3 +32,4 @@ compile_commands.json
|
||||
.ccls-cache/
|
||||
.mypy_cache
|
||||
.envrc
|
||||
rust/Cargo.lock
|
||||
|
||||
9
.gitmodules
vendored
9
.gitmodules
vendored
@@ -6,6 +6,12 @@
|
||||
path = swagger-ui
|
||||
url = ../scylla-swagger-ui
|
||||
ignore = dirty
|
||||
[submodule "libdeflate"]
|
||||
path = libdeflate
|
||||
url = ../libdeflate
|
||||
[submodule "abseil"]
|
||||
path = abseil
|
||||
url = ../abseil-cpp
|
||||
[submodule "scylla-jmx"]
|
||||
path = tools/jmx
|
||||
url = ../scylla-jmx
|
||||
@@ -15,6 +21,3 @@
|
||||
[submodule "scylla-python3"]
|
||||
path = tools/python3
|
||||
url = ../scylla-python3
|
||||
[submodule "tools/cqlsh"]
|
||||
path = tools/cqlsh
|
||||
url = ../scylla-cqlsh
|
||||
|
||||
883
CMakeLists.txt
883
CMakeLists.txt
@@ -2,200 +2,803 @@ cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
project(scylla)
|
||||
|
||||
include(CTest)
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to 'Release' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE
|
||||
STRING "Choose the type of build." FORCE)
|
||||
# Set the possible values of build type for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Release" "Dev" "Sanitize")
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/seastar/cmake)
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
|
||||
else()
|
||||
set(BUILD_TYPE "release")
|
||||
endif()
|
||||
|
||||
function(default_target_arch arch)
|
||||
set(x86_instruction_sets i386 i686 x86_64)
|
||||
if(CMAKE_SYSTEM_PROCESSOR IN_LIST x86_instruction_sets)
|
||||
set(${arch} "westmere" PARENT_SCOPE)
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR EQUAL "aarch64")
|
||||
set(${arch} "armv8-a+crc+crypto" PARENT_SCOPE)
|
||||
else()
|
||||
set(${arch} "" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
default_target_arch(target_arch)
|
||||
if(target_arch)
|
||||
set(target_arch_flag "-march=${target_arch}")
|
||||
endif()
|
||||
|
||||
set(cxx_coro_flag)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
set(cxx_coro_flag -fcoroutines)
|
||||
endif()
|
||||
|
||||
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE
|
||||
STRING "Choose the type of build." FORCE)
|
||||
# Set the possible values of build type for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Release" "Dev" "Sanitize")
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_mode)
|
||||
include(mode.${build_mode})
|
||||
include(mode.common)
|
||||
add_compile_definitions(
|
||||
${Seastar_DEFINITIONS_${build_mode}}
|
||||
FMT_DEPRECATED_OSTREAM)
|
||||
include(limit_jobs)
|
||||
# Configure Seastar compile options to align with Scylla
|
||||
set(CMAKE_CXX_STANDARD "20" CACHE INTERNAL "")
|
||||
set(CMAKE_CXX_EXTENSIONS ON CACHE INTERNAL "")
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(Seastar_CXX_FLAGS ${cxx_coro_flag} ${target_arch_flag} CACHE INTERNAL "" FORCE)
|
||||
set(Seastar_CXX_DIALECT gnu++20 CACHE INTERNAL "" FORCE)
|
||||
|
||||
set(Seastar_TESTING ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(seastar)
|
||||
add_subdirectory(abseil)
|
||||
# Exclude absl::strerror from the default "all" target since it's not
|
||||
# used in Scylla build and, moreover, makes use of deprecated glibc APIs,
|
||||
# such as sys_nerr, which are not exposed from "stdio.h" since glibc 2.32,
|
||||
# which happens to be the case for recent Fedora distribution versions.
|
||||
#
|
||||
# Need to use the internal "absl_strerror" target name instead of namespaced
|
||||
# variant because `set_target_properties` does not understand the latter form,
|
||||
# unfortunately.
|
||||
set_target_properties(absl_strerror PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
|
||||
# System libraries dependencies
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS filesystem program_options system thread regex unit_test_framework)
|
||||
find_package(Boost COMPONENTS filesystem program_options system thread regex REQUIRED)
|
||||
find_package(Lua REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(ICU COMPONENTS uc i18n REQUIRED)
|
||||
find_package(absl COMPONENTS hash raw_hash_set REQUIRED)
|
||||
find_package(libdeflate REQUIRED)
|
||||
find_package(libxcrypt REQUIRED)
|
||||
find_package(Snappy REQUIRED)
|
||||
find_package(RapidJSON REQUIRED)
|
||||
find_package(Thrift REQUIRED)
|
||||
find_package(xxHash REQUIRED)
|
||||
find_package(ICU COMPONENTS uc REQUIRED)
|
||||
|
||||
set(scylla_gen_build_dir "${CMAKE_BINARY_DIR}/gen")
|
||||
file(MAKE_DIRECTORY "${scylla_gen_build_dir}")
|
||||
set(scylla_build_dir "${CMAKE_BINARY_DIR}/build/${BUILD_TYPE}")
|
||||
set(scylla_gen_build_dir "${scylla_build_dir}/gen")
|
||||
file(MAKE_DIRECTORY "${scylla_build_dir}" "${scylla_gen_build_dir}")
|
||||
|
||||
# Place libraries, executables and archives in ${buildroot}/build/${mode}/
|
||||
foreach(mode RUNTIME LIBRARY ARCHIVE)
|
||||
set(CMAKE_${mode}_OUTPUT_DIRECTORY "${scylla_build_dir}")
|
||||
endforeach()
|
||||
|
||||
add_library(scylla-main STATIC)
|
||||
target_sources(scylla-main
|
||||
PRIVATE
|
||||
# Generate C++ source files from thrift definitions
|
||||
function(scylla_generate_thrift)
|
||||
set(one_value_args TARGET VAR IN_FILE OUT_DIR SERVICE)
|
||||
cmake_parse_arguments(args "" "${one_value_args}" "" ${ARGN})
|
||||
|
||||
get_filename_component(in_file_name ${args_IN_FILE} NAME_WE)
|
||||
|
||||
set(aux_out_file_name ${args_OUT_DIR}/${in_file_name})
|
||||
set(outputs
|
||||
${aux_out_file_name}_types.cpp
|
||||
${aux_out_file_name}_types.h
|
||||
${aux_out_file_name}_constants.cpp
|
||||
${aux_out_file_name}_constants.h
|
||||
${args_OUT_DIR}/${args_SERVICE}.cpp
|
||||
${args_OUT_DIR}/${args_SERVICE}.h)
|
||||
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${args_IN_FILE}
|
||||
thrift
|
||||
OUTPUT ${outputs}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${args_OUT_DIR}
|
||||
COMMAND thrift -gen cpp:cob_style,no_skeleton -out "${args_OUT_DIR}" "${args_IN_FILE}")
|
||||
|
||||
add_custom_target(${args_TARGET}
|
||||
DEPENDS ${outputs})
|
||||
|
||||
set(${args_VAR} ${outputs} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
scylla_generate_thrift(
|
||||
TARGET scylla_thrift_gen_cassandra
|
||||
VAR scylla_thrift_gen_cassandra_files
|
||||
IN_FILE "${CMAKE_SOURCE_DIR}/interface/cassandra.thrift"
|
||||
OUT_DIR ${scylla_gen_build_dir}
|
||||
SERVICE Cassandra)
|
||||
|
||||
# Parse antlr3 grammar files and generate C++ sources
|
||||
function(scylla_generate_antlr3)
|
||||
set(one_value_args TARGET VAR IN_FILE OUT_DIR)
|
||||
cmake_parse_arguments(args "" "${one_value_args}" "" ${ARGN})
|
||||
|
||||
get_filename_component(in_file_pure_name ${args_IN_FILE} NAME)
|
||||
get_filename_component(stem ${in_file_pure_name} NAME_WE)
|
||||
|
||||
set(outputs
|
||||
"${args_OUT_DIR}/${stem}Lexer.hpp"
|
||||
"${args_OUT_DIR}/${stem}Lexer.cpp"
|
||||
"${args_OUT_DIR}/${stem}Parser.hpp"
|
||||
"${args_OUT_DIR}/${stem}Parser.cpp")
|
||||
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${args_IN_FILE}
|
||||
OUTPUT ${outputs}
|
||||
# Remove #ifdef'ed code from the grammar source code
|
||||
COMMAND sed -e "/^#if 0/,/^#endif/d" "${args_IN_FILE}" > "${args_OUT_DIR}/${in_file_pure_name}"
|
||||
COMMAND antlr3 "${args_OUT_DIR}/${in_file_pure_name}"
|
||||
# We replace many local `ExceptionBaseType* ex` variables with a single function-scope one.
|
||||
# Because we add such a variable to every function, and because `ExceptionBaseType` is not a global
|
||||
# name, we also add a global typedef to avoid compilation errors.
|
||||
COMMAND sed -i -e "/^.*On :.*$/d" "${args_OUT_DIR}/${stem}Lexer.hpp"
|
||||
COMMAND sed -i -e "/^.*On :.*$/d" "${args_OUT_DIR}/${stem}Lexer.cpp"
|
||||
COMMAND sed -i -e "/^.*On :.*$/d" "${args_OUT_DIR}/${stem}Parser.hpp"
|
||||
COMMAND sed -i
|
||||
-e "s/^\\( *\\)\\(ImplTraits::CommonTokenType\\* [a-zA-Z0-9_]* = NULL;\\)$/\\1const \\2/"
|
||||
-e "/^.*On :.*$/d"
|
||||
-e "1i using ExceptionBaseType = int;"
|
||||
-e "s/^{/{ ExceptionBaseType\\* ex = nullptr;/; s/ExceptionBaseType\\* ex = new/ex = new/; s/exceptions::syntax_exception e/exceptions::syntax_exception\\& e/"
|
||||
"${args_OUT_DIR}/${stem}Parser.cpp"
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(${args_TARGET}
|
||||
DEPENDS ${outputs})
|
||||
|
||||
set(${args_VAR} ${outputs} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set(antlr3_grammar_files
|
||||
cql3/Cql.g
|
||||
alternator/expressions.g)
|
||||
|
||||
set(antlr3_gen_files)
|
||||
|
||||
foreach(f ${antlr3_grammar_files})
|
||||
get_filename_component(grammar_file_name "${f}" NAME_WE)
|
||||
get_filename_component(f_dir "${f}" DIRECTORY)
|
||||
scylla_generate_antlr3(
|
||||
TARGET scylla_antlr3_gen_${grammar_file_name}
|
||||
VAR scylla_antlr3_gen_${grammar_file_name}_files
|
||||
IN_FILE "${CMAKE_SOURCE_DIR}/${f}"
|
||||
OUT_DIR ${scylla_gen_build_dir}/${f_dir})
|
||||
list(APPEND antlr3_gen_files "${scylla_antlr3_gen_${grammar_file_name}_files}")
|
||||
endforeach()
|
||||
|
||||
# Generate C++ sources from ragel grammar files
|
||||
seastar_generate_ragel(
|
||||
TARGET scylla_ragel_gen_protocol_parser
|
||||
VAR scylla_ragel_gen_protocol_parser_file
|
||||
IN_FILE "${CMAKE_SOURCE_DIR}/redis/protocol_parser.rl"
|
||||
OUT_FILE ${scylla_gen_build_dir}/redis/protocol_parser.hh)
|
||||
|
||||
# Generate C++ sources from Swagger definitions
|
||||
set(swagger_files
|
||||
api/api-doc/cache_service.json
|
||||
api/api-doc/collectd.json
|
||||
api/api-doc/column_family.json
|
||||
api/api-doc/commitlog.json
|
||||
api/api-doc/compaction_manager.json
|
||||
api/api-doc/config.json
|
||||
api/api-doc/endpoint_snitch_info.json
|
||||
api/api-doc/error_injection.json
|
||||
api/api-doc/failure_detector.json
|
||||
api/api-doc/gossiper.json
|
||||
api/api-doc/hinted_handoff.json
|
||||
api/api-doc/lsa.json
|
||||
api/api-doc/messaging_service.json
|
||||
api/api-doc/storage_proxy.json
|
||||
api/api-doc/storage_service.json
|
||||
api/api-doc/stream_manager.json
|
||||
api/api-doc/system.json
|
||||
api/api-doc/task_manager.json
|
||||
api/api-doc/task_manager_test.json
|
||||
api/api-doc/utils.json)
|
||||
|
||||
set(swagger_gen_files)
|
||||
|
||||
foreach(f ${swagger_files})
|
||||
get_filename_component(fname "${f}" NAME_WE)
|
||||
get_filename_component(dir "${f}" DIRECTORY)
|
||||
seastar_generate_swagger(
|
||||
TARGET scylla_swagger_gen_${fname}
|
||||
VAR scylla_swagger_gen_${fname}_files
|
||||
IN_FILE "${CMAKE_SOURCE_DIR}/${f}"
|
||||
OUT_DIR "${scylla_gen_build_dir}/${dir}")
|
||||
list(APPEND swagger_gen_files "${scylla_swagger_gen_${fname}_files}")
|
||||
endforeach()
|
||||
|
||||
# Create C++ bindings for IDL serializers
|
||||
function(scylla_generate_idl_serializer)
|
||||
set(one_value_args TARGET VAR IN_FILE OUT_FILE)
|
||||
cmake_parse_arguments(args "" "${one_value_args}" "" ${ARGN})
|
||||
get_filename_component(out_dir ${args_OUT_FILE} DIRECTORY)
|
||||
set(idl_compiler "${CMAKE_SOURCE_DIR}/idl-compiler.py")
|
||||
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${args_IN_FILE}
|
||||
${idl_compiler}
|
||||
OUTPUT ${args_OUT_FILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${out_dir}
|
||||
COMMAND Python3::Interpreter ${idl_compiler} --ns ser -f ${args_IN_FILE} -o ${args_OUT_FILE})
|
||||
|
||||
add_custom_target(${args_TARGET}
|
||||
DEPENDS ${args_OUT_FILE})
|
||||
|
||||
set(${args_VAR} ${args_OUT_FILE} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set(idl_serializers
|
||||
idl/cache_temperature.idl.hh
|
||||
idl/commitlog.idl.hh
|
||||
idl/consistency_level.idl.hh
|
||||
idl/frozen_mutation.idl.hh
|
||||
idl/frozen_schema.idl.hh
|
||||
idl/gossip_digest.idl.hh
|
||||
idl/hinted_handoff.idl.hh
|
||||
idl/idl_test.idl.hh
|
||||
idl/keys.idl.hh
|
||||
idl/messaging_service.idl.hh
|
||||
idl/mutation.idl.hh
|
||||
idl/paging_state.idl.hh
|
||||
idl/partition_checksum.idl.hh
|
||||
idl/paxos.idl.hh
|
||||
idl/query.idl.hh
|
||||
idl/raft.idl.hh
|
||||
idl/range.idl.hh
|
||||
idl/read_command.idl.hh
|
||||
idl/reconcilable_result.idl.hh
|
||||
idl/replay_position.idl.hh
|
||||
idl/result.idl.hh
|
||||
idl/ring_position.idl.hh
|
||||
idl/streaming.idl.hh
|
||||
idl/token.idl.hh
|
||||
idl/tracing.idl.hh
|
||||
idl/truncation_record.idl.hh
|
||||
idl/uuid.idl.hh
|
||||
idl/view.idl.hh)
|
||||
|
||||
set(idl_gen_files)
|
||||
|
||||
foreach(f ${idl_serializers})
|
||||
get_filename_component(idl_name "${f}" NAME)
|
||||
get_filename_component(idl_target "${idl_name}" NAME_WE)
|
||||
get_filename_component(idl_dir "${f}" DIRECTORY)
|
||||
string(REPLACE ".idl.hh" ".dist.hh" idl_out_hdr_name "${idl_name}")
|
||||
scylla_generate_idl_serializer(
|
||||
TARGET scylla_idl_gen_${idl_target}
|
||||
VAR scylla_idl_gen_${idl_target}_files
|
||||
IN_FILE "${CMAKE_SOURCE_DIR}/${f}"
|
||||
OUT_FILE ${scylla_gen_build_dir}/${idl_dir}/${idl_out_hdr_name})
|
||||
list(APPEND idl_gen_files "${scylla_idl_gen_${idl_target}_files}")
|
||||
endforeach()
|
||||
|
||||
set(scylla_sources
|
||||
absl-flat_hash_map.cc
|
||||
alternator/auth.cc
|
||||
alternator/conditions.cc
|
||||
alternator/controller.cc
|
||||
alternator/executor.cc
|
||||
alternator/expressions.cc
|
||||
alternator/serialization.cc
|
||||
alternator/server.cc
|
||||
alternator/stats.cc
|
||||
alternator/streams.cc
|
||||
api/api.cc
|
||||
api/cache_service.cc
|
||||
api/collectd.cc
|
||||
api/column_family.cc
|
||||
api/commitlog.cc
|
||||
api/compaction_manager.cc
|
||||
api/config.cc
|
||||
api/endpoint_snitch.cc
|
||||
api/error_injection.cc
|
||||
api/failure_detector.cc
|
||||
api/gossiper.cc
|
||||
api/hinted_handoff.cc
|
||||
api/lsa.cc
|
||||
api/messaging_service.cc
|
||||
api/storage_proxy.cc
|
||||
api/storage_service.cc
|
||||
api/stream_manager.cc
|
||||
api/system.cc
|
||||
api/task_manager.cc
|
||||
api/task_manager_test.cc
|
||||
atomic_cell.cc
|
||||
auth/allow_all_authenticator.cc
|
||||
auth/allow_all_authorizer.cc
|
||||
auth/authenticated_user.cc
|
||||
auth/authentication_options.cc
|
||||
auth/authenticator.cc
|
||||
auth/common.cc
|
||||
auth/default_authorizer.cc
|
||||
auth/password_authenticator.cc
|
||||
auth/passwords.cc
|
||||
auth/permission.cc
|
||||
auth/permissions_cache.cc
|
||||
auth/resource.cc
|
||||
auth/role_or_anonymous.cc
|
||||
auth/roles-metadata.cc
|
||||
auth/sasl_challenge.cc
|
||||
auth/service.cc
|
||||
auth/standard_role_manager.cc
|
||||
auth/transitional.cc
|
||||
bytes.cc
|
||||
client_data.cc
|
||||
caching_options.cc
|
||||
canonical_mutation.cc
|
||||
cdc/cdc_partitioner.cc
|
||||
cdc/generation.cc
|
||||
cdc/log.cc
|
||||
cdc/metadata.cc
|
||||
cdc/split.cc
|
||||
clocks-impl.cc
|
||||
collection_mutation.cc
|
||||
compaction/compaction.cc
|
||||
compaction/compaction_manager.cc
|
||||
compaction/compaction_strategy.cc
|
||||
compaction/leveled_compaction_strategy.cc
|
||||
compaction/size_tiered_compaction_strategy.cc
|
||||
compaction/time_window_compaction_strategy.cc
|
||||
compress.cc
|
||||
converting_mutation_partition_applier.cc
|
||||
counters.cc
|
||||
direct_failure_detector/failure_detector.cc
|
||||
cql3/abstract_marker.cc
|
||||
cql3/attributes.cc
|
||||
cql3/cf_name.cc
|
||||
cql3/column_condition.cc
|
||||
cql3/column_identifier.cc
|
||||
cql3/column_specification.cc
|
||||
cql3/constants.cc
|
||||
cql3/cql3_type.cc
|
||||
cql3/expr/expression.cc
|
||||
cql3/expr/prepare_expr.cc
|
||||
cql3/expr/restrictions.cc
|
||||
cql3/functions/aggregate_fcts.cc
|
||||
cql3/functions/castas_fcts.cc
|
||||
cql3/functions/error_injection_fcts.cc
|
||||
cql3/functions/functions.cc
|
||||
cql3/functions/user_function.cc
|
||||
cql3/index_name.cc
|
||||
cql3/keyspace_element_name.cc
|
||||
cql3/lists.cc
|
||||
cql3/maps.cc
|
||||
cql3/operation.cc
|
||||
cql3/prepare_context.cc
|
||||
cql3/query_options.cc
|
||||
cql3/query_processor.cc
|
||||
cql3/restrictions/statement_restrictions.cc
|
||||
cql3/result_set.cc
|
||||
cql3/role_name.cc
|
||||
cql3/selection/abstract_function_selector.cc
|
||||
cql3/selection/selectable.cc
|
||||
cql3/selection/selection.cc
|
||||
cql3/selection/selector.cc
|
||||
cql3/selection/selector_factories.cc
|
||||
cql3/selection/simple_selector.cc
|
||||
cql3/sets.cc
|
||||
cql3/statements/alter_keyspace_statement.cc
|
||||
cql3/statements/alter_service_level_statement.cc
|
||||
cql3/statements/alter_table_statement.cc
|
||||
cql3/statements/alter_type_statement.cc
|
||||
cql3/statements/alter_view_statement.cc
|
||||
cql3/statements/attach_service_level_statement.cc
|
||||
cql3/statements/authentication_statement.cc
|
||||
cql3/statements/authorization_statement.cc
|
||||
cql3/statements/batch_statement.cc
|
||||
cql3/statements/cas_request.cc
|
||||
cql3/statements/cf_prop_defs.cc
|
||||
cql3/statements/cf_statement.cc
|
||||
cql3/statements/create_aggregate_statement.cc
|
||||
cql3/statements/create_function_statement.cc
|
||||
cql3/statements/create_index_statement.cc
|
||||
cql3/statements/create_keyspace_statement.cc
|
||||
cql3/statements/create_service_level_statement.cc
|
||||
cql3/statements/create_table_statement.cc
|
||||
cql3/statements/create_type_statement.cc
|
||||
cql3/statements/create_view_statement.cc
|
||||
cql3/statements/delete_statement.cc
|
||||
cql3/statements/detach_service_level_statement.cc
|
||||
cql3/statements/drop_aggregate_statement.cc
|
||||
cql3/statements/drop_function_statement.cc
|
||||
cql3/statements/drop_index_statement.cc
|
||||
cql3/statements/drop_keyspace_statement.cc
|
||||
cql3/statements/drop_service_level_statement.cc
|
||||
cql3/statements/drop_table_statement.cc
|
||||
cql3/statements/drop_type_statement.cc
|
||||
cql3/statements/drop_view_statement.cc
|
||||
cql3/statements/function_statement.cc
|
||||
cql3/statements/grant_statement.cc
|
||||
cql3/statements/index_prop_defs.cc
|
||||
cql3/statements/index_target.cc
|
||||
cql3/statements/ks_prop_defs.cc
|
||||
cql3/statements/list_permissions_statement.cc
|
||||
cql3/statements/list_service_level_attachments_statement.cc
|
||||
cql3/statements/list_service_level_statement.cc
|
||||
cql3/statements/list_users_statement.cc
|
||||
cql3/statements/modification_statement.cc
|
||||
cql3/statements/permission_altering_statement.cc
|
||||
cql3/statements/property_definitions.cc
|
||||
cql3/statements/raw/parsed_statement.cc
|
||||
cql3/statements/revoke_statement.cc
|
||||
cql3/statements/role-management-statements.cc
|
||||
cql3/statements/schema_altering_statement.cc
|
||||
cql3/statements/select_statement.cc
|
||||
cql3/statements/service_level_statement.cc
|
||||
cql3/statements/sl_prop_defs.cc
|
||||
cql3/statements/truncate_statement.cc
|
||||
cql3/statements/update_statement.cc
|
||||
cql3/statements/strongly_consistent_modification_statement.cc
|
||||
cql3/statements/strongly_consistent_select_statement.cc
|
||||
cql3/statements/use_statement.cc
|
||||
cql3/type_json.cc
|
||||
cql3/untyped_result_set.cc
|
||||
cql3/update_parameters.cc
|
||||
cql3/user_types.cc
|
||||
cql3/util.cc
|
||||
cql3/ut_name.cc
|
||||
cql3/values.cc
|
||||
data_dictionary/data_dictionary.cc
|
||||
db/batchlog_manager.cc
|
||||
db/commitlog/commitlog.cc
|
||||
db/commitlog/commitlog_entry.cc
|
||||
db/commitlog/commitlog_replayer.cc
|
||||
db/config.cc
|
||||
db/consistency_level.cc
|
||||
db/cql_type_parser.cc
|
||||
db/data_listeners.cc
|
||||
db/extensions.cc
|
||||
db/heat_load_balance.cc
|
||||
db/hints/host_filter.cc
|
||||
db/hints/manager.cc
|
||||
db/hints/resource_manager.cc
|
||||
db/hints/sync_point.cc
|
||||
db/large_data_handler.cc
|
||||
db/legacy_schema_migrator.cc
|
||||
db/marshal/type_parser.cc
|
||||
db/rate_limiter.cc
|
||||
db/schema_tables.cc
|
||||
db/size_estimates_virtual_reader.cc
|
||||
db/snapshot-ctl.cc
|
||||
db/sstables-format-selector.cc
|
||||
db/system_distributed_keyspace.cc
|
||||
db/system_keyspace.cc
|
||||
db/view/row_locking.cc
|
||||
db/view/view.cc
|
||||
db/view/view_update_generator.cc
|
||||
db/virtual_table.cc
|
||||
dht/boot_strapper.cc
|
||||
dht/i_partitioner.cc
|
||||
dht/murmur3_partitioner.cc
|
||||
dht/range_streamer.cc
|
||||
dht/token.cc
|
||||
replica/distributed_loader.cc
|
||||
duration.cc
|
||||
exceptions/exceptions.cc
|
||||
readers/mutation_readers.cc
|
||||
frozen_mutation.cc
|
||||
frozen_schema.cc
|
||||
generic_server.cc
|
||||
debug.cc
|
||||
gms/application_state.cc
|
||||
gms/endpoint_state.cc
|
||||
gms/failure_detector.cc
|
||||
gms/feature_service.cc
|
||||
gms/gossip_digest_ack2.cc
|
||||
gms/gossip_digest_ack.cc
|
||||
gms/gossip_digest_syn.cc
|
||||
gms/gossiper.cc
|
||||
gms/inet_address.cc
|
||||
gms/versioned_value.cc
|
||||
gms/version_generator.cc
|
||||
hashers.cc
|
||||
index/secondary_index.cc
|
||||
index/secondary_index_manager.cc
|
||||
init.cc
|
||||
keys.cc
|
||||
utils/lister.cc
|
||||
locator/abstract_replication_strategy.cc
|
||||
locator/azure_snitch.cc
|
||||
locator/ec2_multi_region_snitch.cc
|
||||
locator/ec2_snitch.cc
|
||||
locator/everywhere_replication_strategy.cc
|
||||
locator/gce_snitch.cc
|
||||
locator/gossiping_property_file_snitch.cc
|
||||
locator/local_strategy.cc
|
||||
locator/network_topology_strategy.cc
|
||||
locator/production_snitch_base.cc
|
||||
locator/rack_inferring_snitch.cc
|
||||
locator/simple_snitch.cc
|
||||
locator/simple_strategy.cc
|
||||
locator/snitch_base.cc
|
||||
locator/token_metadata.cc
|
||||
lang/lua.cc
|
||||
main.cc
|
||||
replica/memtable.cc
|
||||
message/messaging_service.cc
|
||||
multishard_mutation_query.cc
|
||||
mutation.cc
|
||||
mutation_fragment.cc
|
||||
mutation_partition.cc
|
||||
mutation_partition_serializer.cc
|
||||
mutation_partition_view.cc
|
||||
mutation_query.cc
|
||||
readers/mutation_reader.cc
|
||||
mutation_writer/feed_writers.cc
|
||||
mutation_writer/multishard_writer.cc
|
||||
mutation_writer/partition_based_splitting_writer.cc
|
||||
mutation_writer/shard_based_splitting_writer.cc
|
||||
mutation_writer/timestamp_based_splitting_writer.cc
|
||||
partition_slice_builder.cc
|
||||
partition_version.cc
|
||||
querier.cc
|
||||
query.cc
|
||||
query_ranges_to_vnodes.cc
|
||||
query-result-set.cc
|
||||
raft/fsm.cc
|
||||
raft/log.cc
|
||||
raft/raft.cc
|
||||
raft/server.cc
|
||||
raft/tracker.cc
|
||||
service/broadcast_tables/experimental/lang.cc
|
||||
range_tombstone.cc
|
||||
range_tombstone_list.cc
|
||||
tombstone_gc_options.cc
|
||||
tombstone_gc.cc
|
||||
reader_concurrency_semaphore.cc
|
||||
redis/abstract_command.cc
|
||||
redis/command_factory.cc
|
||||
redis/commands.cc
|
||||
redis/keyspace_utils.cc
|
||||
redis/lolwut.cc
|
||||
redis/mutation_utils.cc
|
||||
redis/options.cc
|
||||
redis/query_processor.cc
|
||||
redis/query_utils.cc
|
||||
redis/server.cc
|
||||
redis/service.cc
|
||||
redis/stats.cc
|
||||
release.cc
|
||||
repair/repair.cc
|
||||
repair/row_level.cc
|
||||
replica/database.cc
|
||||
replica/table.cc
|
||||
row_cache.cc
|
||||
schema.cc
|
||||
schema_mutations.cc
|
||||
schema_registry.cc
|
||||
serializer.cc
|
||||
sstables_loader.cc
|
||||
service/client_state.cc
|
||||
service/forward_service.cc
|
||||
service/migration_manager.cc
|
||||
service/misc_services.cc
|
||||
service/pager/paging_state.cc
|
||||
service/pager/query_pagers.cc
|
||||
service/paxos/paxos_state.cc
|
||||
service/paxos/prepare_response.cc
|
||||
service/paxos/prepare_summary.cc
|
||||
service/paxos/proposal.cc
|
||||
service/priority_manager.cc
|
||||
service/qos/qos_common.cc
|
||||
service/qos/service_level_controller.cc
|
||||
service/qos/standard_service_level_distributed_data_accessor.cc
|
||||
service/raft/raft_group_registry.cc
|
||||
service/raft/raft_rpc.cc
|
||||
service/raft/raft_sys_table_storage.cc
|
||||
service/raft/group0_state_machine.cc
|
||||
service/storage_proxy.cc
|
||||
service/storage_service.cc
|
||||
sstables/compress.cc
|
||||
sstables/integrity_checked_file_impl.cc
|
||||
sstables/kl/reader.cc
|
||||
sstables/metadata_collector.cc
|
||||
sstables/m_format_read_helpers.cc
|
||||
sstables/mx/reader.cc
|
||||
sstables/mx/writer.cc
|
||||
sstables/prepended_input_stream.cc
|
||||
sstables/random_access_reader.cc
|
||||
sstables/sstable_directory.cc
|
||||
sstables/sstable_mutation_reader.cc
|
||||
sstables/sstables.cc
|
||||
sstables/sstable_set.cc
|
||||
sstables/sstables_manager.cc
|
||||
sstables/sstable_version.cc
|
||||
sstables/writer.cc
|
||||
streaming/consumer.cc
|
||||
streaming/progress_info.cc
|
||||
streaming/session_info.cc
|
||||
streaming/stream_coordinator.cc
|
||||
streaming/stream_manager.cc
|
||||
streaming/stream_plan.cc
|
||||
streaming/stream_reason.cc
|
||||
streaming/stream_receive_task.cc
|
||||
streaming/stream_request.cc
|
||||
streaming/stream_result_future.cc
|
||||
streaming/stream_session.cc
|
||||
streaming/stream_session_state.cc
|
||||
streaming/stream_summary.cc
|
||||
streaming/stream_task.cc
|
||||
streaming/stream_transfer_task.cc
|
||||
table_helper.cc
|
||||
tasks/task_manager.cc
|
||||
thrift/controller.cc
|
||||
thrift/handler.cc
|
||||
thrift/server.cc
|
||||
thrift/thrift_validation.cc
|
||||
timeout_config.cc
|
||||
tools/scylla-sstable-index.cc
|
||||
tools/scylla-types.cc
|
||||
tracing/traced_file.cc
|
||||
tracing/trace_keyspace_helper.cc
|
||||
tracing/trace_state.cc
|
||||
tracing/tracing_backend_registry.cc
|
||||
tracing/tracing.cc
|
||||
transport/controller.cc
|
||||
transport/cql_protocol_extension.cc
|
||||
transport/event.cc
|
||||
transport/event_notifier.cc
|
||||
transport/messages/result_message.cc
|
||||
transport/server.cc
|
||||
types.cc
|
||||
unimplemented.cc
|
||||
utils/arch/powerpc/crc32-vpmsum/crc32_wrapper.cc
|
||||
utils/array-search.cc
|
||||
utils/ascii.cc
|
||||
utils/base64.cc
|
||||
utils/big_decimal.cc
|
||||
utils/bloom_calculations.cc
|
||||
utils/bloom_filter.cc
|
||||
utils/buffer_input_stream.cc
|
||||
utils/build_id.cc
|
||||
utils/config_file.cc
|
||||
utils/directories.cc
|
||||
utils/disk-error-handler.cc
|
||||
utils/dynamic_bitset.cc
|
||||
utils/error_injection.cc
|
||||
utils/exceptions.cc
|
||||
utils/file_lock.cc
|
||||
utils/generation-number.cc
|
||||
utils/gz/crc_combine.cc
|
||||
utils/gz/gen_crc_combine_table.cc
|
||||
utils/human_readable.cc
|
||||
utils/i_filter.cc
|
||||
utils/large_bitset.cc
|
||||
utils/like_matcher.cc
|
||||
utils/limiting_data_source.cc
|
||||
utils/logalloc.cc
|
||||
utils/managed_bytes.cc
|
||||
utils/multiprecision_int.cc
|
||||
utils/murmur_hash.cc
|
||||
utils/rate_limiter.cc
|
||||
utils/rjson.cc
|
||||
utils/runtime.cc
|
||||
utils/updateable_value.cc
|
||||
utils/utf8.cc
|
||||
utils/uuid.cc
|
||||
utils/UUID_gen.cc
|
||||
validation.cc
|
||||
vint-serialization.cc
|
||||
zstd.cc)
|
||||
target_link_libraries(scylla-main
|
||||
PRIVATE
|
||||
db
|
||||
absl::hash
|
||||
absl::raw_hash_set
|
||||
Seastar::seastar
|
||||
Snappy::snappy
|
||||
systemd
|
||||
ZLIB::ZLIB)
|
||||
add_subdirectory(api)
|
||||
add_subdirectory(alternator)
|
||||
add_subdirectory(db)
|
||||
add_subdirectory(auth)
|
||||
add_subdirectory(cdc)
|
||||
add_subdirectory(compaction)
|
||||
add_subdirectory(cql3)
|
||||
add_subdirectory(data_dictionary)
|
||||
add_subdirectory(dht)
|
||||
add_subdirectory(gms)
|
||||
add_subdirectory(idl)
|
||||
add_subdirectory(index)
|
||||
add_subdirectory(interface)
|
||||
add_subdirectory(lang)
|
||||
add_subdirectory(locator)
|
||||
add_subdirectory(mutation)
|
||||
add_subdirectory(mutation_writer)
|
||||
add_subdirectory(readers)
|
||||
add_subdirectory(redis)
|
||||
add_subdirectory(replica)
|
||||
add_subdirectory(raft)
|
||||
add_subdirectory(repair)
|
||||
add_subdirectory(rust)
|
||||
add_subdirectory(schema)
|
||||
add_subdirectory(service)
|
||||
add_subdirectory(sstables)
|
||||
add_subdirectory(streaming)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(thrift)
|
||||
add_subdirectory(tools)
|
||||
add_subdirectory(tracing)
|
||||
add_subdirectory(transport)
|
||||
add_subdirectory(types)
|
||||
add_subdirectory(utils)
|
||||
include(add_version_library)
|
||||
add_version_library(scylla_version
|
||||
release.cc)
|
||||
|
||||
set(scylla_gen_sources
|
||||
"${scylla_thrift_gen_cassandra_files}"
|
||||
"${scylla_ragel_gen_protocol_parser_file}"
|
||||
"${swagger_gen_files}"
|
||||
"${idl_gen_files}"
|
||||
"${antlr3_gen_files}")
|
||||
|
||||
add_executable(scylla
|
||||
main.cc)
|
||||
target_link_libraries(scylla PRIVATE
|
||||
scylla-main
|
||||
api
|
||||
auth
|
||||
alternator
|
||||
db
|
||||
cdc
|
||||
compaction
|
||||
cql3
|
||||
data_dictionary
|
||||
dht
|
||||
gms
|
||||
idl
|
||||
index
|
||||
lang
|
||||
locator
|
||||
mutation
|
||||
mutation_writer
|
||||
raft
|
||||
readers
|
||||
redis
|
||||
repair
|
||||
replica
|
||||
schema
|
||||
scylla_version
|
||||
service
|
||||
sstables
|
||||
streaming
|
||||
test-perf
|
||||
thrift
|
||||
tools
|
||||
tracing
|
||||
transport
|
||||
types
|
||||
utils)
|
||||
target_link_libraries(Boost::regex
|
||||
INTERFACE
|
||||
ICU::i18n
|
||||
ICU::uc)
|
||||
${scylla_sources}
|
||||
${scylla_gen_sources})
|
||||
|
||||
target_link_libraries(scylla PRIVATE
|
||||
seastar
|
||||
Boost::program_options)
|
||||
|
||||
# Force SHA1 build-id generation
|
||||
set(default_linker_flags "-Wl,--build-id=sha1")
|
||||
include(CheckLinkerFlag)
|
||||
foreach(linker "lld" "gold")
|
||||
set(linker_flag "-fuse-ld=${linker}")
|
||||
check_linker_flag(CXX ${linker_flag} "CXX_LINKER_HAVE_${linker}")
|
||||
if(CXX_LINKER_HAVE_${linker})
|
||||
string(APPEND default_linker_flags " ${linker_flag}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${default_linker_flags}" CACHE INTERNAL "")
|
||||
# Boost dependencies
|
||||
Boost::filesystem
|
||||
Boost::program_options
|
||||
Boost::system
|
||||
Boost::thread
|
||||
Boost::regex
|
||||
Boost::headers
|
||||
# Abseil libs
|
||||
absl::hashtablez_sampler
|
||||
absl::raw_hash_set
|
||||
absl::synchronization
|
||||
absl::graphcycles_internal
|
||||
absl::stacktrace
|
||||
absl::symbolize
|
||||
absl::debugging_internal
|
||||
absl::demangle_internal
|
||||
absl::time
|
||||
absl::time_zone
|
||||
absl::int128
|
||||
absl::city
|
||||
absl::hash
|
||||
absl::malloc_internal
|
||||
absl::spinlock_wait
|
||||
absl::base
|
||||
absl::dynamic_annotations
|
||||
absl::raw_logging_internal
|
||||
absl::exponential_biased
|
||||
absl::throw_delegate
|
||||
# System libs
|
||||
ZLIB::ZLIB
|
||||
ICU::uc
|
||||
systemd
|
||||
zstd
|
||||
snappy
|
||||
${LUA_LIBRARIES}
|
||||
thrift
|
||||
crypt)
|
||||
|
||||
target_link_libraries(scylla PRIVATE
|
||||
-Wl,--build-id=sha1 # Force SHA1 build-id generation
|
||||
# TODO: Use lld linker if it's available, otherwise gold, else bfd
|
||||
-fuse-ld=lld)
|
||||
# TODO: patch dynamic linker to match configure.py behavior
|
||||
|
||||
target_compile_options(scylla PRIVATE
|
||||
-std=gnu++20
|
||||
${cxx_coro_flag}
|
||||
${target_arch_flag})
|
||||
# Hacks needed to expose internal APIs for xxhash dependencies
|
||||
target_compile_definitions(scylla PRIVATE XXH_PRIVATE_API HAVE_LZ4_COMPRESS_DEFAULT)
|
||||
|
||||
target_include_directories(scylla PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
libdeflate
|
||||
abseil
|
||||
"${scylla_gen_build_dir}")
|
||||
|
||||
###
|
||||
### Create crc_combine_table helper executable.
|
||||
### Use it to generate crc_combine_table.cc to be used in scylla at build time.
|
||||
###
|
||||
add_executable(crc_combine_table utils/gz/gen_crc_combine_table.cc)
|
||||
target_link_libraries(crc_combine_table PRIVATE seastar)
|
||||
target_include_directories(crc_combine_table PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_compile_options(crc_combine_table PRIVATE
|
||||
-std=gnu++20
|
||||
${cxx_coro_flag}
|
||||
${target_arch_flag})
|
||||
add_dependencies(scylla crc_combine_table)
|
||||
|
||||
# Generate an additional source file at build time that is needed for Scylla compilation
|
||||
add_custom_command(OUTPUT "${scylla_gen_build_dir}/utils/gz/crc_combine_table.cc"
|
||||
COMMAND $<TARGET_FILE:crc_combine_table> > "${scylla_gen_build_dir}/utils/gz/crc_combine_table.cc"
|
||||
DEPENDS crc_combine_table)
|
||||
target_sources(scylla PRIVATE "${scylla_gen_build_dir}/utils/gz/crc_combine_table.cc")
|
||||
|
||||
###
|
||||
### Generate version file and supply appropriate compile definitions for release.cc
|
||||
###
|
||||
execute_process(COMMAND ${CMAKE_SOURCE_DIR}/SCYLLA-VERSION-GEN --output-dir "${CMAKE_BINARY_DIR}/gen" RESULT_VARIABLE scylla_version_gen_res)
|
||||
if(scylla_version_gen_res)
|
||||
message(SEND_ERROR "Version file generation failed. Return code: ${scylla_version_gen_res}")
|
||||
endif()
|
||||
|
||||
file(READ "${CMAKE_BINARY_DIR}/gen/SCYLLA-VERSION-FILE" scylla_version)
|
||||
string(STRIP "${scylla_version}" scylla_version)
|
||||
|
||||
file(READ "${CMAKE_BINARY_DIR}/gen/SCYLLA-RELEASE-FILE" scylla_release)
|
||||
string(STRIP "${scylla_release}" scylla_release)
|
||||
|
||||
get_property(release_cdefs SOURCE "${CMAKE_SOURCE_DIR}/release.cc" PROPERTY COMPILE_DEFINITIONS)
|
||||
list(APPEND release_cdefs "SCYLLA_VERSION=\"${scylla_version}\"" "SCYLLA_RELEASE=\"${scylla_release}\"")
|
||||
set_source_files_properties("${CMAKE_SOURCE_DIR}/release.cc" PROPERTIES COMPILE_DEFINITIONS "${release_cdefs}")
|
||||
|
||||
###
|
||||
### Custom command for building libdeflate. Link the library to scylla.
|
||||
###
|
||||
set(libdeflate_lib "${scylla_build_dir}/libdeflate/libdeflate.a")
|
||||
add_custom_command(OUTPUT "${libdeflate_lib}"
|
||||
COMMAND make -C "${CMAKE_SOURCE_DIR}/libdeflate"
|
||||
BUILD_DIR=../build/${BUILD_TYPE}/libdeflate/
|
||||
CC=${CMAKE_C_COMPILER}
|
||||
"CFLAGS=${target_arch_flag}"
|
||||
../build/${BUILD_TYPE}/libdeflate//libdeflate.a) # Two backslashes are important!
|
||||
# Hack to force generating custom command to produce libdeflate.a
|
||||
add_custom_target(libdeflate DEPENDS "${libdeflate_lib}")
|
||||
target_link_libraries(scylla PRIVATE "${libdeflate_lib}")
|
||||
|
||||
# TODO: create cmake/ directory and move utilities (generate functions etc) there
|
||||
# TODO: Build tests if BUILD_TESTING=on (using CTest module)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Asking questions or requesting help
|
||||
|
||||
Use the [ScyllaDB Community Forum](https://forum.scylladb.com) or the [Slack workspace](http://slack.scylladb.com) for general questions and help.
|
||||
Use the [Scylla Users mailing list](https://groups.google.com/g/scylladb-users) or the [Slack workspace](http://slack.scylladb.com) for general questions and help.
|
||||
|
||||
Join the [Scylla Developers mailing list](https://groups.google.com/g/scylladb-dev) for deeper technical discussions and to discuss your ideas for contributions.
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ $ # Edit configuration options as appropriate
|
||||
$ SCYLLA_HOME=$HOME/scylla build/release/scylla
|
||||
```
|
||||
|
||||
The `scylla.yaml` file in the repository by default writes all database data to `/var/lib/scylla`, which likely requires root access. Change the `data_file_directories`, `commitlog_directory` and `schema_commitlog_directory` fields as appropriate.
|
||||
The `scylla.yaml` file in the repository by default writes all database data to `/var/lib/scylla`, which likely requires root access. Change the `data_file_directories` and `commitlog_directory` fields as appropriate.
|
||||
|
||||
Scylla has a number of requirements for the file-system and operating system to operate ideally and at peak performance. However, during development, these requirements can be relaxed with the `--developer-mode` flag.
|
||||
|
||||
|
||||
12
README.md
12
README.md
@@ -30,9 +30,9 @@ requirements - you just need to meet the frozen toolchain's prerequisites
|
||||
Building Scylla with the frozen toolchain `dbuild` is as easy as:
|
||||
|
||||
```bash
|
||||
$ git submodule update --init --force --recursive
|
||||
$ ./tools/toolchain/dbuild ./configure.py
|
||||
$ ./tools/toolchain/dbuild ninja build/release/scylla
|
||||
$ git submodule update --init --force --recursive
|
||||
$ ./tools/toolchain/dbuild ./configure.py
|
||||
$ ./tools/toolchain/dbuild ninja build/release/scylla
|
||||
```
|
||||
|
||||
For further information, please see:
|
||||
@@ -60,7 +60,7 @@ Please note that you need to run Scylla with `dbuild` if you built it with the f
|
||||
For more run options, run:
|
||||
|
||||
```bash
|
||||
$ ./tools/toolchain/dbuild ./build/release/scylla --help
|
||||
$ ./tools/toolchain/dbuild ./build/release/scylla --help
|
||||
```
|
||||
|
||||
## Testing
|
||||
@@ -100,10 +100,10 @@ If you are a developer working on Scylla, please read the [developer guidelines]
|
||||
|
||||
## Contact
|
||||
|
||||
* The [community forum] and [Slack channel] are for users to discuss configuration, management, and operations of the ScyllaDB open source.
|
||||
* The [users mailing list] and [Slack channel] are for users to discuss configuration, management, and operations of the ScyllaDB open source.
|
||||
* The [developers mailing list] is for developers and people interested in following the development of ScyllaDB to discuss technical topics.
|
||||
|
||||
[Community forum]: https://forum.scylladb.com/
|
||||
[Users mailing list]: https://groups.google.com/forum/#!forum/scylladb-users
|
||||
|
||||
[Slack channel]: http://slack.scylladb.com/
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ END
|
||||
|
||||
DATE=""
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
while [[ $# -gt 0 ]]; do
|
||||
opt="$1"
|
||||
case $opt in
|
||||
-h|--help)
|
||||
@@ -72,7 +72,7 @@ fi
|
||||
|
||||
# Default scylla product/version tags
|
||||
PRODUCT=scylla
|
||||
VERSION=5.3.0-dev
|
||||
VERSION=5.2.0-dev
|
||||
|
||||
if test -f version
|
||||
then
|
||||
|
||||
1
abseil
Submodule
1
abseil
Submodule
Submodule abseil added at 7f3c0d7811
@@ -1,30 +0,0 @@
|
||||
include(generate_cql_grammar)
|
||||
generate_cql_grammar(
|
||||
GRAMMAR expressions.g
|
||||
SOURCES cql_grammar_srcs)
|
||||
|
||||
add_library(alternator STATIC)
|
||||
target_sources(alternator
|
||||
PRIVATE
|
||||
controller.cc
|
||||
server.cc
|
||||
executor.cc
|
||||
stats.cc
|
||||
serialization.cc
|
||||
expressions.cc
|
||||
conditions.cc
|
||||
auth.cc
|
||||
streams.cc
|
||||
ttl.cc
|
||||
${cql_grammar_srcs})
|
||||
target_include_directories(alternator
|
||||
PUBLIC
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_BINARY_DIR}
|
||||
PRIVATE
|
||||
${RAPIDJSON_INCLUDE_DIRS})
|
||||
target_link_libraries(alternator
|
||||
cql3
|
||||
idl
|
||||
Seastar::seastar
|
||||
xxHash::xxhash)
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "log.hh"
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <gnutls/crypto.h>
|
||||
#include "hashers.hh"
|
||||
#include "bytes.hh"
|
||||
#include "alternator/auth.hh"
|
||||
#include <fmt/format.h>
|
||||
@@ -27,6 +29,99 @@ namespace alternator {
|
||||
|
||||
static logging::logger alogger("alternator-auth");
|
||||
|
||||
static hmac_sha256_digest hmac_sha256(std::string_view key, std::string_view msg) {
|
||||
hmac_sha256_digest digest;
|
||||
int ret = gnutls_hmac_fast(GNUTLS_MAC_SHA256, key.data(), key.size(), msg.data(), msg.size(), digest.data());
|
||||
if (ret) {
|
||||
throw std::runtime_error(fmt::format("Computing HMAC failed ({}): {}", ret, gnutls_strerror(ret)));
|
||||
}
|
||||
return digest;
|
||||
}
|
||||
|
||||
static hmac_sha256_digest get_signature_key(std::string_view key, std::string_view date_stamp, std::string_view region_name, std::string_view service_name) {
|
||||
auto date = hmac_sha256("AWS4" + std::string(key), date_stamp);
|
||||
auto region = hmac_sha256(std::string_view(date.data(), date.size()), region_name);
|
||||
auto service = hmac_sha256(std::string_view(region.data(), region.size()), service_name);
|
||||
auto signing = hmac_sha256(std::string_view(service.data(), service.size()), "aws4_request");
|
||||
return signing;
|
||||
}
|
||||
|
||||
static std::string apply_sha256(std::string_view msg) {
|
||||
sha256_hasher hasher;
|
||||
hasher.update(msg.data(), msg.size());
|
||||
return to_hex(hasher.finalize());
|
||||
}
|
||||
|
||||
static std::string apply_sha256(const std::vector<temporary_buffer<char>>& msg) {
|
||||
sha256_hasher hasher;
|
||||
for (const temporary_buffer<char>& buf : msg) {
|
||||
hasher.update(buf.get(), buf.size());
|
||||
}
|
||||
return to_hex(hasher.finalize());
|
||||
}
|
||||
|
||||
static std::string format_time_point(db_clock::time_point tp) {
|
||||
time_t time_point_repr = db_clock::to_time_t(tp);
|
||||
std::string time_point_str;
|
||||
time_point_str.resize(17);
|
||||
::tm time_buf;
|
||||
// strftime prints the terminating null character as well
|
||||
std::strftime(time_point_str.data(), time_point_str.size(), "%Y%m%dT%H%M%SZ", ::gmtime_r(&time_point_repr, &time_buf));
|
||||
time_point_str.resize(16);
|
||||
return time_point_str;
|
||||
}
|
||||
|
||||
void check_expiry(std::string_view signature_date) {
|
||||
//FIXME: The default 15min can be changed with X-Amz-Expires header - we should honor it
|
||||
std::string expiration_str = format_time_point(db_clock::now() - 15min);
|
||||
std::string validity_str = format_time_point(db_clock::now() + 15min);
|
||||
if (signature_date < expiration_str) {
|
||||
throw api_error::invalid_signature(
|
||||
fmt::format("Signature expired: {} is now earlier than {} (current time - 15 min.)",
|
||||
signature_date, expiration_str));
|
||||
}
|
||||
if (signature_date > validity_str) {
|
||||
throw api_error::invalid_signature(
|
||||
fmt::format("Signature not yet current: {} is still later than {} (current time + 15 min.)",
|
||||
signature_date, validity_str));
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_signature(std::string_view access_key_id, std::string_view secret_access_key, std::string_view host, std::string_view method,
|
||||
std::string_view orig_datestamp, std::string_view signed_headers_str, const std::map<std::string_view, std::string_view>& signed_headers_map,
|
||||
const std::vector<temporary_buffer<char>>& body_content, std::string_view region, std::string_view service, std::string_view query_string) {
|
||||
auto amz_date_it = signed_headers_map.find("x-amz-date");
|
||||
if (amz_date_it == signed_headers_map.end()) {
|
||||
throw api_error::invalid_signature("X-Amz-Date header is mandatory for signature verification");
|
||||
}
|
||||
std::string_view amz_date = amz_date_it->second;
|
||||
check_expiry(amz_date);
|
||||
std::string_view datestamp = amz_date.substr(0, 8);
|
||||
if (datestamp != orig_datestamp) {
|
||||
throw api_error::invalid_signature(
|
||||
format("X-Amz-Date date does not match the provided datestamp. Expected {}, got {}",
|
||||
orig_datestamp, datestamp));
|
||||
}
|
||||
std::string_view canonical_uri = "/";
|
||||
|
||||
std::stringstream canonical_headers;
|
||||
for (const auto& header : signed_headers_map) {
|
||||
canonical_headers << fmt::format("{}:{}", header.first, header.second) << '\n';
|
||||
}
|
||||
|
||||
std::string payload_hash = apply_sha256(body_content);
|
||||
std::string canonical_request = fmt::format("{}\n{}\n{}\n{}\n{}\n{}", method, canonical_uri, query_string, canonical_headers.str(), signed_headers_str, payload_hash);
|
||||
|
||||
std::string_view algorithm = "AWS4-HMAC-SHA256";
|
||||
std::string credential_scope = fmt::format("{}/{}/{}/aws4_request", datestamp, region, service);
|
||||
std::string string_to_sign = fmt::format("{}\n{}\n{}\n{}", algorithm, amz_date, credential_scope, apply_sha256(canonical_request));
|
||||
|
||||
hmac_sha256_digest signing_key = get_signature_key(secret_access_key, datestamp, region, service);
|
||||
hmac_sha256_digest signature = hmac_sha256(std::string_view(signing_key.data(), signing_key.size()), string_to_sign);
|
||||
|
||||
return to_hex(bytes_view(reinterpret_cast<const int8_t*>(signature.data()), signature.size()));
|
||||
}
|
||||
|
||||
future<std::string> get_key_from_roles(service::storage_proxy& proxy, std::string username) {
|
||||
schema_ptr schema = proxy.data_dictionary().find_schema("system_auth", "roles");
|
||||
partition_key pk = partition_key::from_single_value(*schema, utf8_type->decompose(username));
|
||||
@@ -46,7 +141,7 @@ future<std::string> get_key_from_roles(service::storage_proxy& proxy, std::strin
|
||||
service::storage_proxy::coordinator_query_result qr = co_await proxy.query(schema, std::move(command), std::move(partition_ranges), cl,
|
||||
service::storage_proxy::coordinator_query_options(executor::default_timeout(), empty_service_permit(), client_state));
|
||||
|
||||
cql3::selection::result_set_builder builder(*selection, gc_clock::now());
|
||||
cql3::selection::result_set_builder builder(*selection, gc_clock::now(), cql_serialization_format::latest());
|
||||
query::result_view::consume(*qr.query_result, partition_slice, cql3::selection::result_set_builder::visitor(builder, *schema, *selection));
|
||||
|
||||
auto result_set = builder.build();
|
||||
|
||||
@@ -20,8 +20,14 @@ class storage_proxy;
|
||||
|
||||
namespace alternator {
|
||||
|
||||
using hmac_sha256_digest = std::array<char, 32>;
|
||||
|
||||
using key_cache = utils::loading_cache<std::string, std::string, 1>;
|
||||
|
||||
std::string get_signature(std::string_view access_key_id, std::string_view secret_access_key, std::string_view host, std::string_view method,
|
||||
std::string_view orig_datestamp, std::string_view signed_headers_str, const std::map<std::string_view, std::string_view>& signed_headers_map,
|
||||
const std::vector<temporary_buffer<char>>& body_content, std::string_view region, std::string_view service, std::string_view query_string);
|
||||
|
||||
future<std::string> get_key_from_roles(service::storage_proxy& proxy, std::string username);
|
||||
|
||||
}
|
||||
|
||||
@@ -232,14 +232,7 @@ bool check_BEGINS_WITH(const rjson::value* v1, const rjson::value& v2,
|
||||
if (it2->name == "S") {
|
||||
return rjson::to_string_view(it1->value).starts_with(rjson::to_string_view(it2->value));
|
||||
} else /* it2->name == "B" */ {
|
||||
try {
|
||||
return base64_begins_with(rjson::to_string_view(it1->value), rjson::to_string_view(it2->value));
|
||||
} catch(std::invalid_argument&) {
|
||||
// determine if any of the malformed values is from query and raise an exception if so
|
||||
unwrap_bytes(it1->value, v1_from_query);
|
||||
unwrap_bytes(it2->value, v2_from_query);
|
||||
return false;
|
||||
}
|
||||
return base64_begins_with(rjson::to_string_view(it1->value), rjson::to_string_view(it2->value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +241,7 @@ static bool is_set_of(const rjson::value& type1, const rjson::value& type2) {
|
||||
}
|
||||
|
||||
// Check if two JSON-encoded values match with the CONTAINS relation
|
||||
bool check_CONTAINS(const rjson::value* v1, const rjson::value& v2, bool v1_from_query, bool v2_from_query) {
|
||||
bool check_CONTAINS(const rjson::value* v1, const rjson::value& v2) {
|
||||
if (!v1) {
|
||||
return false;
|
||||
}
|
||||
@@ -257,12 +250,7 @@ bool check_CONTAINS(const rjson::value* v1, const rjson::value& v2, bool v1_from
|
||||
if (kv1.name == "S" && kv2.name == "S") {
|
||||
return rjson::to_string_view(kv1.value).find(rjson::to_string_view(kv2.value)) != std::string_view::npos;
|
||||
} else if (kv1.name == "B" && kv2.name == "B") {
|
||||
auto d_kv1 = unwrap_bytes(kv1.value, v1_from_query);
|
||||
auto d_kv2 = unwrap_bytes(kv2.value, v2_from_query);
|
||||
if (!d_kv1 || !d_kv2) {
|
||||
return false;
|
||||
}
|
||||
return d_kv1->find(*d_kv2) != bytes::npos;
|
||||
return rjson::base64_decode(kv1.value).find(rjson::base64_decode(kv2.value)) != bytes::npos;
|
||||
} else if (is_set_of(kv1.name, kv2.name)) {
|
||||
for (auto i = kv1.value.Begin(); i != kv1.value.End(); ++i) {
|
||||
if (*i == kv2.value) {
|
||||
@@ -285,11 +273,11 @@ bool check_CONTAINS(const rjson::value* v1, const rjson::value& v2, bool v1_from
|
||||
}
|
||||
|
||||
// Check if two JSON-encoded values match with the NOT_CONTAINS relation
|
||||
static bool check_NOT_CONTAINS(const rjson::value* v1, const rjson::value& v2, bool v1_from_query, bool v2_from_query) {
|
||||
static bool check_NOT_CONTAINS(const rjson::value* v1, const rjson::value& v2) {
|
||||
if (!v1) {
|
||||
return false;
|
||||
}
|
||||
return !check_CONTAINS(v1, v2, v1_from_query, v2_from_query);
|
||||
return !check_CONTAINS(v1, v2);
|
||||
}
|
||||
|
||||
// Check if a JSON-encoded value equals any element of an array, which must have at least one element.
|
||||
@@ -386,12 +374,7 @@ bool check_compare(const rjson::value* v1, const rjson::value& v2, const Compara
|
||||
std::string_view(kv2.value.GetString(), kv2.value.GetStringLength()));
|
||||
}
|
||||
if (kv1.name == "B") {
|
||||
auto d_kv1 = unwrap_bytes(kv1.value, v1_from_query);
|
||||
auto d_kv2 = unwrap_bytes(kv2.value, v2_from_query);
|
||||
if(!d_kv1 || !d_kv2) {
|
||||
return false;
|
||||
}
|
||||
return cmp(*d_kv1, *d_kv2);
|
||||
return cmp(rjson::base64_decode(kv1.value), rjson::base64_decode(kv2.value));
|
||||
}
|
||||
// cannot reach here, as check_comparable_type() verifies the type is one
|
||||
// of the above options.
|
||||
@@ -481,13 +464,7 @@ static bool check_BETWEEN(const rjson::value* v, const rjson::value& lb, const r
|
||||
bounds_from_query);
|
||||
}
|
||||
if (kv_v.name == "B") {
|
||||
auto d_kv_v = unwrap_bytes(kv_v.value, v_from_query);
|
||||
auto d_kv_lb = unwrap_bytes(kv_lb.value, lb_from_query);
|
||||
auto d_kv_ub = unwrap_bytes(kv_ub.value, ub_from_query);
|
||||
if(!d_kv_v || !d_kv_lb || !d_kv_ub) {
|
||||
return false;
|
||||
}
|
||||
return check_BETWEEN(*d_kv_v, *d_kv_lb, *d_kv_ub, bounds_from_query);
|
||||
return check_BETWEEN(rjson::base64_decode(kv_v.value), rjson::base64_decode(kv_lb.value), rjson::base64_decode(kv_ub.value), bounds_from_query);
|
||||
}
|
||||
if (v_from_query) {
|
||||
throw api_error::validation(
|
||||
@@ -580,7 +557,7 @@ static bool verify_expected_one(const rjson::value& condition, const rjson::valu
|
||||
format("CONTAINS operator requires a single AttributeValue of type String, Number, or Binary, "
|
||||
"got {} instead", argtype));
|
||||
}
|
||||
return check_CONTAINS(got, arg, false, true);
|
||||
return check_CONTAINS(got, arg);
|
||||
}
|
||||
case comparison_operator_type::NOT_CONTAINS:
|
||||
{
|
||||
@@ -594,7 +571,7 @@ static bool verify_expected_one(const rjson::value& condition, const rjson::valu
|
||||
format("CONTAINS operator requires a single AttributeValue of type String, Number, or Binary, "
|
||||
"got {} instead", argtype));
|
||||
}
|
||||
return check_NOT_CONTAINS(got, arg, false, true);
|
||||
return check_NOT_CONTAINS(got, arg);
|
||||
}
|
||||
}
|
||||
throw std::logic_error(format("Internal error: corrupted operator enum: {}", int(op)));
|
||||
|
||||
@@ -38,7 +38,7 @@ conditional_operator_type get_conditional_operator(const rjson::value& req);
|
||||
bool verify_expected(const rjson::value& req, const rjson::value* previous_item);
|
||||
bool verify_condition(const rjson::value& condition, bool require_all, const rjson::value* previous_item);
|
||||
|
||||
bool check_CONTAINS(const rjson::value* v1, const rjson::value& v2, bool v1_from_query, bool v2_from_query);
|
||||
bool check_CONTAINS(const rjson::value* v1, const rjson::value& v2);
|
||||
bool check_BEGINS_WITH(const rjson::value* v1, const rjson::value& v2, bool v1_from_query, bool v2_from_query);
|
||||
|
||||
bool verify_condition_expression(
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace alternator {
|
||||
// api_error into a JSON object, and that is returned to the user.
|
||||
class api_error final : public std::exception {
|
||||
public:
|
||||
using status_type = http::reply::status_type;
|
||||
using status_type = httpd::reply::status_type;
|
||||
status_type _http_code;
|
||||
std::string _type;
|
||||
std::string _msg;
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
return api_error("TableNotFoundException", std::move(msg));
|
||||
}
|
||||
static api_error internal(std::string msg) {
|
||||
return api_error("InternalServerError", std::move(msg), http::reply::status_type::internal_server_error);
|
||||
return api_error("InternalServerError", std::move(msg), reply::status_type::internal_server_error);
|
||||
}
|
||||
|
||||
// Provide the "std::exception" interface, to make it easier to print this
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
#include <seastar/core/sleep.hh>
|
||||
#include "alternator/executor.hh"
|
||||
#include "log.hh"
|
||||
#include "schema/schema_builder.hh"
|
||||
#include "schema_builder.hh"
|
||||
#include "data_dictionary/keyspace_metadata.hh"
|
||||
#include "exceptions/exceptions.hh"
|
||||
#include "timestamp.hh"
|
||||
#include "types/map.hh"
|
||||
#include "schema/schema.hh"
|
||||
#include "schema.hh"
|
||||
#include "query-request.hh"
|
||||
#include "query-result-reader.hh"
|
||||
#include "cql3/selection/selection.hh"
|
||||
@@ -34,14 +34,13 @@
|
||||
#include "expressions.hh"
|
||||
#include "conditions.hh"
|
||||
#include "cql3/constants.hh"
|
||||
#include "cql3/util.hh"
|
||||
#include <optional>
|
||||
#include "utils/overloaded_functor.hh"
|
||||
#include <seastar/json/json_elements.hh>
|
||||
#include <boost/algorithm/cxx11/any_of.hpp>
|
||||
#include "collection_mutation.hh"
|
||||
#include "db/query_context.hh"
|
||||
#include "schema/schema.hh"
|
||||
#include "schema.hh"
|
||||
#include "db/tags/extension.hh"
|
||||
#include "db/tags/utils.hh"
|
||||
#include "alternator/rmw_operation.hh"
|
||||
@@ -51,13 +50,11 @@
|
||||
#include <unordered_set>
|
||||
#include "service/storage_proxy.hh"
|
||||
#include "gms/gossiper.hh"
|
||||
#include "schema/schema_registry.hh"
|
||||
#include "schema_registry.hh"
|
||||
#include "utils/error_injection.hh"
|
||||
#include "db/schema_tables.hh"
|
||||
#include "utils/rjson.hh"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
logging::logger elogger("alternator-executor");
|
||||
|
||||
namespace alternator {
|
||||
@@ -117,7 +114,8 @@ std::string json_string::to_json() const {
|
||||
void executor::supplement_table_info(rjson::value& descr, const schema& schema, service::storage_proxy& sp) {
|
||||
rjson::add(descr, "CreationDateTime", rjson::value(std::chrono::duration_cast<std::chrono::seconds>(gc_clock::now().time_since_epoch()).count()));
|
||||
rjson::add(descr, "TableStatus", "ACTIVE");
|
||||
rjson::add(descr, "TableId", rjson::from_string(schema.id().to_sstring()));
|
||||
auto schema_id_str = schema.id().to_sstring();
|
||||
rjson::add(descr, "TableId", rjson::from_string(schema_id_str));
|
||||
|
||||
executor::supplement_table_stream_info(descr, schema, sp);
|
||||
}
|
||||
@@ -129,20 +127,6 @@ void executor::supplement_table_info(rjson::value& descr, const schema& schema,
|
||||
// See https://github.com/scylladb/scylla/issues/4480
|
||||
static constexpr int max_table_name_length = 222;
|
||||
|
||||
static bool valid_table_name_chars(std::string_view name) {
|
||||
for (auto c : name) {
|
||||
if ((c < 'a' || c > 'z') &&
|
||||
(c < 'A' || c > 'Z') &&
|
||||
(c < '0' || c > '9') &&
|
||||
c != '_' &&
|
||||
c != '-' &&
|
||||
c != '.') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// The DynamoDB developer guide, https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.NamingRules
|
||||
// specifies that table names "names must be between 3 and 255 characters long
|
||||
// and can contain only the following characters: a-z, A-Z, 0-9, _ (underscore), - (dash), . (dot)
|
||||
@@ -152,7 +136,8 @@ static void validate_table_name(const std::string& name) {
|
||||
throw api_error::validation(
|
||||
format("TableName must be at least 3 characters long and at most {} characters long", max_table_name_length));
|
||||
}
|
||||
if (!valid_table_name_chars(name)) {
|
||||
static const std::regex valid_table_name_chars ("[a-zA-Z0-9_.-]*");
|
||||
if (!std::regex_match(name.c_str(), valid_table_name_chars)) {
|
||||
throw api_error::validation(
|
||||
"TableName must satisfy regular expression pattern: [a-zA-Z0-9_.-]+");
|
||||
}
|
||||
@@ -168,10 +153,11 @@ static void validate_table_name(const std::string& name) {
|
||||
// The view_name() function assumes the table_name has already been validated
|
||||
// but validates the legality of index_name and the combination of both.
|
||||
static std::string view_name(const std::string& table_name, std::string_view index_name, const std::string& delim = ":") {
|
||||
static const std::regex valid_index_name_chars ("[a-zA-Z0-9_.-]*");
|
||||
if (index_name.length() < 3) {
|
||||
throw api_error::validation("IndexName must be at least 3 characters long");
|
||||
}
|
||||
if (!valid_table_name_chars(index_name)) {
|
||||
if (!std::regex_match(index_name.data(), valid_index_name_chars)) {
|
||||
throw api_error::validation(
|
||||
format("IndexName '{}' must satisfy regular expression pattern: [a-zA-Z0-9_.-]+", index_name));
|
||||
}
|
||||
@@ -774,6 +760,7 @@ future<executor::request_return_type> executor::tag_resource(client_state& clien
|
||||
co_return api_error::access_denied("Incorrect resource identifier");
|
||||
}
|
||||
schema_ptr schema = get_table_from_arn(_proxy, rjson::to_string_view(*arn));
|
||||
std::map<sstring, sstring> tags_map = get_tags_of_table_or_throw(schema);
|
||||
const rjson::value* tags = rjson::find(request, "Tags");
|
||||
if (!tags || !tags->IsArray()) {
|
||||
co_return api_error::validation("Cannot parse tags");
|
||||
@@ -781,9 +768,8 @@ future<executor::request_return_type> executor::tag_resource(client_state& clien
|
||||
if (tags->Size() < 1) {
|
||||
co_return api_error::validation("The number of tags must be at least 1") ;
|
||||
}
|
||||
co_await db::modify_tags(_mm, schema->ks_name(), schema->cf_name(), [tags](std::map<sstring, sstring>& tags_map) {
|
||||
update_tags_map(*tags, tags_map, update_tags_action::add_tags);
|
||||
});
|
||||
update_tags_map(*tags, tags_map, update_tags_action::add_tags);
|
||||
co_await db::update_tags(_mm, schema, std::move(tags_map));
|
||||
co_return json_string("");
|
||||
}
|
||||
|
||||
@@ -801,9 +787,9 @@ future<executor::request_return_type> executor::untag_resource(client_state& cli
|
||||
|
||||
schema_ptr schema = get_table_from_arn(_proxy, rjson::to_string_view(*arn));
|
||||
|
||||
co_await db::modify_tags(_mm, schema->ks_name(), schema->cf_name(), [tags](std::map<sstring, sstring>& tags_map) {
|
||||
update_tags_map(*tags, tags_map, update_tags_action::delete_tags);
|
||||
});
|
||||
std::map<sstring, sstring> tags_map = get_tags_of_table_or_throw(schema);
|
||||
update_tags_map(*tags, tags_map, update_tags_action::delete_tags);
|
||||
co_await db::update_tags(_mm, schema, std::move(tags_map));
|
||||
co_return json_string("");
|
||||
}
|
||||
|
||||
@@ -941,10 +927,9 @@ static future<executor::request_return_type> create_table_on_shard0(tracing::tra
|
||||
if (!range_key.empty() && range_key != view_hash_key && range_key != view_range_key) {
|
||||
add_column(view_builder, range_key, attribute_definitions, column_kind::clustering_key);
|
||||
}
|
||||
sstring where_clause = format("{} IS NOT NULL", cql3::util::maybe_quote(view_hash_key));
|
||||
sstring where_clause = "\"" + view_hash_key + "\" IS NOT NULL";
|
||||
if (!view_range_key.empty()) {
|
||||
where_clause = format("{} AND {} IS NOT NULL", where_clause,
|
||||
cql3::util::maybe_quote(view_range_key));
|
||||
where_clause = where_clause + " AND \"" + view_hash_key + "\" IS NOT NULL";
|
||||
}
|
||||
where_clauses.push_back(std::move(where_clause));
|
||||
view_builders.emplace_back(std::move(view_builder));
|
||||
@@ -999,10 +984,9 @@ static future<executor::request_return_type> create_table_on_shard0(tracing::tra
|
||||
// Note above we don't need to add virtual columns, as all
|
||||
// base columns were copied to view. TODO: reconsider the need
|
||||
// for virtual columns when we support Projection.
|
||||
sstring where_clause = format("{} IS NOT NULL", cql3::util::maybe_quote(view_hash_key));
|
||||
sstring where_clause = "\"" + view_hash_key + "\" IS NOT NULL";
|
||||
if (!view_range_key.empty()) {
|
||||
where_clause = format("{} AND {} IS NOT NULL", where_clause,
|
||||
cql3::util::maybe_quote(view_range_key));
|
||||
where_clause = where_clause + " AND \"" + view_range_key + "\" IS NOT NULL";
|
||||
}
|
||||
where_clauses.push_back(std::move(where_clause));
|
||||
view_builders.emplace_back(std::move(view_builder));
|
||||
@@ -1545,7 +1529,7 @@ future<executor::request_return_type> rmw_operation::execute(service::storage_pr
|
||||
// This is the old, unsafe, read before write which does first
|
||||
// a read, then a write. TODO: remove this mode entirely.
|
||||
return get_previous_item(proxy, client_state, schema(), _pk, _ck, permit, stats).then(
|
||||
[this, &proxy, trace_state, permit = std::move(permit)] (std::unique_ptr<rjson::value> previous_item) mutable {
|
||||
[this, &client_state, &proxy, trace_state, permit = std::move(permit)] (std::unique_ptr<rjson::value> previous_item) mutable {
|
||||
std::optional<mutation> m = apply(std::move(previous_item), api::new_timestamp());
|
||||
if (!m) {
|
||||
return make_ready_future<executor::request_return_type>(api_error::conditional_check_failed("Failed condition."));
|
||||
@@ -2318,7 +2302,7 @@ void executor::describe_single_item(const cql3::selection::selection& selection,
|
||||
rjson::add_with_string_name(field, type_to_string((*column_it)->type), json_key_column_value(*cell, **column_it));
|
||||
}
|
||||
} else if (cell) {
|
||||
auto deserialized = attrs_type()->deserialize(*cell);
|
||||
auto deserialized = attrs_type()->deserialize(*cell, cql_serialization_format::latest());
|
||||
auto keys_and_values = value_cast<map_type_impl::native_type>(deserialized);
|
||||
for (auto entry : keys_and_values) {
|
||||
std::string attr_name = value_cast<sstring>(entry.first);
|
||||
@@ -2353,7 +2337,7 @@ std::optional<rjson::value> executor::describe_single_item(schema_ptr schema,
|
||||
const std::optional<attrs_to_get>& attrs_to_get) {
|
||||
rjson::value item = rjson::empty_object();
|
||||
|
||||
cql3::selection::result_set_builder builder(selection, gc_clock::now());
|
||||
cql3::selection::result_set_builder builder(selection, gc_clock::now(), cql_serialization_format::latest());
|
||||
query::result_view::consume(query_result, slice, cql3::selection::result_set_builder::visitor(builder, *schema, selection));
|
||||
|
||||
auto result_set = builder.build();
|
||||
@@ -2376,7 +2360,7 @@ std::vector<rjson::value> executor::describe_multi_item(schema_ptr schema,
|
||||
const cql3::selection::selection& selection,
|
||||
const query::result& query_result,
|
||||
const std::optional<attrs_to_get>& attrs_to_get) {
|
||||
cql3::selection::result_set_builder builder(selection, gc_clock::now());
|
||||
cql3::selection::result_set_builder builder(selection, gc_clock::now(), cql_serialization_format::latest());
|
||||
query::result_view::consume(query_result, slice, cql3::selection::result_set_builder::visitor(builder, *schema, selection));
|
||||
auto result_set = builder.build();
|
||||
std::vector<rjson::value> ret;
|
||||
@@ -3120,10 +3104,20 @@ future<executor::request_return_type> executor::get_item(client_state& client_st
|
||||
});
|
||||
}
|
||||
|
||||
// is_big() checks approximately if the given JSON value is "bigger" than
|
||||
// the given big_size number of bytes. The goal is to *quickly* detect
|
||||
// oversized JSON that, for example, is too large to be serialized to a
|
||||
// contiguous string - we don't need an accurate size for that. Moreover,
|
||||
// as soon as we detect that the JSON is indeed "big", we can return true
|
||||
// and don't need to continue calculating its exact size.
|
||||
// For simplicity, we use a recursive implementation. This is fine because
|
||||
// Alternator limits the depth of JSONs it reads from inputs, and doesn't
|
||||
// add more than a couple of levels in its own output construction.
|
||||
|
||||
static void check_big_object(const rjson::value& val, int& size_left);
|
||||
static void check_big_array(const rjson::value& val, int& size_left);
|
||||
|
||||
bool is_big(const rjson::value& val, int big_size) {
|
||||
static bool is_big(const rjson::value& val, int big_size = 100'000) {
|
||||
if (val.IsString()) {
|
||||
return ssize_t(val.GetStringLength()) > big_size;
|
||||
} else if (val.IsObject()) {
|
||||
@@ -3514,7 +3508,7 @@ public:
|
||||
rjson::add_with_string_name(field, type_to_string((*_column_it)->type), json_key_column_value(bv, **_column_it));
|
||||
}
|
||||
} else {
|
||||
auto deserialized = attrs_type()->deserialize(bv);
|
||||
auto deserialized = attrs_type()->deserialize(bv, cql_serialization_format::latest());
|
||||
auto keys_and_values = value_cast<map_type_impl::native_type>(deserialized);
|
||||
for (auto entry : keys_and_values) {
|
||||
std::string attr_name = value_cast<sstring>(entry.first);
|
||||
@@ -3571,7 +3565,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static std::tuple<rjson::value, size_t> describe_items(const cql3::selection::selection& selection, std::unique_ptr<cql3::result_set> result_set, std::optional<attrs_to_get>&& attrs_to_get, filter&& filter) {
|
||||
static std::tuple<rjson::value, size_t> describe_items(schema_ptr schema, const query::partition_slice& slice, const cql3::selection::selection& selection, std::unique_ptr<cql3::result_set> result_set, std::optional<attrs_to_get>&& attrs_to_get, filter&& filter) {
|
||||
describe_items_visitor visitor(selection.get_columns(), attrs_to_get, filter);
|
||||
result_set->visit(visitor);
|
||||
auto scanned_count = visitor.get_scanned_count();
|
||||
@@ -3621,7 +3615,7 @@ static rjson::value encode_paging_state(const schema& schema, const service::pag
|
||||
// We conditionally include these fields when reading CQL tables through alternator.
|
||||
if (!is_alternator_keyspace(schema.ks_name()) && (!pos.has_key() || pos.get_bound_weight() != bound_weight::equal)) {
|
||||
rjson::add_with_string_name(last_evaluated_key, scylla_paging_region, rjson::empty_object());
|
||||
rjson::add(last_evaluated_key[scylla_paging_region.data()], "S", rjson::from_string(fmt::to_string(pos.region())));
|
||||
rjson::add(last_evaluated_key[scylla_paging_region.data()], "S", rjson::from_string(to_string(pos.region())));
|
||||
rjson::add_with_string_name(last_evaluated_key, scylla_paging_weight, rjson::empty_object());
|
||||
rjson::add(last_evaluated_key[scylla_paging_weight.data()], "N", static_cast<int>(pos.get_bound_weight()));
|
||||
}
|
||||
@@ -3648,7 +3642,7 @@ static future<executor::request_return_type> do_query(service::storage_proxy& pr
|
||||
|
||||
if (exclusive_start_key) {
|
||||
partition_key pk = pk_from_json(*exclusive_start_key, schema);
|
||||
auto pos = position_in_partition::for_partition_start();
|
||||
auto pos = position_in_partition(position_in_partition::partition_start_tag_t());
|
||||
if (schema->clustering_key_size() > 0) {
|
||||
pos = pos_from_json(*exclusive_start_key, schema);
|
||||
}
|
||||
@@ -3685,7 +3679,7 @@ static future<executor::request_return_type> do_query(service::storage_proxy& pr
|
||||
}
|
||||
auto paging_state = rs->get_metadata().paging_state();
|
||||
bool has_filter = filter;
|
||||
auto [items, size] = describe_items(*selection, std::move(rs), std::move(attrs_to_get), std::move(filter));
|
||||
auto [items, size] = describe_items(schema, partition_slice, *selection, std::move(rs), std::move(attrs_to_get), std::move(filter));
|
||||
if (paging_state) {
|
||||
rjson::add(items, "LastEvaluatedKey", encode_paging_state(*schema, *paging_state));
|
||||
}
|
||||
@@ -3694,7 +3688,8 @@ static future<executor::request_return_type> do_query(service::storage_proxy& pr
|
||||
// update our "filtered_row_matched_total" for all the rows matched, despited the filter
|
||||
cql_stats.filtered_rows_matched_total += size;
|
||||
}
|
||||
if (is_big(items)) {
|
||||
// TODO: better threshold
|
||||
if (size > 10) {
|
||||
return make_ready_future<executor::request_return_type>(make_streamed(std::move(items)));
|
||||
}
|
||||
return make_ready_future<executor::request_return_type>(make_jsonable(std::move(items)));
|
||||
|
||||
@@ -239,15 +239,4 @@ public:
|
||||
static void supplement_table_stream_info(rjson::value& descr, const schema& schema, service::storage_proxy& sp);
|
||||
};
|
||||
|
||||
// is_big() checks approximately if the given JSON value is "bigger" than
|
||||
// the given big_size number of bytes. The goal is to *quickly* detect
|
||||
// oversized JSON that, for example, is too large to be serialized to a
|
||||
// contiguous string - we don't need an accurate size for that. Moreover,
|
||||
// as soon as we detect that the JSON is indeed "big", we can return true
|
||||
// and don't need to continue calculating its exact size.
|
||||
// For simplicity, we use a recursive implementation. This is fine because
|
||||
// Alternator limits the depth of JSONs it reads from inputs, and doesn't
|
||||
// add more than a couple of levels in its own output construction.
|
||||
bool is_big(const rjson::value& val, int big_size = 100'000);
|
||||
|
||||
}
|
||||
|
||||
@@ -634,8 +634,7 @@ std::unordered_map<std::string_view, function_handler_type*> function_handlers {
|
||||
}
|
||||
rjson::value v1 = calculate_value(f._parameters[0], caller, previous_item);
|
||||
rjson::value v2 = calculate_value(f._parameters[1], caller, previous_item);
|
||||
return to_bool_json(check_CONTAINS(v1.IsNull() ? nullptr : &v1, v2,
|
||||
f._parameters[0].is_constant(), f._parameters[1].is_constant()));
|
||||
return to_bool_json(check_CONTAINS(v1.IsNull() ? nullptr : &v1, v2));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
/*
|
||||
* Parsed representation of expressions and their components.
|
||||
*
|
||||
* Types in alternator::parsed namespace are used for holding the parse
|
||||
* Types in alternator::parse namespace are used for holding the parse
|
||||
* tree - objects generated by the Antlr rules after parsing an expression.
|
||||
* Because of the way Antlr works, all these objects are default-constructed
|
||||
* first, and then assigned when the rule is completed, so all these types
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "rapidjson/writer.h"
|
||||
#include "concrete_types.hh"
|
||||
#include "cql3/type_json.hh"
|
||||
#include "mutation/position_in_partition.hh"
|
||||
#include "position_in_partition.hh"
|
||||
|
||||
static logging::logger slogger("alternator-serialization");
|
||||
|
||||
@@ -59,9 +59,7 @@ struct from_json_visitor {
|
||||
bo.write(t.from_string(rjson::to_string_view(v)));
|
||||
}
|
||||
void operator()(const bytes_type_impl& t) const {
|
||||
// FIXME: it's difficult at this point to get information if value was provided
|
||||
// in request or comes from the storage, for now we assume it's user's fault.
|
||||
bo.write(*unwrap_bytes(v, true));
|
||||
bo.write(rjson::base64_decode(v));
|
||||
}
|
||||
void operator()(const boolean_type_impl& t) const {
|
||||
bo.write(boolean_type->decompose(v.GetBool()));
|
||||
@@ -75,7 +73,7 @@ struct from_json_visitor {
|
||||
}
|
||||
// default
|
||||
void operator()(const abstract_type& t) const {
|
||||
bo.write(from_json_object(t, v));
|
||||
bo.write(from_json_object(t, v, cql_serialization_format::internal()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -200,9 +198,7 @@ bytes get_key_from_typed_value(const rjson::value& key_typed_value, const column
|
||||
format("The AttributeValue for a key attribute cannot contain an empty string value. Key: {}", column.name_as_text()));
|
||||
}
|
||||
if (column.type == bytes_type) {
|
||||
// FIXME: it's difficult at this point to get information if value was provided
|
||||
// in request or comes from the storage, for now we assume it's user's fault.
|
||||
return *unwrap_bytes(value, true);
|
||||
return rjson::base64_decode(value);
|
||||
} else {
|
||||
return column.type->from_string(value_view);
|
||||
}
|
||||
@@ -214,7 +210,7 @@ rjson::value json_key_column_value(bytes_view cell, const column_definition& col
|
||||
std::string b64 = base64_encode(cell);
|
||||
return rjson::from_string(b64);
|
||||
} if (column.type == utf8_type) {
|
||||
return rjson::from_string(reinterpret_cast<const char*>(cell.data()), cell.size());
|
||||
return rjson::from_string(std::string(reinterpret_cast<const char*>(cell.data()), cell.size()));
|
||||
} else if (column.type == decimal_type) {
|
||||
// FIXME: use specialized Alternator number type, not the more
|
||||
// general "decimal_type". A dedicated type can be more efficient
|
||||
@@ -265,6 +261,7 @@ position_in_partition pos_from_json(const rjson::value& item, schema_ptr schema)
|
||||
if (bool(region_item) != bool(weight_item)) {
|
||||
throw api_error::validation("Malformed value object: region and weight has to be either both missing or both present");
|
||||
}
|
||||
partition_region region;
|
||||
bound_weight weight;
|
||||
if (region_item) {
|
||||
auto region_view = rjson::to_string_view(get_typed_value(*region_item, "S", scylla_paging_region, "key region"));
|
||||
@@ -282,7 +279,7 @@ position_in_partition pos_from_json(const rjson::value& item, schema_ptr schema)
|
||||
return position_in_partition(region, weight, region == partition_region::clustered ? std::optional(std::move(ck)) : std::nullopt);
|
||||
}
|
||||
if (ck.is_empty()) {
|
||||
return position_in_partition::for_partition_start();
|
||||
return position_in_partition(position_in_partition::partition_start_tag_t());
|
||||
}
|
||||
return position_in_partition::for_key(std::move(ck));
|
||||
}
|
||||
@@ -322,17 +319,6 @@ std::optional<big_decimal> try_unwrap_number(const rjson::value& v) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<bytes> unwrap_bytes(const rjson::value& value, bool from_query) {
|
||||
try {
|
||||
return rjson::base64_decode(value);
|
||||
} catch (...) {
|
||||
if (from_query) {
|
||||
throw api_error::serialization(format("Invalid base64 data"));
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
const std::pair<std::string, const rjson::value*> unwrap_set(const rjson::value& v) {
|
||||
if (!v.IsObject() || v.MemberCount() != 1) {
|
||||
return {"", nullptr};
|
||||
@@ -362,7 +348,7 @@ rjson::value number_add(const rjson::value& v1, const rjson::value& v2) {
|
||||
auto n1 = unwrap_number(v1, "UpdateExpression");
|
||||
auto n2 = unwrap_number(v2, "UpdateExpression");
|
||||
rjson::value ret = rjson::empty_object();
|
||||
sstring str_ret = (n1 + n2).to_string();
|
||||
std::string str_ret = std::string((n1 + n2).to_string());
|
||||
rjson::add(ret, "N", rjson::from_string(str_ret));
|
||||
return ret;
|
||||
}
|
||||
@@ -371,7 +357,7 @@ rjson::value number_subtract(const rjson::value& v1, const rjson::value& v2) {
|
||||
auto n1 = unwrap_number(v1, "UpdateExpression");
|
||||
auto n2 = unwrap_number(v2, "UpdateExpression");
|
||||
rjson::value ret = rjson::empty_object();
|
||||
sstring str_ret = (n1 - n2).to_string();
|
||||
std::string str_ret = std::string((n1 - n2).to_string());
|
||||
rjson::add(ret, "N", rjson::from_string(str_ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <optional>
|
||||
#include "types/types.hh"
|
||||
#include "schema/schema_fwd.hh"
|
||||
#include "types.hh"
|
||||
#include "schema_fwd.hh"
|
||||
#include "keys.hh"
|
||||
#include "utils/rjson.hh"
|
||||
#include "utils/big_decimal.hh"
|
||||
@@ -62,11 +62,6 @@ big_decimal unwrap_number(const rjson::value& v, std::string_view diagnostic);
|
||||
// when the given v does not encode a number.
|
||||
std::optional<big_decimal> try_unwrap_number(const rjson::value& v);
|
||||
|
||||
// unwrap_bytes decodes byte value, on decoding failure it either raises api_error::serialization
|
||||
// iff from_query is true or returns unset optional iff from_query is false.
|
||||
// Therefore it's safe to dereference returned optional when called with from_query equal true.
|
||||
std::optional<bytes> unwrap_bytes(const rjson::value& value, bool from_query);
|
||||
|
||||
// Check if a given JSON object encodes a set (i.e., it is a {"SS": [...]}, or "NS", "BS"
|
||||
// and returns set's type and a pointer to that set. If the object does not encode a set,
|
||||
// returned value is {"", nullptr}
|
||||
|
||||
@@ -24,13 +24,10 @@
|
||||
#include "gms/gossiper.hh"
|
||||
#include "utils/overloaded_functor.hh"
|
||||
#include "utils/fb_utilities.hh"
|
||||
#include "utils/aws_sigv4.hh"
|
||||
|
||||
static logging::logger slogger("alternator-server");
|
||||
|
||||
using namespace httpd;
|
||||
using request = http::request;
|
||||
using reply = http::reply;
|
||||
|
||||
namespace alternator {
|
||||
|
||||
@@ -146,7 +143,7 @@ public:
|
||||
std::unique_ptr<request> req, std::unique_ptr<reply> rep) override {
|
||||
handle_CORS(*req, *rep, false);
|
||||
return _f_handle(std::move(req), std::move(rep)).then(
|
||||
[](std::unique_ptr<reply> rep) {
|
||||
[this](std::unique_ptr<reply> rep) {
|
||||
rep->set_mime_type("application/x-amz-json-1.0");
|
||||
rep->done();
|
||||
return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
|
||||
@@ -320,13 +317,8 @@ future<std::string> server::verify_signature(const request& req, const chunked_c
|
||||
region = std::move(region),
|
||||
service = std::move(service),
|
||||
user_signature = std::move(user_signature)] (key_cache::value_ptr key_ptr) {
|
||||
std::string signature;
|
||||
try {
|
||||
signature = utils::aws::get_signature(user, *key_ptr, std::string_view(host), "/", req._method,
|
||||
datestamp, signed_headers_str, signed_headers_map, &content, region, service, "");
|
||||
} catch (const std::exception& e) {
|
||||
throw api_error::invalid_signature(e.what());
|
||||
}
|
||||
std::string signature = get_signature(user, *key_ptr, std::string_view(host), req._method,
|
||||
datestamp, signed_headers_str, signed_headers_map, content, region, service, "");
|
||||
|
||||
if (signature != std::string_view(user_signature)) {
|
||||
_key_cache.remove(user);
|
||||
|
||||
@@ -27,11 +27,11 @@ using chunked_content = rjson::chunked_content;
|
||||
class server {
|
||||
static constexpr size_t content_length_limit = 16*MB;
|
||||
using alternator_callback = std::function<future<executor::request_return_type>(executor&, executor::client_state&,
|
||||
tracing::trace_state_ptr, service_permit, rjson::value, std::unique_ptr<http::request>)>;
|
||||
tracing::trace_state_ptr, service_permit, rjson::value, std::unique_ptr<request>)>;
|
||||
using alternator_callbacks_map = std::unordered_map<std::string_view, alternator_callback>;
|
||||
|
||||
httpd::http_server _http_server;
|
||||
httpd::http_server _https_server;
|
||||
http_server _http_server;
|
||||
http_server _https_server;
|
||||
executor& _executor;
|
||||
service::storage_proxy& _proxy;
|
||||
gms::gossiper& _gossiper;
|
||||
@@ -76,8 +76,8 @@ public:
|
||||
private:
|
||||
void set_routes(seastar::httpd::routes& r);
|
||||
// If verification succeeds, returns the authenticated user's username
|
||||
future<std::string> verify_signature(const seastar::http::request&, const chunked_content&);
|
||||
future<executor::request_return_type> handle_api_request(std::unique_ptr<http::request> req);
|
||||
future<std::string> verify_signature(const seastar::httpd::request&, const chunked_content&);
|
||||
future<executor::request_return_type> handle_api_request(std::unique_ptr<request> req);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,14 +27,13 @@
|
||||
#include "cql3/result_set.hh"
|
||||
#include "cql3/type_json.hh"
|
||||
#include "cql3/column_identifier.hh"
|
||||
#include "schema/schema_builder.hh"
|
||||
#include "schema_builder.hh"
|
||||
#include "service/storage_proxy.hh"
|
||||
#include "gms/feature.hh"
|
||||
#include "gms/feature_service.hh"
|
||||
|
||||
#include "executor.hh"
|
||||
#include "rmw_operation.hh"
|
||||
#include "data_dictionary/data_dictionary.hh"
|
||||
|
||||
/**
|
||||
* Base template type to implement rapidjson::internal::TypeHelper<...>:s
|
||||
@@ -141,43 +140,24 @@ namespace alternator {
|
||||
future<alternator::executor::request_return_type> alternator::executor::list_streams(client_state& client_state, service_permit permit, rjson::value request) {
|
||||
_stats.api_operations.list_streams++;
|
||||
|
||||
auto limit = rjson::get_opt<int>(request, "Limit").value_or(100);
|
||||
auto limit = rjson::get_opt<int>(request, "Limit").value_or(std::numeric_limits<int>::max());
|
||||
auto streams_start = rjson::get_opt<stream_arn>(request, "ExclusiveStartStreamArn");
|
||||
auto table = find_table(_proxy, request);
|
||||
auto db = _proxy.data_dictionary();
|
||||
auto cfs = db.get_tables();
|
||||
auto i = cfs.begin();
|
||||
auto e = cfs.end();
|
||||
|
||||
if (limit < 1) {
|
||||
throw api_error::validation("Limit must be 1 or more");
|
||||
}
|
||||
|
||||
std::vector<data_dictionary::table> cfs;
|
||||
|
||||
if (table) {
|
||||
auto log_name = cdc::log_name(table->cf_name());
|
||||
try {
|
||||
cfs.emplace_back(db.find_table(table->ks_name(), log_name));
|
||||
} catch (data_dictionary::no_such_column_family&) {
|
||||
cfs.clear();
|
||||
}
|
||||
} else {
|
||||
cfs = db.get_tables();
|
||||
}
|
||||
|
||||
// # 12601 (maybe?) - sort the set of tables on ID. This should ensure we never
|
||||
// generate duplicates in a paged listing here. Can obviously miss things if they
|
||||
// are added between paged calls and end up with a "smaller" UUID/ARN, but that
|
||||
// is to be expected.
|
||||
if (std::cmp_less(limit, cfs.size()) || streams_start) {
|
||||
std::sort(cfs.begin(), cfs.end(), [](const data_dictionary::table& t1, const data_dictionary::table& t2) {
|
||||
return t1.schema()->id().uuid() < t2.schema()->id().uuid();
|
||||
});
|
||||
}
|
||||
|
||||
auto i = cfs.begin();
|
||||
auto e = cfs.end();
|
||||
|
||||
// TODO: the unordered_map here is not really well suited for partial
|
||||
// querying - we're sorting on local hash order, and creating a table
|
||||
// between queries may or may not miss info. But that should be rare,
|
||||
// and we can probably expect this to be a single call.
|
||||
if (streams_start) {
|
||||
i = std::find_if(i, e, [&](const data_dictionary::table& t) {
|
||||
i = std::find_if(i, e, [&](data_dictionary::table t) {
|
||||
return t.schema()->id().uuid() == streams_start
|
||||
&& cdc::get_base_table(db.real_database(), *t.schema())
|
||||
&& is_alternator_keyspace(t.schema()->ks_name())
|
||||
@@ -201,7 +181,14 @@ future<alternator::executor::request_return_type> alternator::executor::list_str
|
||||
if (!is_alternator_keyspace(ks_name)) {
|
||||
continue;
|
||||
}
|
||||
if (table && ks_name != table->ks_name()) {
|
||||
continue;
|
||||
}
|
||||
if (cdc::is_log_for_some_table(db.real_database(), ks_name, cf_name)) {
|
||||
if (table && table != cdc::get_base_table(db.real_database(), *s)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rjson::value new_entry = rjson::empty_object();
|
||||
|
||||
last = i->schema()->id();
|
||||
@@ -429,8 +416,6 @@ static std::chrono::seconds confidence_interval(data_dictionary::database db) {
|
||||
return std::chrono::seconds(db.get_config().alternator_streams_time_window_s());
|
||||
}
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
// Dynamo docs says no data shall live longer than 24h.
|
||||
static constexpr auto dynamodb_streams_max_window = 24h;
|
||||
|
||||
@@ -508,7 +493,7 @@ future<executor::request_return_type> executor::describe_stream(client_state& cl
|
||||
// filter out cdc generations older than the table or now() - cdc::ttl (typically dynamodb_streams_max_window - 24h)
|
||||
auto low_ts = std::max(as_timepoint(schema->id()), db_clock::now() - ttl);
|
||||
|
||||
return _sdks.cdc_get_versioned_streams(low_ts, { normal_token_owners }).then([db, shard_start, limit, ret = std::move(ret), stream_desc = std::move(stream_desc)] (std::map<db_clock::time_point, cdc::streams_version> topologies) mutable {
|
||||
return _sdks.cdc_get_versioned_streams(low_ts, { normal_token_owners }).then([this, db, shard_start, limit, ret = std::move(ret), stream_desc = std::move(stream_desc)] (std::map<db_clock::time_point, cdc::streams_version> topologies) mutable {
|
||||
|
||||
auto e = topologies.end();
|
||||
auto prev = e;
|
||||
@@ -827,7 +812,7 @@ future<executor::request_return_type> executor::get_records(client_state& client
|
||||
}
|
||||
|
||||
if (!schema || !base || !is_alternator_keyspace(schema->ks_name())) {
|
||||
throw api_error::resource_not_found(fmt::to_string(iter.table));
|
||||
throw api_error::resource_not_found(boost::lexical_cast<std::string>(iter.table));
|
||||
}
|
||||
|
||||
tracing::add_table_name(trace_state, schema->ks_name(), schema->cf_name());
|
||||
@@ -898,7 +883,7 @@ future<executor::request_return_type> executor::get_records(client_state& client
|
||||
|
||||
return _proxy.query(schema, std::move(command), std::move(partition_ranges), cl, service::storage_proxy::coordinator_query_options(default_timeout(), std::move(permit), client_state)).then(
|
||||
[this, schema, partition_slice = std::move(partition_slice), selection = std::move(selection), start_time = std::move(start_time), limit, key_names = std::move(key_names), attr_names = std::move(attr_names), type, iter, high_ts] (service::storage_proxy::coordinator_query_result qr) mutable {
|
||||
cql3::selection::result_set_builder builder(*selection, gc_clock::now());
|
||||
cql3::selection::result_set_builder builder(*selection, gc_clock::now(), cql_serialization_format::latest());
|
||||
query::result_view::consume(*qr.query_result, partition_slice, cql3::selection::result_set_builder::visitor(builder, *schema, *selection));
|
||||
|
||||
auto result_set = builder.build();
|
||||
@@ -1027,7 +1012,7 @@ future<executor::request_return_type> executor::get_records(client_state& client
|
||||
// ugh. figure out if we are and end-of-shard
|
||||
auto normal_token_owners = _proxy.get_token_metadata_ptr()->count_normal_token_owners();
|
||||
|
||||
return _sdks.cdc_current_generation_timestamp({ normal_token_owners }).then([this, iter, high_ts, start_time, ret = std::move(ret)](db_clock::time_point ts) mutable {
|
||||
return _sdks.cdc_current_generation_timestamp({ normal_token_owners }).then([this, iter, high_ts, start_time, ret = std::move(ret), nrecords](db_clock::time_point ts) mutable {
|
||||
auto& shard = iter.shard;
|
||||
|
||||
if (shard.time < ts && ts < high_ts) {
|
||||
@@ -1044,7 +1029,8 @@ future<executor::request_return_type> executor::get_records(client_state& client
|
||||
rjson::add(ret, "NextShardIterator", iter);
|
||||
}
|
||||
_stats.api_operations.get_records_latency.add(std::chrono::steady_clock::now() - start_time);
|
||||
if (is_big(ret)) {
|
||||
// TODO: determine a better threshold...
|
||||
if (nrecords > 10) {
|
||||
return make_ready_future<executor::request_return_type>(make_streamed(std::move(ret)));
|
||||
}
|
||||
return make_ready_future<executor::request_return_type>(make_jsonable(std::move(ret)));
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <seastar/core/sstring.hh>
|
||||
#include <seastar/core/coroutine.hh>
|
||||
@@ -18,7 +17,6 @@
|
||||
#include <seastar/coroutine/maybe_yield.hh>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
#include "exceptions/exceptions.hh"
|
||||
#include "gms/gossiper.hh"
|
||||
#include "gms/inet_address.hh"
|
||||
#include "inet_address_vectors.hh"
|
||||
@@ -33,8 +31,8 @@
|
||||
#include "service/pager/query_pagers.hh"
|
||||
#include "gms/feature_service.hh"
|
||||
#include "sstables/types.hh"
|
||||
#include "mutation/mutation.hh"
|
||||
#include "types/types.hh"
|
||||
#include "mutation.hh"
|
||||
#include "types.hh"
|
||||
#include "types/map.hh"
|
||||
#include "utils/rjson.hh"
|
||||
#include "utils/big_decimal.hh"
|
||||
@@ -94,25 +92,24 @@ future<executor::request_return_type> executor::update_time_to_live(client_state
|
||||
}
|
||||
sstring attribute_name(v->GetString(), v->GetStringLength());
|
||||
|
||||
co_await db::modify_tags(_mm, schema->ks_name(), schema->cf_name(), [&](std::map<sstring, sstring>& tags_map) {
|
||||
if (enabled) {
|
||||
if (tags_map.contains(TTL_TAG_KEY)) {
|
||||
throw api_error::validation("TTL is already enabled");
|
||||
}
|
||||
tags_map[TTL_TAG_KEY] = attribute_name;
|
||||
} else {
|
||||
auto i = tags_map.find(TTL_TAG_KEY);
|
||||
if (i == tags_map.end()) {
|
||||
throw api_error::validation("TTL is already disabled");
|
||||
} else if (i->second != attribute_name) {
|
||||
throw api_error::validation(format(
|
||||
"Requested to disable TTL on attribute {}, but a different attribute {} is enabled.",
|
||||
attribute_name, i->second));
|
||||
}
|
||||
tags_map.erase(TTL_TAG_KEY);
|
||||
std::map<sstring, sstring> tags_map = get_tags_of_table_or_throw(schema);
|
||||
if (enabled) {
|
||||
if (tags_map.contains(TTL_TAG_KEY)) {
|
||||
co_return api_error::validation("TTL is already enabled");
|
||||
}
|
||||
});
|
||||
|
||||
tags_map[TTL_TAG_KEY] = attribute_name;
|
||||
} else {
|
||||
auto i = tags_map.find(TTL_TAG_KEY);
|
||||
if (i == tags_map.end()) {
|
||||
co_return api_error::validation("TTL is already disabled");
|
||||
} else if (i->second != attribute_name) {
|
||||
co_return api_error::validation(format(
|
||||
"Requested to disable TTL on attribute {}, but a different attribute {} is enabled.",
|
||||
attribute_name, i->second));
|
||||
}
|
||||
tags_map.erase(TTL_TAG_KEY);
|
||||
}
|
||||
co_await db::update_tags(_mm, schema, std::move(tags_map));
|
||||
// Prepare the response, which contains a TimeToLiveSpecification
|
||||
// basically identical to the request's
|
||||
rjson::value response = rjson::empty_object();
|
||||
@@ -551,34 +548,13 @@ static future<> scan_table_ranges(
|
||||
co_return;
|
||||
}
|
||||
auto units = co_await get_units(page_sem, 1);
|
||||
// We don't need to limit page size in number of rows because there is
|
||||
// a builtin limit of the page's size in bytes. Setting this limit to
|
||||
// 1 is useful for debugging the paging code with moderate-size data.
|
||||
// We don't to limit page size in number of rows because there is a
|
||||
// builtin limit of the page's size in bytes. Setting this limit to 1
|
||||
// is useful for debugging the paging code with moderate-size data.
|
||||
uint32_t limit = std::numeric_limits<uint32_t>::max();
|
||||
// Read a page, and if that times out, try again after a small sleep.
|
||||
// If we didn't catch the timeout exception, it would cause the scan
|
||||
// be aborted and only be restarted at the next scanning period.
|
||||
// If we retry too many times, give up and restart the scan later.
|
||||
std::unique_ptr<cql3::result_set> rs;
|
||||
for (int retries=0; ; retries++) {
|
||||
try {
|
||||
// FIXME: which timeout?
|
||||
rs = co_await p->fetch_page(limit, gc_clock::now(), executor::default_timeout());
|
||||
break;
|
||||
} catch(exceptions::read_timeout_exception&) {
|
||||
tlogger.warn("expiration scanner read timed out, will retry: {}",
|
||||
std::current_exception());
|
||||
}
|
||||
// If we didn't break out of this loop, add a minimal sleep
|
||||
if (retries >= 10) {
|
||||
// Don't get stuck forever asking the same page, maybe there's
|
||||
// a bug or a real problem in several replicas. Give up on
|
||||
// this scan an retry the scan from a random position later,
|
||||
// in the next scan period.
|
||||
throw runtime_exception("scanner thread failed after too many timeouts for the same page");
|
||||
}
|
||||
co_await sleep_abortable(std::chrono::seconds(1), abort_source);
|
||||
}
|
||||
// FIXME: which timeout?
|
||||
// FIXME: if read times out, need to retry it.
|
||||
std::unique_ptr<cql3::result_set> rs = co_await p->fetch_page(limit, gc_clock::now(), executor::default_timeout());
|
||||
auto rows = rs->rows();
|
||||
auto meta = rs->get_metadata().get_names();
|
||||
std::optional<unsigned> expiration_column;
|
||||
|
||||
15
amplify.yml
15
amplify.yml
@@ -1,15 +0,0 @@
|
||||
version: 1
|
||||
applications:
|
||||
- frontend:
|
||||
phases:
|
||||
build:
|
||||
commands:
|
||||
- make setupenv
|
||||
- make dirhtml
|
||||
artifacts:
|
||||
baseDirectory: _build/dirhtml
|
||||
files:
|
||||
- '**/*'
|
||||
cache:
|
||||
paths: []
|
||||
appRoot: docs
|
||||
@@ -1,70 +0,0 @@
|
||||
# Generate C++ sources from Swagger definitions
|
||||
set(swagger_files
|
||||
api-doc/authorization_cache.json
|
||||
api-doc/cache_service.json
|
||||
api-doc/collectd.json
|
||||
api-doc/column_family.json
|
||||
api-doc/commitlog.json
|
||||
api-doc/compaction_manager.json
|
||||
api-doc/config.json
|
||||
api-doc/endpoint_snitch_info.json
|
||||
api-doc/error_injection.json
|
||||
api-doc/failure_detector.json
|
||||
api-doc/gossiper.json
|
||||
api-doc/hinted_handoff.json
|
||||
api-doc/lsa.json
|
||||
api-doc/messaging_service.json
|
||||
api-doc/storage_proxy.json
|
||||
api-doc/storage_service.json
|
||||
api-doc/stream_manager.json
|
||||
api-doc/system.json
|
||||
api-doc/task_manager.json
|
||||
api-doc/task_manager_test.json
|
||||
api-doc/utils.json)
|
||||
|
||||
foreach(f ${swagger_files})
|
||||
get_filename_component(fname "${f}" NAME_WE)
|
||||
get_filename_component(dir "${f}" DIRECTORY)
|
||||
seastar_generate_swagger(
|
||||
TARGET scylla_swagger_gen_${fname}
|
||||
VAR scylla_swagger_gen_${fname}_files
|
||||
IN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${f}"
|
||||
OUT_DIR "${scylla_gen_build_dir}/api/${dir}")
|
||||
list(APPEND swagger_gen_files "${scylla_swagger_gen_${fname}_files}")
|
||||
endforeach()
|
||||
|
||||
add_library(api)
|
||||
target_sources(api
|
||||
PRIVATE
|
||||
api.cc
|
||||
cache_service.cc
|
||||
collectd.cc
|
||||
column_family.cc
|
||||
commitlog.cc
|
||||
compaction_manager.cc
|
||||
config.cc
|
||||
endpoint_snitch.cc
|
||||
error_injection.cc
|
||||
authorization_cache.cc
|
||||
failure_detector.cc
|
||||
gossiper.cc
|
||||
hinted_handoff.cc
|
||||
lsa.cc
|
||||
messaging_service.cc
|
||||
storage_proxy.cc
|
||||
storage_service.cc
|
||||
stream_manager.cc
|
||||
system.cc
|
||||
task_manager.cc
|
||||
task_manager_test.cc
|
||||
${swagger_gen_files})
|
||||
target_include_directories(api
|
||||
PUBLIC
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${scylla_gen_build_dir})
|
||||
target_link_libraries(api
|
||||
idl
|
||||
wasmtime_bindings
|
||||
|
||||
Seastar::seastar
|
||||
xxHash::xxhash)
|
||||
@@ -1228,7 +1228,7 @@
|
||||
"operations":[
|
||||
{
|
||||
"method":"POST",
|
||||
"summary":"Removes a node from the cluster. Replicated data that logically belonged to this node is redistributed among the remaining nodes.",
|
||||
"summary":"Removes token (and all data associated with enpoint that had it) from the ring",
|
||||
"type":"void",
|
||||
"nickname":"remove_node",
|
||||
"produces":[
|
||||
@@ -1245,7 +1245,7 @@
|
||||
},
|
||||
{
|
||||
"name":"ignore_nodes",
|
||||
"description":"Comma-separated list of dead nodes to ignore in removenode operation. Use the same method for all nodes to ignore: either Host IDs or ip addresses.",
|
||||
"description":"List of dead nodes to ingore in removenode operation",
|
||||
"required":false,
|
||||
"allowMultiple":false,
|
||||
"type":"string",
|
||||
|
||||
@@ -49,14 +49,6 @@
|
||||
"type":"string",
|
||||
"paramType":"path"
|
||||
},
|
||||
{
|
||||
"name":"internal",
|
||||
"description":"Boolean flag indicating whether internal tasks should be shown (false by default)",
|
||||
"required":false,
|
||||
"allowMultiple":false,
|
||||
"type":"boolean",
|
||||
"paramType":"query"
|
||||
},
|
||||
{
|
||||
"name":"keyspace",
|
||||
"description":"The keyspace to query about",
|
||||
@@ -148,57 +140,6 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path":"/task_manager/task_status_recursive/{task_id}",
|
||||
"operations":[
|
||||
{
|
||||
"method":"GET",
|
||||
"summary":"Get statuses of the task and all its descendants",
|
||||
"type":"array",
|
||||
"items":{
|
||||
"type":"task_status"
|
||||
},
|
||||
"nickname":"get_task_status_recursively",
|
||||
"produces":[
|
||||
"application/json"
|
||||
],
|
||||
"parameters":[
|
||||
{
|
||||
"name":"task_id",
|
||||
"description":"The uuid of a task to query about",
|
||||
"required":true,
|
||||
"allowMultiple":false,
|
||||
"type":"string",
|
||||
"paramType":"path"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path":"/task_manager/ttl",
|
||||
"operations":[
|
||||
{
|
||||
"method":"POST",
|
||||
"summary":"Set ttl in seconds and get last value",
|
||||
"type":"long",
|
||||
"nickname":"get_and_update_ttl",
|
||||
"produces":[
|
||||
"application/json"
|
||||
],
|
||||
"parameters":[
|
||||
{
|
||||
"name":"ttl",
|
||||
"description":"The number of seconds for which the tasks will be kept in memory after it finishes",
|
||||
"required":true,
|
||||
"allowMultiple":false,
|
||||
"type":"long",
|
||||
"paramType":"query"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"models":{
|
||||
@@ -219,26 +160,6 @@
|
||||
"failed"
|
||||
],
|
||||
"description":"The state of a task"
|
||||
},
|
||||
"type":{
|
||||
"type":"string",
|
||||
"description":"The description of the task"
|
||||
},
|
||||
"keyspace":{
|
||||
"type":"string",
|
||||
"description":"The keyspace the task is working on (if applicable)"
|
||||
},
|
||||
"table":{
|
||||
"type":"string",
|
||||
"description":"The table the task is working on (if applicable)"
|
||||
},
|
||||
"entity":{
|
||||
"type":"string",
|
||||
"description":"Task-specific entity description"
|
||||
},
|
||||
"sequence_number":{
|
||||
"type":"long",
|
||||
"description":"The running sequence number of the task"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -315,13 +236,6 @@
|
||||
"progress_completed":{
|
||||
"type":"double",
|
||||
"description":"The number of units completed so far"
|
||||
},
|
||||
"children_ids":{
|
||||
"type":"array",
|
||||
"items":{
|
||||
"type":"string"
|
||||
},
|
||||
"description":"Task IDs of children of this task"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,14 @@
|
||||
"type":"string",
|
||||
"paramType":"query"
|
||||
},
|
||||
{
|
||||
"name":"type",
|
||||
"description":"The type of the task",
|
||||
"required":false,
|
||||
"allowMultiple":false,
|
||||
"type":"string",
|
||||
"paramType":"query"
|
||||
},
|
||||
{
|
||||
"name":"entity",
|
||||
"description":"Task-specific entity description",
|
||||
@@ -148,6 +156,30 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"path":"/task_manager_test/ttl",
|
||||
"operations":[
|
||||
{
|
||||
"method":"POST",
|
||||
"summary":"Set ttl in seconds and get last value",
|
||||
"type":"long",
|
||||
"nickname":"get_and_update_ttl",
|
||||
"produces":[
|
||||
"application/json"
|
||||
],
|
||||
"parameters":[
|
||||
{
|
||||
"name":"ttl",
|
||||
"description":"The number of seconds for which the tasks will be kept in memory after it finishes",
|
||||
"required":true,
|
||||
"allowMultiple":false,
|
||||
"type":"long",
|
||||
"paramType":"query"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
27
api/api.cc
27
api/api.cc
@@ -35,7 +35,6 @@
|
||||
logging::logger apilog("api");
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
|
||||
static std::unique_ptr<reply> exception_reply(std::exception_ptr eptr) {
|
||||
try {
|
||||
@@ -166,15 +165,9 @@ future<> set_server_gossip(http_context& ctx, sharded<gms::gossiper>& g) {
|
||||
});
|
||||
}
|
||||
|
||||
future<> set_server_load_sstable(http_context& ctx, sharded<db::system_keyspace>& sys_ks) {
|
||||
future<> set_server_load_sstable(http_context& ctx) {
|
||||
return register_api(ctx, "column_family",
|
||||
"The column family API", [&sys_ks] (http_context& ctx, routes& r) {
|
||||
set_column_family(ctx, r, sys_ks);
|
||||
});
|
||||
}
|
||||
|
||||
future<> unset_server_load_sstable(http_context& ctx) {
|
||||
return ctx.http_server.set_routes([&ctx] (routes& r) { unset_column_family(ctx, r); });
|
||||
"The column family API", set_column_family);
|
||||
}
|
||||
|
||||
future<> set_server_messaging_service(http_context& ctx, sharded<netw::messaging_service>& ms) {
|
||||
@@ -194,10 +187,6 @@ future<> set_server_storage_proxy(http_context& ctx, sharded<service::storage_se
|
||||
});
|
||||
}
|
||||
|
||||
future<> unset_server_storage_proxy(http_context& ctx) {
|
||||
return ctx.http_server.set_routes([&ctx] (routes& r) { unset_storage_proxy(ctx, r); });
|
||||
}
|
||||
|
||||
future<> set_server_stream_manager(http_context& ctx, sharded<streaming::stream_manager>& sm) {
|
||||
return register_api(ctx, "stream_manager",
|
||||
"The stream manager API", [&sm] (http_context& ctx, routes& r) {
|
||||
@@ -264,25 +253,25 @@ future<> set_server_done(http_context& ctx) {
|
||||
});
|
||||
}
|
||||
|
||||
future<> set_server_task_manager(http_context& ctx, lw_shared_ptr<db::config> cfg) {
|
||||
future<> set_server_task_manager(http_context& ctx) {
|
||||
auto rb = std::make_shared < api_registry_builder > (ctx.api_doc);
|
||||
|
||||
return ctx.http_server.set_routes([rb, &ctx, &cfg = *cfg](routes& r) {
|
||||
return ctx.http_server.set_routes([rb, &ctx](routes& r) {
|
||||
rb->register_function(r, "task_manager",
|
||||
"The task manager API");
|
||||
set_task_manager(ctx, r, cfg);
|
||||
set_task_manager(ctx, r);
|
||||
});
|
||||
}
|
||||
|
||||
#ifndef SCYLLA_BUILD_MODE_RELEASE
|
||||
|
||||
future<> set_server_task_manager_test(http_context& ctx) {
|
||||
future<> set_server_task_manager_test(http_context& ctx, lw_shared_ptr<db::config> cfg) {
|
||||
auto rb = std::make_shared < api_registry_builder > (ctx.api_doc);
|
||||
|
||||
return ctx.http_server.set_routes([rb, &ctx](routes& r) mutable {
|
||||
return ctx.http_server.set_routes([rb, &ctx, &cfg = *cfg](routes& r) mutable {
|
||||
rb->register_function(r, "task_manager_test",
|
||||
"The task manager test API");
|
||||
set_task_manager_test(ctx, r);
|
||||
set_task_manager_test(ctx, r, cfg);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
14
api/api.hh
14
api/api.hh
@@ -27,7 +27,7 @@ template<class T>
|
||||
std::vector<sstring> container_to_vec(const T& container) {
|
||||
std::vector<sstring> res;
|
||||
for (auto i : container) {
|
||||
res.push_back(fmt::to_string(i));
|
||||
res.push_back(boost::lexical_cast<std::string>(i));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -47,8 +47,8 @@ template<class T, class MAP>
|
||||
std::vector<T>& map_to_key_value(const MAP& map, std::vector<T>& res) {
|
||||
for (auto i : map) {
|
||||
T val;
|
||||
val.key = fmt::to_string(i.first);
|
||||
val.value = fmt::to_string(i.second);
|
||||
val.key = boost::lexical_cast<std::string>(i.first);
|
||||
val.value = boost::lexical_cast<std::string>(i.second);
|
||||
res.push_back(val);
|
||||
}
|
||||
return res;
|
||||
@@ -65,7 +65,7 @@ template <typename MAP>
|
||||
std::vector<sstring> map_keys(const MAP& map) {
|
||||
std::vector<sstring> res;
|
||||
for (const auto& i : map) {
|
||||
res.push_back(fmt::to_string(i.first));
|
||||
res.push_back(boost::lexical_cast<std::string>(i.first));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -189,7 +189,7 @@ struct basic_ratio_holder : public json::jsonable {
|
||||
typedef basic_ratio_holder<double> ratio_holder;
|
||||
typedef basic_ratio_holder<int64_t> integral_ratio_holder;
|
||||
|
||||
class unimplemented_exception : public httpd::base_exception {
|
||||
class unimplemented_exception : public base_exception {
|
||||
public:
|
||||
unimplemented_exception()
|
||||
: base_exception("API call is not supported yet", reply::status_type::internal_server_error) {
|
||||
@@ -238,7 +238,7 @@ public:
|
||||
value = T{boost::lexical_cast<Base>(param)};
|
||||
}
|
||||
} catch (boost::bad_lexical_cast&) {
|
||||
throw httpd::bad_param_exception(format("{} ({}): type error - should be {}", name, param, boost::units::detail::demangle(typeid(Base).name())));
|
||||
throw bad_param_exception(format("{} ({}): type error - should be {}", name, param, boost::units::detail::demangle(typeid(Base).name())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,6 +306,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
httpd::utils_json::estimated_histogram time_to_json_histogram(const utils::time_estimated_histogram& val);
|
||||
utils_json::estimated_histogram time_to_json_histogram(const utils::time_estimated_histogram& val);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
#include "tasks/task_manager.hh"
|
||||
#include "seastarx.hh"
|
||||
|
||||
using request = http::request;
|
||||
using reply = http::reply;
|
||||
|
||||
namespace service {
|
||||
|
||||
class load_meter;
|
||||
@@ -102,12 +99,10 @@ future<> unset_server_authorization_cache(http_context& ctx);
|
||||
future<> set_server_snapshot(http_context& ctx, sharded<db::snapshot_ctl>& snap_ctl);
|
||||
future<> unset_server_snapshot(http_context& ctx);
|
||||
future<> set_server_gossip(http_context& ctx, sharded<gms::gossiper>& g);
|
||||
future<> set_server_load_sstable(http_context& ctx, sharded<db::system_keyspace>& sys_ks);
|
||||
future<> unset_server_load_sstable(http_context& ctx);
|
||||
future<> set_server_load_sstable(http_context& ctx);
|
||||
future<> set_server_messaging_service(http_context& ctx, sharded<netw::messaging_service>& ms);
|
||||
future<> unset_server_messaging_service(http_context& ctx);
|
||||
future<> set_server_storage_proxy(http_context& ctx, sharded<service::storage_service>& ss);
|
||||
future<> unset_server_storage_proxy(http_context& ctx);
|
||||
future<> set_server_stream_manager(http_context& ctx, sharded<streaming::stream_manager>& sm);
|
||||
future<> unset_server_stream_manager(http_context& ctx);
|
||||
future<> set_hinted_handoff(http_context& ctx, sharded<gms::gossiper>& g);
|
||||
@@ -116,7 +111,7 @@ future<> set_server_gossip_settle(http_context& ctx, sharded<gms::gossiper>& g);
|
||||
future<> set_server_cache(http_context& ctx);
|
||||
future<> set_server_compaction_manager(http_context& ctx);
|
||||
future<> set_server_done(http_context& ctx);
|
||||
future<> set_server_task_manager(http_context& ctx, lw_shared_ptr<db::config> cfg);
|
||||
future<> set_server_task_manager_test(http_context& ctx);
|
||||
future<> set_server_task_manager(http_context& ctx);
|
||||
future<> set_server_task_manager_test(http_context& ctx, lw_shared_ptr<db::config> cfg);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,10 +14,9 @@
|
||||
|
||||
namespace api {
|
||||
using namespace json;
|
||||
using namespace seastar::httpd;
|
||||
|
||||
void set_authorization_cache(http_context& ctx, routes& r, sharded<auth::service> &auth_service) {
|
||||
httpd::authorization_cache_json::authorization_cache_reset.set(r, [&auth_service] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
httpd::authorization_cache_json::authorization_cache_reset.set(r, [&auth_service] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
co_await auth_service.invoke_on_all([] (auth::service& auth) -> future<> {
|
||||
auth.reset_authorization_cache();
|
||||
return make_ready_future<>();
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_authorization_cache(http_context& ctx, httpd::routes& r, sharded<auth::service> &auth_service);
|
||||
void unset_authorization_cache(http_context& ctx, httpd::routes& r);
|
||||
void set_authorization_cache(http_context& ctx, routes& r, sharded<auth::service> &auth_service);
|
||||
void unset_authorization_cache(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -12,128 +12,127 @@
|
||||
|
||||
namespace api {
|
||||
using namespace json;
|
||||
using namespace seastar::httpd;
|
||||
namespace cs = httpd::cache_service_json;
|
||||
|
||||
void set_cache_service(http_context& ctx, routes& r) {
|
||||
cs::get_row_cache_save_period_in_seconds.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::get_row_cache_save_period_in_seconds.set(r, [](std::unique_ptr<request> req) {
|
||||
// We never save the cache
|
||||
// Origin uses 0 for never
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::set_row_cache_save_period_in_seconds.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::set_row_cache_save_period_in_seconds.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
auto period = req->get_query_param("period");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::get_key_cache_save_period_in_seconds.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::get_key_cache_save_period_in_seconds.set(r, [](std::unique_ptr<request> req) {
|
||||
// We never save the cache
|
||||
// Origin uses 0 for never
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::set_key_cache_save_period_in_seconds.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::set_key_cache_save_period_in_seconds.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
auto period = req->get_query_param("period");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::get_counter_cache_save_period_in_seconds.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_cache_save_period_in_seconds.set(r, [](std::unique_ptr<request> req) {
|
||||
// We never save the cache
|
||||
// Origin uses 0 for never
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::set_counter_cache_save_period_in_seconds.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::set_counter_cache_save_period_in_seconds.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
auto ccspis = req->get_query_param("ccspis");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::get_row_cache_keys_to_save.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::get_row_cache_keys_to_save.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::set_row_cache_keys_to_save.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::set_row_cache_keys_to_save.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
auto rckts = req->get_query_param("rckts");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::get_key_cache_keys_to_save.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::get_key_cache_keys_to_save.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::set_key_cache_keys_to_save.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::set_key_cache_keys_to_save.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
auto kckts = req->get_query_param("kckts");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::get_counter_cache_keys_to_save.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_cache_keys_to_save.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::set_counter_cache_keys_to_save.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::set_counter_cache_keys_to_save.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
auto cckts = req->get_query_param("cckts");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::invalidate_key_cache.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::invalidate_key_cache.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::invalidate_counter_cache.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::invalidate_counter_cache.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::set_row_cache_capacity_in_mb.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::set_row_cache_capacity_in_mb.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
auto capacity = req->get_query_param("capacity");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::set_key_cache_capacity_in_mb.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::set_key_cache_capacity_in_mb.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
auto period = req->get_query_param("period");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::set_counter_cache_capacity_in_mb.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::set_counter_cache_capacity_in_mb.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
auto capacity = req->get_query_param("capacity");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::save_caches.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cs::save_caches.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cs::get_key_capacity.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_key_capacity.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support keys cache,
|
||||
@@ -141,7 +140,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_key_hits.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_key_hits.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support keys cache,
|
||||
@@ -149,7 +148,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_key_requests.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_key_requests.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support keys cache,
|
||||
@@ -157,7 +156,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_key_hit_rate.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_key_hit_rate.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support keys cache,
|
||||
@@ -165,21 +164,21 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_key_hits_moving_avrage.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_key_hits_moving_avrage.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// See above
|
||||
return make_ready_future<json::json_return_type>(meter_to_json(utils::rate_moving_average()));
|
||||
});
|
||||
|
||||
cs::get_key_requests_moving_avrage.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_key_requests_moving_avrage.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// See above
|
||||
return make_ready_future<json::json_return_type>(meter_to_json(utils::rate_moving_average()));
|
||||
});
|
||||
|
||||
cs::get_key_size.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_key_size.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support keys cache,
|
||||
@@ -187,7 +186,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_key_entries.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_key_entries.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support keys cache,
|
||||
@@ -195,7 +194,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_row_capacity.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cs::get_row_capacity.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return ctx.db.map_reduce0([](replica::database& db) -> uint64_t {
|
||||
return db.row_cache_tracker().region().occupancy().used_space();
|
||||
}, uint64_t(0), std::plus<uint64_t>()).then([](const int64_t& res) {
|
||||
@@ -203,26 +202,26 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
});
|
||||
});
|
||||
|
||||
cs::get_row_hits.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cs::get_row_hits.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, uint64_t(0), [](const replica::column_family& cf) {
|
||||
return cf.get_row_cache().stats().hits.count();
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cs::get_row_requests.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cs::get_row_requests.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, uint64_t(0), [](const replica::column_family& cf) {
|
||||
return cf.get_row_cache().stats().hits.count() + cf.get_row_cache().stats().misses.count();
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cs::get_row_hit_rate.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cs::get_row_hit_rate.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, ratio_holder(), [](const replica::column_family& cf) {
|
||||
return ratio_holder(cf.get_row_cache().stats().hits.count() + cf.get_row_cache().stats().misses.count(),
|
||||
cf.get_row_cache().stats().hits.count());
|
||||
}, std::plus<ratio_holder>());
|
||||
});
|
||||
|
||||
cs::get_row_hits_moving_avrage.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cs::get_row_hits_moving_avrage.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_raw(ctx, utils::rate_moving_average(), [](const replica::column_family& cf) {
|
||||
return cf.get_row_cache().stats().hits.rate();
|
||||
}, std::plus<utils::rate_moving_average>()).then([](const utils::rate_moving_average& m) {
|
||||
@@ -230,7 +229,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
});
|
||||
});
|
||||
|
||||
cs::get_row_requests_moving_avrage.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cs::get_row_requests_moving_avrage.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_raw(ctx, utils::rate_moving_average(), [](const replica::column_family& cf) {
|
||||
return cf.get_row_cache().stats().hits.rate() + cf.get_row_cache().stats().misses.rate();
|
||||
}, std::plus<utils::rate_moving_average>()).then([](const utils::rate_moving_average& m) {
|
||||
@@ -238,7 +237,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
});
|
||||
});
|
||||
|
||||
cs::get_row_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cs::get_row_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
// In origin row size is the weighted size.
|
||||
// We currently do not support weights, so we use num entries instead
|
||||
return ctx.db.map_reduce0([](replica::database& db) -> uint64_t {
|
||||
@@ -248,7 +247,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
});
|
||||
});
|
||||
|
||||
cs::get_row_entries.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cs::get_row_entries.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return ctx.db.map_reduce0([](replica::database& db) -> uint64_t {
|
||||
return db.row_cache_tracker().partitions();
|
||||
}, uint64_t(0), std::plus<uint64_t>()).then([](const int64_t& res) {
|
||||
@@ -256,7 +255,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
});
|
||||
});
|
||||
|
||||
cs::get_counter_capacity.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_capacity.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support counter cache,
|
||||
@@ -264,7 +263,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_counter_hits.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_hits.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support counter cache,
|
||||
@@ -272,7 +271,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_counter_requests.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_requests.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support counter cache,
|
||||
@@ -280,7 +279,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_counter_hit_rate.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_hit_rate.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support counter cache,
|
||||
@@ -288,21 +287,21 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_counter_hits_moving_avrage.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_hits_moving_avrage.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// See above
|
||||
return make_ready_future<json::json_return_type>(meter_to_json(utils::rate_moving_average()));
|
||||
});
|
||||
|
||||
cs::get_counter_requests_moving_avrage.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_requests_moving_avrage.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// See above
|
||||
return make_ready_future<json::json_return_type>(meter_to_json(utils::rate_moving_average()));
|
||||
});
|
||||
|
||||
cs::get_counter_size.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_size.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support counter cache,
|
||||
@@ -310,7 +309,7 @@ void set_cache_service(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cs::get_counter_entries.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cs::get_counter_entries.set(r, [] (std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
// FIXME
|
||||
// we don't support counter cache,
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_cache_service(http_context& ctx, httpd::routes& r);
|
||||
void set_cache_service(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ static const char* str_to_regex(const sstring& v) {
|
||||
}
|
||||
|
||||
void set_collectd(http_context& ctx, routes& r) {
|
||||
cd::get_collectd.set(r, [](std::unique_ptr<request> req) {
|
||||
cd::get_collectd.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
|
||||
auto id = ::make_shared<scollectd::type_instance_id>(req->param["pluginid"],
|
||||
req->get_query_param("instance"), req->get_query_param("type"),
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_collectd(http_context& ctx, httpd::routes& r);
|
||||
void set_collectd(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "db/system_keyspace.hh"
|
||||
#include "db/data_listeners.hh"
|
||||
#include "storage_service.hh"
|
||||
#include "compaction/compaction_manager.hh"
|
||||
#include "unimplemented.hh"
|
||||
|
||||
extern logging::logger apilog;
|
||||
@@ -25,6 +24,7 @@ extern logging::logger apilog;
|
||||
namespace api {
|
||||
using namespace httpd;
|
||||
|
||||
using namespace std;
|
||||
using namespace json;
|
||||
namespace cf = httpd::column_family_json;
|
||||
|
||||
@@ -56,7 +56,7 @@ const table_id& get_uuid(const sstring& name, const replica::database& db) {
|
||||
return get_uuid(ks, cf, db);
|
||||
}
|
||||
|
||||
future<> foreach_column_family(http_context& ctx, const sstring& name, std::function<void(replica::column_family&)> f) {
|
||||
future<> foreach_column_family(http_context& ctx, const sstring& name, function<void(replica::column_family&)> f) {
|
||||
auto uuid = get_uuid(name, ctx.db.local());
|
||||
|
||||
return ctx.db.invoke_on_all([f, uuid](replica::database& db) {
|
||||
@@ -303,16 +303,16 @@ ratio_holder filter_recent_false_positive_as_ratio_holder(const sstables::shared
|
||||
return ratio_holder(f + sst->filter_get_recent_true_positive(), f);
|
||||
}
|
||||
|
||||
void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace>& sys_ks) {
|
||||
void set_column_family(http_context& ctx, routes& r) {
|
||||
cf::get_column_family_name.set(r, [&ctx] (const_req req){
|
||||
std::vector<sstring> res;
|
||||
vector<sstring> res;
|
||||
for (auto i: ctx.db.local().get_column_families_mapping()) {
|
||||
res.push_back(i.first.first + ":" + i.first.second);
|
||||
}
|
||||
return res;
|
||||
});
|
||||
|
||||
cf::get_column_family.set(r, [&ctx] (std::unique_ptr<http::request> req){
|
||||
cf::get_column_family.set(r, [&ctx] (std::unique_ptr<request> req){
|
||||
std::list<cf::column_family_info> res;
|
||||
for (auto i: ctx.db.local().get_column_families_mapping()) {
|
||||
cf::column_family_info info;
|
||||
@@ -325,22 +325,22 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
|
||||
cf::get_column_family_name_keyspace.set(r, [&ctx] (const_req req){
|
||||
std::vector<sstring> res;
|
||||
vector<sstring> res;
|
||||
for (auto i = ctx.db.local().get_keyspaces().cbegin(); i!= ctx.db.local().get_keyspaces().cend(); i++) {
|
||||
res.push_back(i->first);
|
||||
}
|
||||
return res;
|
||||
});
|
||||
|
||||
cf::get_memtable_columns_count.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_memtable_columns_count.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], uint64_t{0}, [](replica::column_family& cf) {
|
||||
return boost::accumulate(cf.active_memtables() | boost::adaptors::transformed(std::mem_fn(&replica::memtable::partition_count)), uint64_t(0));
|
||||
return cf.active_memtable().partition_count();
|
||||
}, std::plus<>());
|
||||
});
|
||||
|
||||
cf::get_all_memtable_columns_count.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_memtable_columns_count.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, uint64_t{0}, [](replica::column_family& cf) {
|
||||
return boost::accumulate(cf.active_memtables() | boost::adaptors::transformed(std::mem_fn(&replica::memtable::partition_count)), uint64_t(0));
|
||||
return cf.active_memtable().partition_count();
|
||||
}, std::plus<>());
|
||||
});
|
||||
|
||||
@@ -352,35 +352,27 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
return 0;
|
||||
});
|
||||
|
||||
cf::get_memtable_off_heap_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_memtable_off_heap_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], int64_t(0), [](replica::column_family& cf) {
|
||||
return boost::accumulate(cf.active_memtables() | boost::adaptors::transformed([] (replica::memtable* active_memtable) {
|
||||
return active_memtable->region().occupancy().total_space();
|
||||
}), uint64_t(0));
|
||||
return cf.active_memtable().region().occupancy().total_space();
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_memtable_off_heap_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_memtable_off_heap_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, int64_t(0), [](replica::column_family& cf) {
|
||||
return boost::accumulate(cf.active_memtables() | boost::adaptors::transformed([] (replica::memtable* active_memtable) {
|
||||
return active_memtable->region().occupancy().total_space();
|
||||
}), uint64_t(0));
|
||||
return cf.active_memtable().region().occupancy().total_space();
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
cf::get_memtable_live_data_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_memtable_live_data_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], int64_t(0), [](replica::column_family& cf) {
|
||||
return boost::accumulate(cf.active_memtables() | boost::adaptors::transformed([] (replica::memtable* active_memtable) {
|
||||
return active_memtable->region().occupancy().used_space();
|
||||
}), uint64_t(0));
|
||||
return cf.active_memtable().region().occupancy().used_space();
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_memtable_live_data_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_memtable_live_data_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, int64_t(0), [](replica::column_family& cf) {
|
||||
return boost::accumulate(cf.active_memtables() | boost::adaptors::transformed([] (replica::memtable* active_memtable) {
|
||||
return active_memtable->region().occupancy().used_space();
|
||||
}), uint64_t(0));
|
||||
return cf.active_memtable().region().occupancy().used_space();
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
@@ -392,14 +384,14 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
return 0;
|
||||
});
|
||||
|
||||
cf::get_cf_all_memtables_off_heap_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_cf_all_memtables_off_heap_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
warn(unimplemented::cause::INDEXES);
|
||||
return map_reduce_cf(ctx, req->param["name"], int64_t(0), [](replica::column_family& cf) {
|
||||
return cf.occupancy().total_space();
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_cf_all_memtables_off_heap_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_cf_all_memtables_off_heap_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
warn(unimplemented::cause::INDEXES);
|
||||
return ctx.db.map_reduce0([](const replica::database& db){
|
||||
return db.dirty_memory_region_group().real_memory_used();
|
||||
@@ -408,32 +400,30 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_cf_all_memtables_live_data_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_cf_all_memtables_live_data_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
warn(unimplemented::cause::INDEXES);
|
||||
return map_reduce_cf(ctx, req->param["name"], int64_t(0), [](replica::column_family& cf) {
|
||||
return cf.occupancy().used_space();
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_cf_all_memtables_live_data_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_cf_all_memtables_live_data_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
warn(unimplemented::cause::INDEXES);
|
||||
return map_reduce_cf(ctx, int64_t(0), [](replica::column_family& cf) {
|
||||
return boost::accumulate(cf.active_memtables() | boost::adaptors::transformed([] (replica::memtable* active_memtable) {
|
||||
return active_memtable->region().occupancy().used_space();
|
||||
}), uint64_t(0));
|
||||
return cf.active_memtable().region().occupancy().used_space();
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
cf::get_memtable_switch_count.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_memtable_switch_count.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats(ctx,req->param["name"] ,&replica::column_family_stats::memtable_switch_count);
|
||||
});
|
||||
|
||||
cf::get_all_memtable_switch_count.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_memtable_switch_count.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats(ctx, &replica::column_family_stats::memtable_switch_count);
|
||||
});
|
||||
|
||||
// FIXME: this refers to partitions, not rows.
|
||||
cf::get_estimated_row_size_histogram.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_estimated_row_size_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], utils::estimated_histogram(0), [](replica::column_family& cf) {
|
||||
utils::estimated_histogram res(0);
|
||||
for (auto sstables = cf.get_sstables(); auto& i : *sstables) {
|
||||
@@ -445,7 +435,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
|
||||
// FIXME: this refers to partitions, not rows.
|
||||
cf::get_estimated_row_count.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_estimated_row_count.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], int64_t(0), [](replica::column_family& cf) {
|
||||
uint64_t res = 0;
|
||||
for (auto sstables = cf.get_sstables(); auto& i : *sstables) {
|
||||
@@ -456,7 +446,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_estimated_column_count_histogram.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_estimated_column_count_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], utils::estimated_histogram(0), [](replica::column_family& cf) {
|
||||
utils::estimated_histogram res(0);
|
||||
for (auto sstables = cf.get_sstables(); auto& i : *sstables) {
|
||||
@@ -467,149 +457,149 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
utils::estimated_histogram_merge, utils_json::estimated_histogram());
|
||||
});
|
||||
|
||||
cf::get_all_compression_ratio.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_compression_ratio.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cf::get_pending_flushes.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_pending_flushes.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats(ctx,req->param["name"] ,&replica::column_family_stats::pending_flushes);
|
||||
});
|
||||
|
||||
cf::get_all_pending_flushes.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_pending_flushes.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats(ctx, &replica::column_family_stats::pending_flushes);
|
||||
});
|
||||
|
||||
cf::get_read.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_read.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats_count(ctx,req->param["name"] ,&replica::column_family_stats::reads);
|
||||
});
|
||||
|
||||
cf::get_all_read.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_read.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats_count(ctx, &replica::column_family_stats::reads);
|
||||
});
|
||||
|
||||
cf::get_write.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_write.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats_count(ctx, req->param["name"] ,&replica::column_family_stats::writes);
|
||||
});
|
||||
|
||||
cf::get_all_write.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_write.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats_count(ctx, &replica::column_family_stats::writes);
|
||||
});
|
||||
|
||||
cf::get_read_latency_histogram_depricated.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_read_latency_histogram_depricated.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_histogram(ctx, req->param["name"], &replica::column_family_stats::reads);
|
||||
});
|
||||
|
||||
cf::get_read_latency_histogram.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_read_latency_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_rate_and_histogram(ctx, req->param["name"], &replica::column_family_stats::reads);
|
||||
});
|
||||
|
||||
cf::get_read_latency.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_read_latency.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats_sum(ctx,req->param["name"] ,&replica::column_family_stats::reads);
|
||||
});
|
||||
|
||||
cf::get_write_latency.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_write_latency.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats_sum(ctx, req->param["name"] ,&replica::column_family_stats::writes);
|
||||
});
|
||||
|
||||
cf::get_all_read_latency_histogram_depricated.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_read_latency_histogram_depricated.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_histogram(ctx, &replica::column_family_stats::writes);
|
||||
});
|
||||
|
||||
cf::get_all_read_latency_histogram.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_read_latency_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_rate_and_histogram(ctx, &replica::column_family_stats::writes);
|
||||
});
|
||||
|
||||
cf::get_write_latency_histogram_depricated.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_write_latency_histogram_depricated.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_histogram(ctx, req->param["name"], &replica::column_family_stats::writes);
|
||||
});
|
||||
|
||||
cf::get_write_latency_histogram.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_write_latency_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_rate_and_histogram(ctx, req->param["name"], &replica::column_family_stats::writes);
|
||||
});
|
||||
|
||||
cf::get_all_write_latency_histogram_depricated.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_write_latency_histogram_depricated.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_histogram(ctx, &replica::column_family_stats::writes);
|
||||
});
|
||||
|
||||
cf::get_all_write_latency_histogram.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_write_latency_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_rate_and_histogram(ctx, &replica::column_family_stats::writes);
|
||||
});
|
||||
|
||||
cf::get_pending_compactions.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_pending_compactions.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], int64_t(0), [](replica::column_family& cf) {
|
||||
return cf.estimate_pending_compactions();
|
||||
return cf.get_compaction_strategy().estimated_pending_compactions(cf.as_table_state());
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_pending_compactions.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_pending_compactions.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, int64_t(0), [](replica::column_family& cf) {
|
||||
return cf.estimate_pending_compactions();
|
||||
return cf.get_compaction_strategy().estimated_pending_compactions(cf.as_table_state());
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
cf::get_live_ss_table_count.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_live_ss_table_count.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats(ctx, req->param["name"], &replica::column_family_stats::live_sstable_count);
|
||||
});
|
||||
|
||||
cf::get_all_live_ss_table_count.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_live_ss_table_count.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_stats(ctx, &replica::column_family_stats::live_sstable_count);
|
||||
});
|
||||
|
||||
cf::get_unleveled_sstables.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_unleveled_sstables.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_unleveled_sstables(ctx, req->param["name"]);
|
||||
});
|
||||
|
||||
cf::get_live_disk_space_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_live_disk_space_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return sum_sstable(ctx, req->param["name"], false);
|
||||
});
|
||||
|
||||
cf::get_all_live_disk_space_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_live_disk_space_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return sum_sstable(ctx, false);
|
||||
});
|
||||
|
||||
cf::get_total_disk_space_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_total_disk_space_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return sum_sstable(ctx, req->param["name"], true);
|
||||
});
|
||||
|
||||
cf::get_all_total_disk_space_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_total_disk_space_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return sum_sstable(ctx, true);
|
||||
});
|
||||
|
||||
// FIXME: this refers to partitions, not rows.
|
||||
cf::get_min_row_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_min_row_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], INT64_MAX, min_partition_size, min_int64);
|
||||
});
|
||||
|
||||
// FIXME: this refers to partitions, not rows.
|
||||
cf::get_all_min_row_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_min_row_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, INT64_MAX, min_partition_size, min_int64);
|
||||
});
|
||||
|
||||
// FIXME: this refers to partitions, not rows.
|
||||
cf::get_max_row_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_max_row_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], int64_t(0), max_partition_size, max_int64);
|
||||
});
|
||||
|
||||
// FIXME: this refers to partitions, not rows.
|
||||
cf::get_all_max_row_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_max_row_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, int64_t(0), max_partition_size, max_int64);
|
||||
});
|
||||
|
||||
// FIXME: this refers to partitions, not rows.
|
||||
cf::get_mean_row_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_mean_row_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
// Cassandra 3.x mean values are truncated as integrals.
|
||||
return map_reduce_cf(ctx, req->param["name"], integral_ratio_holder(), mean_partition_size, std::plus<integral_ratio_holder>());
|
||||
});
|
||||
|
||||
// FIXME: this refers to partitions, not rows.
|
||||
cf::get_all_mean_row_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_mean_row_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
// Cassandra 3.x mean values are truncated as integrals.
|
||||
return map_reduce_cf(ctx, integral_ratio_holder(), mean_partition_size, std::plus<integral_ratio_holder>());
|
||||
});
|
||||
|
||||
cf::get_bloom_filter_false_positives.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_bloom_filter_false_positives.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -618,7 +608,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_bloom_filter_false_positives.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_bloom_filter_false_positives.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -627,7 +617,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_recent_bloom_filter_false_positives.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_recent_bloom_filter_false_positives.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -636,7 +626,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_recent_bloom_filter_false_positives.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_recent_bloom_filter_false_positives.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -645,31 +635,31 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_bloom_filter_false_ratio.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_bloom_filter_false_ratio.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], ratio_holder(), [] (replica::column_family& cf) {
|
||||
return boost::accumulate(*cf.get_sstables() | boost::adaptors::transformed(filter_false_positive_as_ratio_holder), ratio_holder());
|
||||
}, std::plus<>());
|
||||
});
|
||||
|
||||
cf::get_all_bloom_filter_false_ratio.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_bloom_filter_false_ratio.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, ratio_holder(), [] (replica::column_family& cf) {
|
||||
return boost::accumulate(*cf.get_sstables() | boost::adaptors::transformed(filter_false_positive_as_ratio_holder), ratio_holder());
|
||||
}, std::plus<>());
|
||||
});
|
||||
|
||||
cf::get_recent_bloom_filter_false_ratio.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_recent_bloom_filter_false_ratio.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], ratio_holder(), [] (replica::column_family& cf) {
|
||||
return boost::accumulate(*cf.get_sstables() | boost::adaptors::transformed(filter_recent_false_positive_as_ratio_holder), ratio_holder());
|
||||
}, std::plus<>());
|
||||
});
|
||||
|
||||
cf::get_all_recent_bloom_filter_false_ratio.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_recent_bloom_filter_false_ratio.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, ratio_holder(), [] (replica::column_family& cf) {
|
||||
return boost::accumulate(*cf.get_sstables() | boost::adaptors::transformed(filter_recent_false_positive_as_ratio_holder), ratio_holder());
|
||||
}, std::plus<>());
|
||||
});
|
||||
|
||||
cf::get_bloom_filter_disk_space_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_bloom_filter_disk_space_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -678,7 +668,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_bloom_filter_disk_space_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_bloom_filter_disk_space_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -687,7 +677,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_bloom_filter_off_heap_memory_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_bloom_filter_off_heap_memory_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -696,7 +686,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_bloom_filter_off_heap_memory_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_bloom_filter_off_heap_memory_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -705,7 +695,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_index_summary_off_heap_memory_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_index_summary_off_heap_memory_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -714,7 +704,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_all_index_summary_off_heap_memory_used.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_index_summary_off_heap_memory_used.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, uint64_t(0), [] (replica::column_family& cf) {
|
||||
auto sstables = cf.get_sstables();
|
||||
return std::accumulate(sstables->begin(), sstables->end(), uint64_t(0), [](uint64_t s, auto& sst) {
|
||||
@@ -723,7 +713,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
}, std::plus<uint64_t>());
|
||||
});
|
||||
|
||||
cf::get_compression_metadata_off_heap_memory_used.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_compression_metadata_off_heap_memory_used.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
// FIXME
|
||||
// We are missing the off heap memory calculation
|
||||
@@ -733,33 +723,33 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cf::get_all_compression_metadata_off_heap_memory_used.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_compression_metadata_off_heap_memory_used.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cf::get_speculative_retries.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_speculative_retries.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
//auto id = get_uuid(req->param["name"], ctx.db.local());
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cf::get_all_speculative_retries.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_speculative_retries.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cf::get_key_cache_hit_rate.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_key_cache_hit_rate.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
//auto id = get_uuid(req->param["name"], ctx.db.local());
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cf::get_true_snapshots_size.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_true_snapshots_size.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
auto uuid = get_uuid(req->param["name"], ctx.db.local());
|
||||
return ctx.db.local().find_column_family(uuid).get_snapshot_details().then([](
|
||||
const std::unordered_map<sstring, replica::column_family::snapshot_details>& sd) {
|
||||
@@ -771,26 +761,26 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_all_true_snapshots_size.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_true_snapshots_size.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cf::get_row_cache_hit_out_of_range.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_row_cache_hit_out_of_range.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
//auto id = get_uuid(req->param["name"], ctx.db.local());
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cf::get_all_row_cache_hit_out_of_range.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_row_cache_hit_out_of_range.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cf::get_row_cache_hit.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_row_cache_hit.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_raw(ctx, req->param["name"], utils::rate_moving_average(), [](const replica::column_family& cf) {
|
||||
return cf.get_row_cache().stats().hits.rate();
|
||||
}, std::plus<utils::rate_moving_average>()).then([](const utils::rate_moving_average& m) {
|
||||
@@ -798,7 +788,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_all_row_cache_hit.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_row_cache_hit.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_raw(ctx, utils::rate_moving_average(), [](const replica::column_family& cf) {
|
||||
return cf.get_row_cache().stats().hits.rate();
|
||||
}, std::plus<utils::rate_moving_average>()).then([](const utils::rate_moving_average& m) {
|
||||
@@ -806,7 +796,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_row_cache_miss.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_row_cache_miss.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_raw(ctx, req->param["name"], utils::rate_moving_average(), [](const replica::column_family& cf) {
|
||||
return cf.get_row_cache().stats().misses.rate();
|
||||
}, std::plus<utils::rate_moving_average>()).then([](const utils::rate_moving_average& m) {
|
||||
@@ -814,7 +804,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_all_row_cache_miss.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_all_row_cache_miss.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_raw(ctx, utils::rate_moving_average(), [](const replica::column_family& cf) {
|
||||
return cf.get_row_cache().stats().misses.rate();
|
||||
}, std::plus<utils::rate_moving_average>()).then([](const utils::rate_moving_average& m) {
|
||||
@@ -823,40 +813,40 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
|
||||
});
|
||||
|
||||
cf::get_cas_prepare.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_cas_prepare.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_time_histogram(ctx, req->param["name"], [](const replica::column_family& cf) {
|
||||
return cf.get_stats().cas_prepare.histogram();
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_cas_propose.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_cas_propose.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_time_histogram(ctx, req->param["name"], [](const replica::column_family& cf) {
|
||||
return cf.get_stats().cas_accept.histogram();
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_cas_commit.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_cas_commit.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_time_histogram(ctx, req->param["name"], [](const replica::column_family& cf) {
|
||||
return cf.get_stats().cas_learn.histogram();
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_sstables_per_read_histogram.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_sstables_per_read_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, req->param["name"], utils::estimated_histogram(0), [](replica::column_family& cf) {
|
||||
return cf.get_stats().estimated_sstable_per_read;
|
||||
},
|
||||
utils::estimated_histogram_merge, utils_json::estimated_histogram());
|
||||
});
|
||||
|
||||
cf::get_tombstone_scanned_histogram.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_tombstone_scanned_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_histogram(ctx, req->param["name"], &replica::column_family_stats::tombstone_scanned);
|
||||
});
|
||||
|
||||
cf::get_live_scanned_histogram.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::get_live_scanned_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cf_histogram(ctx, req->param["name"], &replica::column_family_stats::live_scanned);
|
||||
});
|
||||
|
||||
cf::get_col_update_time_delta_histogram.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cf::get_col_update_time_delta_histogram.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
//auto id = get_uuid(req->param["name"], ctx.db.local());
|
||||
@@ -870,7 +860,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
return !cf.is_auto_compaction_disabled_by_user();
|
||||
});
|
||||
|
||||
cf::enable_auto_compaction.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
cf::enable_auto_compaction.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return ctx.db.invoke_on(0, [&ctx, req = std::move(req)] (replica::database& db) {
|
||||
auto g = replica::database::autocompaction_toggle_guard(db);
|
||||
return foreach_column_family(ctx, req->param["name"], [](replica::column_family &cf) {
|
||||
@@ -881,7 +871,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::disable_auto_compaction.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
cf::disable_auto_compaction.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return ctx.db.invoke_on(0, [&ctx, req = std::move(req)] (replica::database& db) {
|
||||
auto g = replica::database::autocompaction_toggle_guard(db);
|
||||
return foreach_column_family(ctx, req->param["name"], [](replica::column_family &cf) {
|
||||
@@ -892,11 +882,11 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_built_indexes.set(r, [&ctx, &sys_ks](std::unique_ptr<http::request> req) {
|
||||
cf::get_built_indexes.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
auto ks_cf = parse_fully_qualified_cf_name(req->param["name"]);
|
||||
auto&& ks = std::get<0>(ks_cf);
|
||||
auto&& cf_name = std::get<1>(ks_cf);
|
||||
return sys_ks.local().load_view_build_progress().then([ks, cf_name, &ctx](const std::vector<db::system_keyspace_view_build_progress>& vb) mutable {
|
||||
return db::system_keyspace::load_view_build_progress().then([ks, cf_name, &ctx](const std::vector<db::system_keyspace_view_build_progress>& vb) mutable {
|
||||
std::set<sstring> vp;
|
||||
for (auto b : vb) {
|
||||
if (b.view.first == ks) {
|
||||
@@ -930,7 +920,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
return std::vector<sstring>();
|
||||
});
|
||||
|
||||
cf::get_compression_ratio.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
cf::get_compression_ratio.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
auto uuid = get_uuid(req->param["name"], ctx.db.local());
|
||||
|
||||
return ctx.db.map_reduce(sum_ratio<double>(), [uuid](replica::database& db) {
|
||||
@@ -941,19 +931,19 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_read_latency_estimated_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
cf::get_read_latency_estimated_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_time_histogram(ctx, req->param["name"], [](const replica::column_family& cf) {
|
||||
return cf.get_stats().reads.histogram();
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_write_latency_estimated_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
cf::get_write_latency_estimated_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_time_histogram(ctx, req->param["name"], [](const replica::column_family& cf) {
|
||||
return cf.get_stats().writes.histogram();
|
||||
});
|
||||
});
|
||||
|
||||
cf::set_compaction_strategy_class.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
cf::set_compaction_strategy_class.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
sstring strategy = req->get_query_param("class_name");
|
||||
return foreach_column_family(ctx, req->param["name"], [strategy](replica::column_family& cf) {
|
||||
cf.set_compaction_strategy(sstables::compaction_strategy::type(strategy));
|
||||
@@ -966,19 +956,19 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
return ctx.db.local().find_column_family(get_uuid(req.param["name"], ctx.db.local())).get_compaction_strategy().name();
|
||||
});
|
||||
|
||||
cf::set_compression_parameters.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cf::set_compression_parameters.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cf::set_crc_check_chance.set(r, [](std::unique_ptr<http::request> req) {
|
||||
cf::set_crc_check_chance.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cf::get_sstable_count_per_level.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
cf::get_sstable_count_per_level.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return map_reduce_cf_raw(ctx, req->param["name"], std::vector<uint64_t>(), [](const replica::column_family& cf) {
|
||||
return cf.sstable_count_per_level();
|
||||
}, concat_sstable_count_per_level).then([](const std::vector<uint64_t>& res) {
|
||||
@@ -986,7 +976,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::get_sstables_for_key.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
cf::get_sstables_for_key.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
auto key = req->get_query_param("key");
|
||||
auto uuid = get_uuid(req->param["name"], ctx.db.local());
|
||||
|
||||
@@ -1002,7 +992,7 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
|
||||
|
||||
cf::toppartitions.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cf::toppartitions.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
auto name = req->param["name"];
|
||||
auto [ks, cf] = parse_fully_qualified_cf_name(name);
|
||||
|
||||
@@ -1018,127 +1008,15 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
|
||||
});
|
||||
});
|
||||
|
||||
cf::force_major_compaction.set(r, [&ctx](std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
cf::force_major_compaction.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
if (req->get_query_param("split_output") != "") {
|
||||
fail(unimplemented::cause::API);
|
||||
}
|
||||
|
||||
auto [ks, cf] = parse_fully_qualified_cf_name(req->param["name"]);
|
||||
auto keyspace = validate_keyspace(ctx, ks);
|
||||
std::vector<table_id> table_infos = {ctx.db.local().find_uuid(ks, cf)};
|
||||
|
||||
auto& compaction_module = ctx.db.local().get_compaction_manager().get_task_manager_module();
|
||||
auto task = co_await compaction_module.make_and_start_task<major_keyspace_compaction_task_impl>({}, std::move(keyspace), ctx.db, std::move(table_infos));
|
||||
co_await task->done();
|
||||
co_return json_void();
|
||||
return foreach_column_family(ctx, req->param["name"], [](replica::column_family &cf) {
|
||||
return cf.compact_all_sstables();
|
||||
}).then([] {
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void unset_column_family(http_context& ctx, routes& r) {
|
||||
cf::get_column_family_name.unset(r);
|
||||
cf::get_column_family.unset(r);
|
||||
cf::get_column_family_name_keyspace.unset(r);
|
||||
cf::get_memtable_columns_count.unset(r);
|
||||
cf::get_all_memtable_columns_count.unset(r);
|
||||
cf::get_memtable_on_heap_size.unset(r);
|
||||
cf::get_all_memtable_on_heap_size.unset(r);
|
||||
cf::get_memtable_off_heap_size.unset(r);
|
||||
cf::get_all_memtable_off_heap_size.unset(r);
|
||||
cf::get_memtable_live_data_size.unset(r);
|
||||
cf::get_all_memtable_live_data_size.unset(r);
|
||||
cf::get_cf_all_memtables_on_heap_size.unset(r);
|
||||
cf::get_all_cf_all_memtables_on_heap_size.unset(r);
|
||||
cf::get_cf_all_memtables_off_heap_size.unset(r);
|
||||
cf::get_all_cf_all_memtables_off_heap_size.unset(r);
|
||||
cf::get_cf_all_memtables_live_data_size.unset(r);
|
||||
cf::get_all_cf_all_memtables_live_data_size.unset(r);
|
||||
cf::get_memtable_switch_count.unset(r);
|
||||
cf::get_all_memtable_switch_count.unset(r);
|
||||
cf::get_estimated_row_size_histogram.unset(r);
|
||||
cf::get_estimated_row_count.unset(r);
|
||||
cf::get_estimated_column_count_histogram.unset(r);
|
||||
cf::get_all_compression_ratio.unset(r);
|
||||
cf::get_pending_flushes.unset(r);
|
||||
cf::get_all_pending_flushes.unset(r);
|
||||
cf::get_read.unset(r);
|
||||
cf::get_all_read.unset(r);
|
||||
cf::get_write.unset(r);
|
||||
cf::get_all_write.unset(r);
|
||||
cf::get_read_latency_histogram_depricated.unset(r);
|
||||
cf::get_read_latency_histogram.unset(r);
|
||||
cf::get_read_latency.unset(r);
|
||||
cf::get_write_latency.unset(r);
|
||||
cf::get_all_read_latency_histogram_depricated.unset(r);
|
||||
cf::get_all_read_latency_histogram.unset(r);
|
||||
cf::get_write_latency_histogram_depricated.unset(r);
|
||||
cf::get_write_latency_histogram.unset(r);
|
||||
cf::get_all_write_latency_histogram_depricated.unset(r);
|
||||
cf::get_all_write_latency_histogram.unset(r);
|
||||
cf::get_pending_compactions.unset(r);
|
||||
cf::get_all_pending_compactions.unset(r);
|
||||
cf::get_live_ss_table_count.unset(r);
|
||||
cf::get_all_live_ss_table_count.unset(r);
|
||||
cf::get_unleveled_sstables.unset(r);
|
||||
cf::get_live_disk_space_used.unset(r);
|
||||
cf::get_all_live_disk_space_used.unset(r);
|
||||
cf::get_total_disk_space_used.unset(r);
|
||||
cf::get_all_total_disk_space_used.unset(r);
|
||||
cf::get_min_row_size.unset(r);
|
||||
cf::get_all_min_row_size.unset(r);
|
||||
cf::get_max_row_size.unset(r);
|
||||
cf::get_all_max_row_size.unset(r);
|
||||
cf::get_mean_row_size.unset(r);
|
||||
cf::get_all_mean_row_size.unset(r);
|
||||
cf::get_bloom_filter_false_positives.unset(r);
|
||||
cf::get_all_bloom_filter_false_positives.unset(r);
|
||||
cf::get_recent_bloom_filter_false_positives.unset(r);
|
||||
cf::get_all_recent_bloom_filter_false_positives.unset(r);
|
||||
cf::get_bloom_filter_false_ratio.unset(r);
|
||||
cf::get_all_bloom_filter_false_ratio.unset(r);
|
||||
cf::get_recent_bloom_filter_false_ratio.unset(r);
|
||||
cf::get_all_recent_bloom_filter_false_ratio.unset(r);
|
||||
cf::get_bloom_filter_disk_space_used.unset(r);
|
||||
cf::get_all_bloom_filter_disk_space_used.unset(r);
|
||||
cf::get_bloom_filter_off_heap_memory_used.unset(r);
|
||||
cf::get_all_bloom_filter_off_heap_memory_used.unset(r);
|
||||
cf::get_index_summary_off_heap_memory_used.unset(r);
|
||||
cf::get_all_index_summary_off_heap_memory_used.unset(r);
|
||||
cf::get_compression_metadata_off_heap_memory_used.unset(r);
|
||||
cf::get_all_compression_metadata_off_heap_memory_used.unset(r);
|
||||
cf::get_speculative_retries.unset(r);
|
||||
cf::get_all_speculative_retries.unset(r);
|
||||
cf::get_key_cache_hit_rate.unset(r);
|
||||
cf::get_true_snapshots_size.unset(r);
|
||||
cf::get_all_true_snapshots_size.unset(r);
|
||||
cf::get_row_cache_hit_out_of_range.unset(r);
|
||||
cf::get_all_row_cache_hit_out_of_range.unset(r);
|
||||
cf::get_row_cache_hit.unset(r);
|
||||
cf::get_all_row_cache_hit.unset(r);
|
||||
cf::get_row_cache_miss.unset(r);
|
||||
cf::get_all_row_cache_miss.unset(r);
|
||||
cf::get_cas_prepare.unset(r);
|
||||
cf::get_cas_propose.unset(r);
|
||||
cf::get_cas_commit.unset(r);
|
||||
cf::get_sstables_per_read_histogram.unset(r);
|
||||
cf::get_tombstone_scanned_histogram.unset(r);
|
||||
cf::get_live_scanned_histogram.unset(r);
|
||||
cf::get_col_update_time_delta_histogram.unset(r);
|
||||
cf::get_auto_compaction.unset(r);
|
||||
cf::enable_auto_compaction.unset(r);
|
||||
cf::disable_auto_compaction.unset(r);
|
||||
cf::get_built_indexes.unset(r);
|
||||
cf::get_compression_metadata_off_heap_memory_used.unset(r);
|
||||
cf::get_compression_parameters.unset(r);
|
||||
cf::get_compression_ratio.unset(r);
|
||||
cf::get_read_latency_estimated_histogram.unset(r);
|
||||
cf::get_write_latency_estimated_histogram.unset(r);
|
||||
cf::set_compaction_strategy_class.unset(r);
|
||||
cf::get_compaction_strategy_class.unset(r);
|
||||
cf::set_compression_parameters.unset(r);
|
||||
cf::set_crc_check_chance.unset(r);
|
||||
cf::get_sstable_count_per_level.unset(r);
|
||||
cf::get_sstables_for_key.unset(r);
|
||||
cf::toppartitions.unset(r);
|
||||
cf::force_major_compaction.unset(r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,9 @@
|
||||
#include <seastar/core/future-util.hh>
|
||||
#include <any>
|
||||
|
||||
namespace db {
|
||||
class system_keyspace;
|
||||
}
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_column_family(http_context& ctx, httpd::routes& r, sharded<db::system_keyspace>& sys_ks);
|
||||
void unset_column_family(http_context& ctx, httpd::routes& r);
|
||||
void set_column_family(http_context& ctx, routes& r);
|
||||
|
||||
const table_id& get_uuid(const sstring& name, const replica::database& db);
|
||||
future<> foreach_column_family(http_context& ctx, const sstring& name, std::function<void(replica::column_family&)> f);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <vector>
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
|
||||
template<typename T>
|
||||
static auto acquire_cl_metric(http_context& ctx, std::function<T (db::commitlog*)> func) {
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_commitlog(http_context& ctx, httpd::routes& r);
|
||||
void set_commitlog(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace api {
|
||||
|
||||
namespace cm = httpd::compaction_manager_json;
|
||||
using namespace json;
|
||||
using namespace seastar::httpd;
|
||||
|
||||
static future<json::json_return_type> get_cm_stats(http_context& ctx,
|
||||
int64_t compaction_manager::stats::*f) {
|
||||
@@ -42,8 +41,9 @@ static std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_ha
|
||||
return std::move(a);
|
||||
}
|
||||
|
||||
|
||||
void set_compaction_manager(http_context& ctx, routes& r) {
|
||||
cm::get_compactions.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cm::get_compactions.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return ctx.db.map_reduce0([](replica::database& db) {
|
||||
std::vector<cm::summary> summaries;
|
||||
const compaction_manager& cm = db.get_compaction_manager();
|
||||
@@ -65,12 +65,12 @@ void set_compaction_manager(http_context& ctx, routes& r) {
|
||||
});
|
||||
});
|
||||
|
||||
cm::get_pending_tasks_by_table.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
return ctx.db.map_reduce0([](replica::database& db) {
|
||||
return do_with(std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>(), [&db](std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>& tasks) {
|
||||
return do_for_each(db.get_column_families(), [&tasks](const std::pair<table_id, seastar::lw_shared_ptr<replica::table>>& i) -> future<> {
|
||||
cm::get_pending_tasks_by_table.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return ctx.db.map_reduce0([&ctx](replica::database& db) {
|
||||
return do_with(std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>(), [&ctx, &db](std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>& tasks) {
|
||||
return do_for_each(db.get_column_families(), [&tasks](const std::pair<table_id, seastar::lw_shared_ptr<replica::table>>& i) {
|
||||
replica::table& cf = *i.second.get();
|
||||
tasks[std::make_pair(cf.schema()->ks_name(), cf.schema()->cf_name())] = cf.estimate_pending_compactions();
|
||||
tasks[std::make_pair(cf.schema()->ks_name(), cf.schema()->cf_name())] = cf.get_compaction_strategy().estimated_pending_compactions(cf.as_table_state());
|
||||
return make_ready_future<>();
|
||||
}).then([&tasks] {
|
||||
return std::move(tasks);
|
||||
@@ -91,14 +91,14 @@ void set_compaction_manager(http_context& ctx, routes& r) {
|
||||
});
|
||||
});
|
||||
|
||||
cm::force_user_defined_compaction.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cm::force_user_defined_compaction.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
// FIXME
|
||||
warn(unimplemented::cause::API);
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
cm::stop_compaction.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cm::stop_compaction.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
auto type = req->get_query_param("type");
|
||||
return ctx.db.invoke_on_all([type] (replica::database& db) {
|
||||
auto& cm = db.get_compaction_manager();
|
||||
@@ -108,7 +108,7 @@ void set_compaction_manager(http_context& ctx, routes& r) {
|
||||
});
|
||||
});
|
||||
|
||||
cm::stop_keyspace_compaction.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
cm::stop_keyspace_compaction.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
auto ks_name = validate_keyspace(ctx, req->param);
|
||||
auto table_names = parse_tables(ks_name, ctx, req->query_parameters, "tables");
|
||||
if (table_names.empty()) {
|
||||
@@ -119,43 +119,41 @@ void set_compaction_manager(http_context& ctx, routes& r) {
|
||||
auto& cm = db.get_compaction_manager();
|
||||
return parallel_for_each(table_names, [&db, &cm, &ks_name, type] (sstring& table_name) {
|
||||
auto& t = db.find_column_family(ks_name, table_name);
|
||||
return t.parallel_foreach_table_state([&] (compaction::table_state& ts) {
|
||||
return cm.stop_compaction(type, &ts);
|
||||
});
|
||||
return cm.stop_compaction(type, &t.as_table_state());
|
||||
});
|
||||
});
|
||||
co_return json_void();
|
||||
});
|
||||
|
||||
cm::get_pending_tasks.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cm::get_pending_tasks.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return map_reduce_cf(ctx, int64_t(0), [](replica::column_family& cf) {
|
||||
return cf.estimate_pending_compactions();
|
||||
return cf.get_compaction_strategy().estimated_pending_compactions(cf.as_table_state());
|
||||
}, std::plus<int64_t>());
|
||||
});
|
||||
|
||||
cm::get_completed_tasks.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
cm::get_completed_tasks.set(r, [&ctx] (std::unique_ptr<request> req) {
|
||||
return get_cm_stats(ctx, &compaction_manager::stats::completed_tasks);
|
||||
});
|
||||
|
||||
cm::get_total_compactions_completed.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cm::get_total_compactions_completed.set(r, [] (std::unique_ptr<request> req) {
|
||||
// FIXME
|
||||
// We are currently dont have an API for compaction
|
||||
// so returning a 0 as the number of total compaction is ok
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cm::get_bytes_compacted.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cm::get_bytes_compacted.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
// FIXME
|
||||
warn(unimplemented::cause::API);
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
cm::get_compaction_history.set(r, [&ctx] (std::unique_ptr<http::request> req) {
|
||||
std::function<future<>(output_stream<char>&&)> f = [&ctx](output_stream<char>&& s) {
|
||||
return do_with(output_stream<char>(std::move(s)), true, [&ctx] (output_stream<char>& s, bool& first){
|
||||
return s.write("[").then([&ctx, &s, &first] {
|
||||
return ctx.db.local().get_compaction_manager().get_compaction_history([&s, &first](const db::compaction_history_entry& entry) mutable {
|
||||
cm::get_compaction_history.set(r, [] (std::unique_ptr<request> req) {
|
||||
std::function<future<>(output_stream<char>&&)> f = [](output_stream<char>&& s) {
|
||||
return do_with(output_stream<char>(std::move(s)), true, [] (output_stream<char>& s, bool& first){
|
||||
return s.write("[").then([&s, &first] {
|
||||
return db::system_keyspace::get_compaction_history([&s, &first](const db::system_keyspace::compaction_history_entry& entry) mutable {
|
||||
cm::history h;
|
||||
h.id = entry.id.to_sstring();
|
||||
h.ks = std::move(entry.ks);
|
||||
@@ -185,7 +183,7 @@ void set_compaction_manager(http_context& ctx, routes& r) {
|
||||
return make_ready_future<json::json_return_type>(std::move(f));
|
||||
});
|
||||
|
||||
cm::get_compaction_info.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
cm::get_compaction_info.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
// FIXME
|
||||
warn(unimplemented::cause::API);
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_compaction_manager(http_context& ctx, httpd::routes& r);
|
||||
void set_compaction_manager(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
|
||||
template<class T>
|
||||
json::json_return_type get_json_return_type(const T& val) {
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_config(std::shared_ptr<httpd::api_registry_builder20> rb, http_context& ctx, httpd::routes& r, const db::config& cfg);
|
||||
void set_config(std::shared_ptr<api_registry_builder20> rb, http_context& ctx, routes& r, const db::config& cfg);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "utils/fb_utilities.hh"
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
|
||||
void set_endpoint_snitch(http_context& ctx, routes& r, sharded<locator::snitch_ptr>& snitch) {
|
||||
static auto host_or_broadcast = [](const_req req) {
|
||||
@@ -26,10 +25,10 @@ void set_endpoint_snitch(http_context& ctx, routes& r, sharded<locator::snitch_p
|
||||
httpd::endpoint_snitch_info_json::get_datacenter.set(r, [&ctx](const_req req) {
|
||||
auto& topology = ctx.shared_token_metadata.local().get()->get_topology();
|
||||
auto ep = host_or_broadcast(req);
|
||||
if (!topology.has_endpoint(ep)) {
|
||||
if (!topology.has_endpoint(ep, locator::topology::pending::yes)) {
|
||||
// Cannot return error here, nodetool status can race, request
|
||||
// info about just-left node and not handle it nicely
|
||||
return locator::endpoint_dc_rack::default_location.dc;
|
||||
return sstring(locator::production_snitch_base::default_dc);
|
||||
}
|
||||
return topology.get_datacenter(ep);
|
||||
});
|
||||
@@ -37,10 +36,10 @@ void set_endpoint_snitch(http_context& ctx, routes& r, sharded<locator::snitch_p
|
||||
httpd::endpoint_snitch_info_json::get_rack.set(r, [&ctx](const_req req) {
|
||||
auto& topology = ctx.shared_token_metadata.local().get()->get_topology();
|
||||
auto ep = host_or_broadcast(req);
|
||||
if (!topology.has_endpoint(ep)) {
|
||||
if (!topology.has_endpoint(ep, locator::topology::pending::yes)) {
|
||||
// Cannot return error here, nodetool status can race, request
|
||||
// info about just-left node and not handle it nicely
|
||||
return locator::endpoint_dc_rack::default_location.rack;
|
||||
return sstring(locator::production_snitch_base::default_rack);
|
||||
}
|
||||
return topology.get_rack(ep);
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ class snitch_ptr;
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_endpoint_snitch(http_context& ctx, httpd::routes& r, sharded<locator::snitch_ptr>&);
|
||||
void unset_endpoint_snitch(http_context& ctx, httpd::routes& r);
|
||||
void set_endpoint_snitch(http_context& ctx, routes& r, sharded<locator::snitch_ptr>&);
|
||||
void unset_endpoint_snitch(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <seastar/core/future-util.hh>
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
|
||||
namespace hf = httpd::error_injection_json;
|
||||
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_error_injection(http_context& ctx, httpd::routes& r);
|
||||
void set_error_injection(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -8,11 +8,10 @@
|
||||
|
||||
#include "failure_detector.hh"
|
||||
#include "api/api-doc/failure_detector.json.hh"
|
||||
#include "gms/failure_detector.hh"
|
||||
#include "gms/application_state.hh"
|
||||
#include "gms/gossiper.hh"
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
|
||||
namespace fd = httpd::failure_detector_json;
|
||||
|
||||
@@ -21,18 +20,18 @@ void set_failure_detector(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
std::vector<fd::endpoint_state> res;
|
||||
for (auto i : g.get_endpoint_states()) {
|
||||
fd::endpoint_state val;
|
||||
val.addrs = fmt::to_string(i.first);
|
||||
val.addrs = boost::lexical_cast<std::string>(i.first);
|
||||
val.is_alive = i.second.is_alive();
|
||||
val.generation = i.second.get_heart_beat_state().get_generation().value();
|
||||
val.version = i.second.get_heart_beat_state().get_heart_beat_version().value();
|
||||
val.generation = i.second.get_heart_beat_state().get_generation();
|
||||
val.version = i.second.get_heart_beat_state().get_heart_beat_version();
|
||||
val.update_time = i.second.get_update_timestamp().time_since_epoch().count();
|
||||
for (auto a : i.second.get_application_state_map()) {
|
||||
fd::version_value version_val;
|
||||
// We return the enum index and not it's name to stay compatible to origin
|
||||
// method that the state index are static but the name can be changed.
|
||||
version_val.application_state = static_cast<std::underlying_type<gms::application_state>::type>(a.first);
|
||||
version_val.value = a.second.value();
|
||||
version_val.version = a.second.version().value();
|
||||
version_val.value = a.second.value;
|
||||
version_val.version = a.second.version;
|
||||
val.application_state.push(version_val);
|
||||
}
|
||||
res.push_back(val);
|
||||
@@ -63,9 +62,7 @@ void set_failure_detector(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
});
|
||||
|
||||
fd::set_phi_convict_threshold.set(r, [](std::unique_ptr<request> req) {
|
||||
// TBD
|
||||
unimplemented();
|
||||
std::ignore = atof(req->get_query_param("phi").c_str());
|
||||
double phi = atof(req->get_query_param("phi").c_str());
|
||||
return make_ready_future<json::json_return_type>("");
|
||||
});
|
||||
|
||||
@@ -80,9 +77,15 @@ void set_failure_detector(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
});
|
||||
|
||||
fd::get_endpoint_phi_values.set(r, [](std::unique_ptr<request> req) {
|
||||
// We no longer have a phi failure detector,
|
||||
// just returning the empty value is good enough.
|
||||
std::map<gms::inet_address, gms::arrival_window> map;
|
||||
std::vector<fd::endpoint_phi_value> res;
|
||||
auto now = gms::arrival_window::clk::now();
|
||||
for (auto& p : map) {
|
||||
fd::endpoint_phi_value val;
|
||||
val.endpoint = p.first.to_sstring();
|
||||
val.phi = p.second.phi(now);
|
||||
res.emplace_back(std::move(val));
|
||||
}
|
||||
return make_ready_future<json::json_return_type>(res);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@ class gossiper;
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_failure_detector(http_context& ctx, httpd::routes& r, gms::gossiper& g);
|
||||
void set_failure_detector(http_context& ctx, routes& r, gms::gossiper& g);
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "gms/gossiper.hh"
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
using namespace json;
|
||||
|
||||
void set_gossiper(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
@@ -20,11 +19,9 @@ void set_gossiper(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
return container_to_vec(res);
|
||||
});
|
||||
|
||||
|
||||
httpd::gossiper_json::get_live_endpoint.set(r, [&g] (std::unique_ptr<request> req) {
|
||||
return g.get_live_members_synchronized().then([] (auto res) {
|
||||
return make_ready_future<json::json_return_type>(container_to_vec(res));
|
||||
});
|
||||
httpd::gossiper_json::get_live_endpoint.set(r, [&g] (const_req req) {
|
||||
auto res = g.get_live_members();
|
||||
return container_to_vec(res);
|
||||
});
|
||||
|
||||
httpd::gossiper_json::get_endpoint_downtime.set(r, [&g] (const_req req) {
|
||||
@@ -32,21 +29,21 @@ void set_gossiper(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
return g.get_endpoint_downtime(ep);
|
||||
});
|
||||
|
||||
httpd::gossiper_json::get_current_generation_number.set(r, [&g] (std::unique_ptr<http::request> req) {
|
||||
httpd::gossiper_json::get_current_generation_number.set(r, [&g] (std::unique_ptr<request> req) {
|
||||
gms::inet_address ep(req->param["addr"]);
|
||||
return g.get_current_generation_number(ep).then([] (gms::generation_type res) {
|
||||
return make_ready_future<json::json_return_type>(res.value());
|
||||
return g.get_current_generation_number(ep).then([] (int res) {
|
||||
return make_ready_future<json::json_return_type>(res);
|
||||
});
|
||||
});
|
||||
|
||||
httpd::gossiper_json::get_current_heart_beat_version.set(r, [&g] (std::unique_ptr<http::request> req) {
|
||||
httpd::gossiper_json::get_current_heart_beat_version.set(r, [&g] (std::unique_ptr<request> req) {
|
||||
gms::inet_address ep(req->param["addr"]);
|
||||
return g.get_current_heart_beat_version(ep).then([] (gms::version_type res) {
|
||||
return make_ready_future<json::json_return_type>(res.value());
|
||||
return g.get_current_heart_beat_version(ep).then([] (int res) {
|
||||
return make_ready_future<json::json_return_type>(res);
|
||||
});
|
||||
});
|
||||
|
||||
httpd::gossiper_json::assassinate_endpoint.set(r, [&g](std::unique_ptr<http::request> req) {
|
||||
httpd::gossiper_json::assassinate_endpoint.set(r, [&g](std::unique_ptr<request> req) {
|
||||
if (req->get_query_param("unsafe") != "True") {
|
||||
return g.assassinate_endpoint(req->param["addr"]).then([] {
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
@@ -57,7 +54,7 @@ void set_gossiper(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
});
|
||||
});
|
||||
|
||||
httpd::gossiper_json::force_remove_endpoint.set(r, [&g](std::unique_ptr<http::request> req) {
|
||||
httpd::gossiper_json::force_remove_endpoint.set(r, [&g](std::unique_ptr<request> req) {
|
||||
gms::inet_address ep(req->param["addr"]);
|
||||
return g.force_remove_endpoint(ep).then([] {
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
|
||||
@@ -18,6 +18,6 @@ class gossiper;
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_gossiper(http_context& ctx, httpd::routes& r, gms::gossiper& g);
|
||||
void set_gossiper(http_context& ctx, routes& r, gms::gossiper& g);
|
||||
|
||||
}
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
namespace api {
|
||||
|
||||
using namespace json;
|
||||
using namespace seastar::httpd;
|
||||
namespace hh = httpd::hinted_handoff_json;
|
||||
|
||||
void set_hinted_handoff(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
hh::create_hints_sync_point.set(r, [&ctx, &g] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
hh::create_hints_sync_point.set(r, [&ctx, &g] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
auto parse_hosts_list = [&g] (sstring arg) {
|
||||
std::vector<sstring> hosts_str = split(arg, ",");
|
||||
std::vector<gms::inet_address> hosts;
|
||||
@@ -53,7 +52,7 @@ void set_hinted_handoff(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
});
|
||||
});
|
||||
|
||||
hh::get_hints_sync_point.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
hh::get_hints_sync_point.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
db::hints::sync_point sync_point;
|
||||
const sstring encoded = req->get_query_param("id");
|
||||
try {
|
||||
@@ -94,42 +93,42 @@ void set_hinted_handoff(http_context& ctx, routes& r, gms::gossiper& g) {
|
||||
});
|
||||
});
|
||||
|
||||
hh::list_endpoints_pending_hints.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
hh::list_endpoints_pending_hints.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
std::vector<sstring> res;
|
||||
return make_ready_future<json::json_return_type>(res);
|
||||
});
|
||||
|
||||
hh::truncate_all_hints.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
hh::truncate_all_hints.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
sstring host = req->get_query_param("host");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
hh::schedule_hint_delivery.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
hh::schedule_hint_delivery.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
sstring host = req->get_query_param("host");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
hh::pause_hints_delivery.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
hh::pause_hints_delivery.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
sstring pause = req->get_query_param("pause");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
hh::get_create_hint_count.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
hh::get_create_hint_count.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
sstring host = req->get_query_param("host");
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
hh::get_not_stored_hints_count.set(r, [] (std::unique_ptr<http::request> req) {
|
||||
hh::get_not_stored_hints_count.set(r, [] (std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
sstring host = req->get_query_param("host");
|
||||
|
||||
@@ -18,7 +18,7 @@ class gossiper;
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_hinted_handoff(http_context& ctx, httpd::routes& r, gms::gossiper& g);
|
||||
void unset_hinted_handoff(http_context& ctx, httpd::routes& r);
|
||||
void set_hinted_handoff(http_context& ctx, routes& r, gms::gossiper& g);
|
||||
void unset_hinted_handoff(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "replica/database.hh"
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
|
||||
static logging::logger alogger("lsa-api");
|
||||
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_lsa(http_context& ctx, httpd::routes& r);
|
||||
void set_lsa(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace seastar::httpd;
|
||||
using namespace httpd::messaging_service_json;
|
||||
using namespace netw;
|
||||
|
||||
@@ -29,7 +28,7 @@ std::vector<message_counter> map_to_message_counters(
|
||||
std::vector<message_counter> res;
|
||||
for (auto i : map) {
|
||||
res.push_back(message_counter());
|
||||
res.back().key = fmt::to_string(i.first);
|
||||
res.back().key = boost::lexical_cast<sstring>(i.first);
|
||||
res.back().value = i.second;
|
||||
}
|
||||
return res;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace netw { class messaging_service; }
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_messaging_service(http_context& ctx, httpd::routes& r, sharded<netw::messaging_service>& ms);
|
||||
void unset_messaging_service(http_context& ctx, httpd::routes& r);
|
||||
void set_messaging_service(http_context& ctx, routes& r, sharded<netw::messaging_service>& ms);
|
||||
void unset_messaging_service(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace api {
|
||||
|
||||
namespace sp = httpd::storage_proxy_json;
|
||||
using proxy = service::storage_proxy;
|
||||
using namespace seastar::httpd;
|
||||
using namespace json;
|
||||
|
||||
utils::time_estimated_histogram timed_rate_moving_average_summary_merge(utils::time_estimated_histogram a, const utils::timed_rate_moving_average_summary_and_histogram& b) {
|
||||
@@ -185,75 +184,75 @@ sum_timer_stats_storage_proxy(distributed<proxy>& d,
|
||||
}
|
||||
|
||||
void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_service>& ss) {
|
||||
sp::get_total_hints.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::get_total_hints.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
sp::get_hinted_handoff_enabled.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
const auto& filter = ctx.sp.local().get_hints_host_filter();
|
||||
sp::get_hinted_handoff_enabled.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
const auto& filter = service::get_storage_proxy().local().get_hints_host_filter();
|
||||
return make_ready_future<json::json_return_type>(!filter.is_disabled_for_all());
|
||||
});
|
||||
|
||||
sp::set_hinted_handoff_enabled.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::set_hinted_handoff_enabled.set(r, [](std::unique_ptr<request> req) {
|
||||
auto enable = req->get_query_param("enable");
|
||||
auto filter = (enable == "true" || enable == "1")
|
||||
? db::hints::host_filter(db::hints::host_filter::enabled_for_all_tag {})
|
||||
: db::hints::host_filter(db::hints::host_filter::disabled_for_all_tag {});
|
||||
return ctx.sp.invoke_on_all([filter = std::move(filter)] (service::storage_proxy& sp) {
|
||||
return service::get_storage_proxy().invoke_on_all([filter = std::move(filter)] (service::storage_proxy& sp) {
|
||||
return sp.change_hints_host_filter(filter);
|
||||
}).then([] {
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
});
|
||||
|
||||
sp::get_hinted_handoff_enabled_by_dc.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_hinted_handoff_enabled_by_dc.set(r, [](std::unique_ptr<request> req) {
|
||||
std::vector<sstring> res;
|
||||
const auto& filter = ctx.sp.local().get_hints_host_filter();
|
||||
const auto& filter = service::get_storage_proxy().local().get_hints_host_filter();
|
||||
const auto& dcs = filter.get_dcs();
|
||||
res.reserve(res.size());
|
||||
std::copy(dcs.begin(), dcs.end(), std::back_inserter(res));
|
||||
return make_ready_future<json::json_return_type>(res);
|
||||
});
|
||||
|
||||
sp::set_hinted_handoff_enabled_by_dc_list.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::set_hinted_handoff_enabled_by_dc_list.set(r, [](std::unique_ptr<request> req) {
|
||||
auto dcs = req->get_query_param("dcs");
|
||||
auto filter = db::hints::host_filter::parse_from_dc_list(std::move(dcs));
|
||||
return ctx.sp.invoke_on_all([filter = std::move(filter)] (service::storage_proxy& sp) {
|
||||
return service::get_storage_proxy().invoke_on_all([filter = std::move(filter)] (service::storage_proxy& sp) {
|
||||
return sp.change_hints_host_filter(filter);
|
||||
}).then([] {
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
});
|
||||
|
||||
sp::get_max_hint_window.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::get_max_hint_window.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
});
|
||||
|
||||
sp::set_max_hint_window.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::set_max_hint_window.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
auto enable = req->get_query_param("ms");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
sp::get_max_hints_in_progress.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::get_max_hints_in_progress.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(1);
|
||||
});
|
||||
|
||||
sp::set_max_hints_in_progress.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::set_max_hints_in_progress.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
auto enable = req->get_query_param("qs");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
sp::get_hints_in_progress.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::get_hints_in_progress.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(0);
|
||||
@@ -263,7 +262,7 @@ void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_se
|
||||
return ctx.db.local().get_config().request_timeout_in_ms()/1000.0;
|
||||
});
|
||||
|
||||
sp::set_rpc_timeout.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::set_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
auto enable = req->get_query_param("timeout");
|
||||
@@ -274,7 +273,7 @@ void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_se
|
||||
return ctx.db.local().get_config().read_request_timeout_in_ms()/1000.0;
|
||||
});
|
||||
|
||||
sp::set_read_rpc_timeout.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::set_read_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
auto enable = req->get_query_param("timeout");
|
||||
@@ -285,7 +284,7 @@ void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_se
|
||||
return ctx.db.local().get_config().write_request_timeout_in_ms()/1000.0;
|
||||
});
|
||||
|
||||
sp::set_write_rpc_timeout.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::set_write_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
auto enable = req->get_query_param("timeout");
|
||||
@@ -296,7 +295,7 @@ void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_se
|
||||
return ctx.db.local().get_config().counter_write_request_timeout_in_ms()/1000.0;
|
||||
});
|
||||
|
||||
sp::set_counter_write_rpc_timeout.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::set_counter_write_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
auto enable = req->get_query_param("timeout");
|
||||
@@ -307,7 +306,7 @@ void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_se
|
||||
return ctx.db.local().get_config().cas_contention_timeout_in_ms()/1000.0;
|
||||
});
|
||||
|
||||
sp::set_cas_contention_timeout.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::set_cas_contention_timeout.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
auto enable = req->get_query_param("timeout");
|
||||
@@ -318,7 +317,7 @@ void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_se
|
||||
return ctx.db.local().get_config().range_request_timeout_in_ms()/1000.0;
|
||||
});
|
||||
|
||||
sp::set_range_rpc_timeout.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::set_range_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
auto enable = req->get_query_param("timeout");
|
||||
@@ -329,32 +328,32 @@ void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_se
|
||||
return ctx.db.local().get_config().truncate_request_timeout_in_ms()/1000.0;
|
||||
});
|
||||
|
||||
sp::set_truncate_rpc_timeout.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::set_truncate_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
auto enable = req->get_query_param("timeout");
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
sp::reload_trigger_classes.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::reload_trigger_classes.set(r, [](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
unimplemented();
|
||||
return make_ready_future<json::json_return_type>(json_void());
|
||||
});
|
||||
|
||||
sp::get_read_repair_attempted.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_repair_attempted.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::read_repair_attempts);
|
||||
});
|
||||
|
||||
sp::get_read_repair_repaired_blocking.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_repair_repaired_blocking.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::read_repair_repaired_blocking);
|
||||
});
|
||||
|
||||
sp::get_read_repair_repaired_background.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_repair_repaired_background.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::read_repair_repaired_background);
|
||||
});
|
||||
|
||||
sp::get_schema_versions.set(r, [&ss](std::unique_ptr<http::request> req) {
|
||||
sp::get_schema_versions.set(r, [&ss](std::unique_ptr<request> req) {
|
||||
return ss.local().describe_schema_versions().then([] (auto result) {
|
||||
std::vector<sp::mapper_list> res;
|
||||
for (auto e : result) {
|
||||
@@ -367,122 +366,122 @@ void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_se
|
||||
});
|
||||
});
|
||||
|
||||
sp::get_cas_read_timeouts.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_read_timeouts.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &proxy::stats::cas_read_timeouts);
|
||||
});
|
||||
|
||||
sp::get_cas_read_unavailables.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_read_unavailables.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &proxy::stats::cas_read_unavailables);
|
||||
});
|
||||
|
||||
sp::get_cas_write_timeouts.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_write_timeouts.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &proxy::stats::cas_write_timeouts);
|
||||
});
|
||||
|
||||
sp::get_cas_write_unavailables.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_write_unavailables.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &proxy::stats::cas_write_unavailables);
|
||||
});
|
||||
|
||||
sp::get_cas_write_metrics_unfinished_commit.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_write_metrics_unfinished_commit.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_stats(ctx.sp, &proxy::stats::cas_write_unfinished_commit);
|
||||
});
|
||||
|
||||
sp::get_cas_write_metrics_contention.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_write_metrics_contention.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_estimated_histogram(ctx, &proxy::stats::cas_write_contention);
|
||||
});
|
||||
|
||||
sp::get_cas_write_metrics_condition_not_met.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_write_metrics_condition_not_met.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_stats(ctx.sp, &proxy::stats::cas_write_condition_not_met);
|
||||
});
|
||||
|
||||
sp::get_cas_write_metrics_failed_read_round_optimization.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_write_metrics_failed_read_round_optimization.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_stats(ctx.sp, &proxy::stats::cas_failed_read_round_optimization);
|
||||
});
|
||||
|
||||
sp::get_cas_read_metrics_unfinished_commit.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_read_metrics_unfinished_commit.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_stats(ctx.sp, &proxy::stats::cas_read_unfinished_commit);
|
||||
});
|
||||
|
||||
sp::get_cas_read_metrics_contention.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_read_metrics_contention.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_estimated_histogram(ctx, &proxy::stats::cas_read_contention);
|
||||
});
|
||||
|
||||
sp::get_read_metrics_timeouts.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_metrics_timeouts.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &service::storage_proxy_stats::stats::read_timeouts);
|
||||
});
|
||||
|
||||
sp::get_read_metrics_unavailables.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_metrics_unavailables.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &service::storage_proxy_stats::stats::read_unavailables);
|
||||
});
|
||||
|
||||
sp::get_range_metrics_timeouts.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_range_metrics_timeouts.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &service::storage_proxy_stats::stats::range_slice_timeouts);
|
||||
});
|
||||
|
||||
sp::get_range_metrics_unavailables.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_range_metrics_unavailables.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &service::storage_proxy_stats::stats::range_slice_unavailables);
|
||||
});
|
||||
|
||||
sp::get_write_metrics_timeouts.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_write_metrics_timeouts.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &service::storage_proxy_stats::stats::write_timeouts);
|
||||
});
|
||||
|
||||
sp::get_write_metrics_unavailables.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_write_metrics_unavailables.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_long(ctx.sp, &service::storage_proxy_stats::stats::write_unavailables);
|
||||
});
|
||||
|
||||
sp::get_read_metrics_timeouts_rates.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_metrics_timeouts_rates.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_obj(ctx.sp, &service::storage_proxy_stats::stats::read_timeouts);
|
||||
});
|
||||
|
||||
sp::get_read_metrics_unavailables_rates.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_metrics_unavailables_rates.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_obj(ctx.sp, &service::storage_proxy_stats::stats::read_unavailables);
|
||||
});
|
||||
|
||||
sp::get_range_metrics_timeouts_rates.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_range_metrics_timeouts_rates.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_obj(ctx.sp, &service::storage_proxy_stats::stats::range_slice_timeouts);
|
||||
});
|
||||
|
||||
sp::get_range_metrics_unavailables_rates.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_range_metrics_unavailables_rates.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_obj(ctx.sp, &service::storage_proxy_stats::stats::range_slice_unavailables);
|
||||
});
|
||||
|
||||
sp::get_write_metrics_timeouts_rates.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_write_metrics_timeouts_rates.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_obj(ctx.sp, &service::storage_proxy_stats::stats::write_timeouts);
|
||||
});
|
||||
|
||||
sp::get_write_metrics_unavailables_rates.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_write_metrics_unavailables_rates.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timed_rate_as_obj(ctx.sp, &service::storage_proxy_stats::stats::write_unavailables);
|
||||
});
|
||||
|
||||
sp::get_range_metrics_latency_histogram_depricated.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_range_metrics_latency_histogram_depricated.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_histogram_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::range);
|
||||
});
|
||||
|
||||
sp::get_write_metrics_latency_histogram_depricated.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_write_metrics_latency_histogram_depricated.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_histogram_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::write);
|
||||
});
|
||||
|
||||
sp::get_read_metrics_latency_histogram_depricated.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_metrics_latency_histogram_depricated.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_histogram_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::read);
|
||||
});
|
||||
|
||||
sp::get_range_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_range_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timer_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::range);
|
||||
});
|
||||
|
||||
sp::get_write_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_write_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timer_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::write);
|
||||
});
|
||||
sp::get_cas_write_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_write_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timer_stats(ctx.sp, &proxy::stats::cas_write);
|
||||
});
|
||||
|
||||
sp::get_cas_read_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_cas_read_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timer_stats(ctx.sp, &proxy::stats::cas_read);
|
||||
});
|
||||
|
||||
sp::get_view_write_metrics_latency_histogram.set(r, [](std::unique_ptr<http::request> req) {
|
||||
sp::get_view_write_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
//TBD
|
||||
// FIXME
|
||||
// No View metrics are available, so just return empty moving average
|
||||
@@ -490,101 +489,32 @@ void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_se
|
||||
return make_ready_future<json::json_return_type>(get_empty_moving_average());
|
||||
});
|
||||
|
||||
sp::get_read_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timer_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::read);
|
||||
});
|
||||
|
||||
sp::get_read_estimated_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_estimated_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_estimated_histogram(ctx, &service::storage_proxy_stats::stats::read);
|
||||
});
|
||||
|
||||
sp::get_read_latency.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_read_latency.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return total_latency(ctx, &service::storage_proxy_stats::stats::read);
|
||||
});
|
||||
sp::get_write_estimated_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_write_estimated_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_estimated_histogram(ctx, &service::storage_proxy_stats::stats::write);
|
||||
});
|
||||
|
||||
sp::get_write_latency.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_write_latency.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return total_latency(ctx, &service::storage_proxy_stats::stats::write);
|
||||
});
|
||||
|
||||
sp::get_range_estimated_histogram.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_range_estimated_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return sum_timer_stats_storage_proxy(ctx.sp, &service::storage_proxy_stats::stats::range);
|
||||
});
|
||||
|
||||
sp::get_range_latency.set(r, [&ctx](std::unique_ptr<http::request> req) {
|
||||
sp::get_range_latency.set(r, [&ctx](std::unique_ptr<request> req) {
|
||||
return total_latency(ctx, &service::storage_proxy_stats::stats::range);
|
||||
});
|
||||
}
|
||||
|
||||
void unset_storage_proxy(http_context& ctx, routes& r) {
|
||||
sp::get_total_hints.unset(r);
|
||||
sp::get_hinted_handoff_enabled.unset(r);
|
||||
sp::set_hinted_handoff_enabled.unset(r);
|
||||
sp::get_hinted_handoff_enabled_by_dc.unset(r);
|
||||
sp::set_hinted_handoff_enabled_by_dc_list.unset(r);
|
||||
sp::get_max_hint_window.unset(r);
|
||||
sp::set_max_hint_window.unset(r);
|
||||
sp::get_max_hints_in_progress.unset(r);
|
||||
sp::set_max_hints_in_progress.unset(r);
|
||||
sp::get_hints_in_progress.unset(r);
|
||||
sp::get_rpc_timeout.unset(r);
|
||||
sp::set_rpc_timeout.unset(r);
|
||||
sp::get_read_rpc_timeout.unset(r);
|
||||
sp::set_read_rpc_timeout.unset(r);
|
||||
sp::get_write_rpc_timeout.unset(r);
|
||||
sp::set_write_rpc_timeout.unset(r);
|
||||
sp::get_counter_write_rpc_timeout.unset(r);
|
||||
sp::set_counter_write_rpc_timeout.unset(r);
|
||||
sp::get_cas_contention_timeout.unset(r);
|
||||
sp::set_cas_contention_timeout.unset(r);
|
||||
sp::get_range_rpc_timeout.unset(r);
|
||||
sp::set_range_rpc_timeout.unset(r);
|
||||
sp::get_truncate_rpc_timeout.unset(r);
|
||||
sp::set_truncate_rpc_timeout.unset(r);
|
||||
sp::reload_trigger_classes.unset(r);
|
||||
sp::get_read_repair_attempted.unset(r);
|
||||
sp::get_read_repair_repaired_blocking.unset(r);
|
||||
sp::get_read_repair_repaired_background.unset(r);
|
||||
sp::get_schema_versions.unset(r);
|
||||
sp::get_cas_read_timeouts.unset(r);
|
||||
sp::get_cas_read_unavailables.unset(r);
|
||||
sp::get_cas_write_timeouts.unset(r);
|
||||
sp::get_cas_write_unavailables.unset(r);
|
||||
sp::get_cas_write_metrics_unfinished_commit.unset(r);
|
||||
sp::get_cas_write_metrics_contention.unset(r);
|
||||
sp::get_cas_write_metrics_condition_not_met.unset(r);
|
||||
sp::get_cas_write_metrics_failed_read_round_optimization.unset(r);
|
||||
sp::get_cas_read_metrics_unfinished_commit.unset(r);
|
||||
sp::get_cas_read_metrics_contention.unset(r);
|
||||
sp::get_read_metrics_timeouts.unset(r);
|
||||
sp::get_read_metrics_unavailables.unset(r);
|
||||
sp::get_range_metrics_timeouts.unset(r);
|
||||
sp::get_range_metrics_unavailables.unset(r);
|
||||
sp::get_write_metrics_timeouts.unset(r);
|
||||
sp::get_write_metrics_unavailables.unset(r);
|
||||
sp::get_read_metrics_timeouts_rates.unset(r);
|
||||
sp::get_read_metrics_unavailables_rates.unset(r);
|
||||
sp::get_range_metrics_timeouts_rates.unset(r);
|
||||
sp::get_range_metrics_unavailables_rates.unset(r);
|
||||
sp::get_write_metrics_timeouts_rates.unset(r);
|
||||
sp::get_write_metrics_unavailables_rates.unset(r);
|
||||
sp::get_range_metrics_latency_histogram_depricated.unset(r);
|
||||
sp::get_write_metrics_latency_histogram_depricated.unset(r);
|
||||
sp::get_read_metrics_latency_histogram_depricated.unset(r);
|
||||
sp::get_range_metrics_latency_histogram.unset(r);
|
||||
sp::get_write_metrics_latency_histogram.unset(r);
|
||||
sp::get_cas_write_metrics_latency_histogram.unset(r);
|
||||
sp::get_cas_read_metrics_latency_histogram.unset(r);
|
||||
sp::get_view_write_metrics_latency_histogram.unset(r);
|
||||
sp::get_read_metrics_latency_histogram.unset(r);
|
||||
sp::get_read_estimated_histogram.unset(r);
|
||||
sp::get_read_latency.unset(r);
|
||||
sp::get_write_estimated_histogram.unset(r);
|
||||
sp::get_write_latency.unset(r);
|
||||
sp::get_range_estimated_histogram.unset(r);
|
||||
sp::get_range_latency.unset(r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace service { class storage_service; }
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_storage_proxy(http_context& ctx, httpd::routes& r, sharded<service::storage_service>& ss);
|
||||
void unset_storage_proxy(http_context& ctx, httpd::routes& r);
|
||||
void set_storage_proxy(http_context& ctx, routes& r, sharded<service::storage_service>& ss);
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <seastar/core/sharded.hh>
|
||||
#include "api.hh"
|
||||
#include "db/data_listeners.hh"
|
||||
@@ -36,52 +34,28 @@ class gossiper;
|
||||
|
||||
namespace api {
|
||||
|
||||
// verify that the keyspace is found, otherwise a bad_param_exception exception is thrown
|
||||
// containing the description of the respective keyspace error.
|
||||
sstring validate_keyspace(http_context& ctx, sstring ks_name);
|
||||
|
||||
// verify that the keyspace parameter is found, otherwise a bad_param_exception exception is thrown
|
||||
// containing the description of the respective keyspace error.
|
||||
sstring validate_keyspace(http_context& ctx, const httpd::parameters& param);
|
||||
sstring validate_keyspace(http_context& ctx, const parameters& param);
|
||||
|
||||
// splits a request parameter assumed to hold a comma-separated list of table names
|
||||
// verify that the tables are found, otherwise a bad_param_exception exception is thrown
|
||||
// containing the description of the respective no_such_column_family error.
|
||||
// Returns an empty vector if no parameter was found.
|
||||
// If the parameter is found and empty, returns a list of all table names in the keyspace.
|
||||
std::vector<sstring> parse_tables(const sstring& ks_name, http_context& ctx, const std::unordered_map<sstring, sstring>& query_params, sstring param_name);
|
||||
|
||||
struct table_info {
|
||||
sstring name;
|
||||
table_id id;
|
||||
};
|
||||
|
||||
// splits a request parameter assumed to hold a comma-separated list of table names
|
||||
// verify that the tables are found, otherwise a bad_param_exception exception is thrown
|
||||
// containing the description of the respective no_such_column_family error.
|
||||
// Returns a vector of all table infos given by the parameter, or
|
||||
// if the parameter is not found or is empty, returns a list of all table infos in the keyspace.
|
||||
std::vector<table_info> parse_table_infos(const sstring& ks_name, http_context& ctx, const std::unordered_map<sstring, sstring>& query_params, sstring param_name);
|
||||
|
||||
void set_storage_service(http_context& ctx, httpd::routes& r, sharded<service::storage_service>& ss, gms::gossiper& g, sharded<cdc::generation_service>& cdc_gs, sharded<db::system_keyspace>& sys_ls);
|
||||
void set_sstables_loader(http_context& ctx, httpd::routes& r, sharded<sstables_loader>& sst_loader);
|
||||
void unset_sstables_loader(http_context& ctx, httpd::routes& r);
|
||||
void set_view_builder(http_context& ctx, httpd::routes& r, sharded<db::view::view_builder>& vb);
|
||||
void unset_view_builder(http_context& ctx, httpd::routes& r);
|
||||
void set_repair(http_context& ctx, httpd::routes& r, sharded<repair_service>& repair);
|
||||
void unset_repair(http_context& ctx, httpd::routes& r);
|
||||
void set_transport_controller(http_context& ctx, httpd::routes& r, cql_transport::controller& ctl);
|
||||
void unset_transport_controller(http_context& ctx, httpd::routes& r);
|
||||
void set_rpc_controller(http_context& ctx, httpd::routes& r, thrift_controller& ctl);
|
||||
void unset_rpc_controller(http_context& ctx, httpd::routes& r);
|
||||
void set_snapshot(http_context& ctx, httpd::routes& r, sharded<db::snapshot_ctl>& snap_ctl);
|
||||
void unset_snapshot(http_context& ctx, httpd::routes& r);
|
||||
void set_storage_service(http_context& ctx, routes& r, sharded<service::storage_service>& ss, gms::gossiper& g, sharded<cdc::generation_service>& cdc_gs, sharded<db::system_keyspace>& sys_ls);
|
||||
void set_sstables_loader(http_context& ctx, routes& r, sharded<sstables_loader>& sst_loader);
|
||||
void unset_sstables_loader(http_context& ctx, routes& r);
|
||||
void set_view_builder(http_context& ctx, routes& r, sharded<db::view::view_builder>& vb);
|
||||
void unset_view_builder(http_context& ctx, routes& r);
|
||||
void set_repair(http_context& ctx, routes& r, sharded<repair_service>& repair);
|
||||
void unset_repair(http_context& ctx, routes& r);
|
||||
void set_transport_controller(http_context& ctx, routes& r, cql_transport::controller& ctl);
|
||||
void unset_transport_controller(http_context& ctx, routes& r);
|
||||
void set_rpc_controller(http_context& ctx, routes& r, thrift_controller& ctl);
|
||||
void unset_rpc_controller(http_context& ctx, routes& r);
|
||||
void set_snapshot(http_context& ctx, routes& r, sharded<db::snapshot_ctl>& snap_ctl);
|
||||
void unset_snapshot(http_context& ctx, routes& r);
|
||||
seastar::future<json::json_return_type> run_toppartitions_query(db::toppartitions_query& q, http_context &ctx, bool legacy_request = false);
|
||||
|
||||
} // namespace api
|
||||
|
||||
namespace std {
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const api::table_info& ti);
|
||||
|
||||
} // namespace std
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "gms/gossiper.hh"
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
|
||||
namespace hs = httpd::stream_manager_json;
|
||||
|
||||
@@ -22,7 +21,7 @@ static void set_summaries(const std::vector<streaming::stream_summary>& from,
|
||||
json::json_list<hs::stream_summary>& to) {
|
||||
if (!from.empty()) {
|
||||
hs::stream_summary res;
|
||||
res.cf_id = fmt::to_string(from.front().cf_id);
|
||||
res.cf_id = boost::lexical_cast<std::string>(from.front().cf_id);
|
||||
// For each stream_session, we pretend we are sending/receiving one
|
||||
// file, to make it compatible with nodetool.
|
||||
res.files = 1;
|
||||
@@ -39,7 +38,7 @@ static hs::progress_info get_progress_info(const streaming::progress_info& info)
|
||||
res.current_bytes = info.current_bytes;
|
||||
res.direction = info.dir;
|
||||
res.file_name = info.file_name;
|
||||
res.peer = fmt::to_string(info.peer);
|
||||
res.peer = boost::lexical_cast<std::string>(info.peer);
|
||||
res.session_index = 0;
|
||||
res.total_bytes = info.total_bytes;
|
||||
return res;
|
||||
@@ -62,7 +61,7 @@ static hs::stream_state get_state(
|
||||
state.plan_id = result_future.plan_id.to_sstring();
|
||||
for (auto info : result_future.get_coordinator().get()->get_all_session_info()) {
|
||||
hs::stream_info si;
|
||||
si.peer = fmt::to_string(info.peer);
|
||||
si.peer = boost::lexical_cast<std::string>(info.peer);
|
||||
si.session_index = 0;
|
||||
si.state = info.state;
|
||||
si.connecting = si.peer;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_stream_manager(http_context& ctx, httpd::routes& r, sharded<streaming::stream_manager>& sm);
|
||||
void unset_stream_manager(http_context& ctx, httpd::routes& r);
|
||||
void set_stream_manager(http_context& ctx, routes& r, sharded<streaming::stream_manager>& sm);
|
||||
void unset_stream_manager(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
extern logging::logger apilog;
|
||||
|
||||
namespace api {
|
||||
using namespace seastar::httpd;
|
||||
|
||||
namespace hs = httpd::system_json;
|
||||
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_system(http_context& ctx, httpd::routes& r);
|
||||
void set_system(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace api {
|
||||
|
||||
namespace tm = httpd::task_manager_json;
|
||||
using namespace json;
|
||||
using namespace seastar::httpd;
|
||||
|
||||
inline bool filter_tasks(tasks::task_manager::task_ptr task, std::unordered_map<sstring, sstring>& query_params) {
|
||||
return (!query_params.contains("keyspace") || query_params["keyspace"] == task->get_status().keyspace) &&
|
||||
@@ -31,32 +30,17 @@ inline bool filter_tasks(tasks::task_manager::task_ptr task, std::unordered_map<
|
||||
|
||||
struct full_task_status {
|
||||
tasks::task_manager::task::status task_status;
|
||||
std::string type;
|
||||
tasks::task_manager::task::progress progress;
|
||||
std::string module;
|
||||
tasks::task_id parent_id;
|
||||
tasks::is_abortable abortable;
|
||||
std::vector<std::string> children_ids;
|
||||
};
|
||||
|
||||
struct task_stats {
|
||||
task_stats(tasks::task_manager::task_ptr task)
|
||||
: task_id(task->id().to_sstring())
|
||||
, state(task->get_status().state)
|
||||
, type(task->type())
|
||||
, keyspace(task->get_status().keyspace)
|
||||
, table(task->get_status().table)
|
||||
, entity(task->get_status().entity)
|
||||
, sequence_number(task->get_status().sequence_number)
|
||||
{ }
|
||||
task_stats(tasks::task_manager::task_ptr task) : task_id(task->id().to_sstring()), state(task->get_status().state) {}
|
||||
|
||||
sstring task_id;
|
||||
tasks::task_manager::task_state state;
|
||||
std::string type;
|
||||
std::string keyspace;
|
||||
std::string table;
|
||||
std::string entity;
|
||||
uint64_t sequence_number;
|
||||
};
|
||||
|
||||
tm::task_status make_status(full_task_status status) {
|
||||
@@ -68,7 +52,7 @@ tm::task_status make_status(full_task_status status) {
|
||||
|
||||
tm::task_status res{};
|
||||
res.id = status.task_status.id.to_sstring();
|
||||
res.type = status.type;
|
||||
res.type = status.task_status.type;
|
||||
res.state = status.task_status.state;
|
||||
res.is_abortable = bool(status.abortable);
|
||||
res.start_time = st;
|
||||
@@ -83,45 +67,37 @@ tm::task_status make_status(full_task_status status) {
|
||||
res.progress_units = status.task_status.progress_units;
|
||||
res.progress_total = status.progress.total;
|
||||
res.progress_completed = status.progress.completed;
|
||||
res.children_ids = std::move(status.children_ids);
|
||||
return res;
|
||||
}
|
||||
|
||||
future<full_task_status> retrieve_status(const tasks::task_manager::foreign_task_ptr& task) {
|
||||
future<json::json_return_type> retrieve_status(tasks::task_manager::foreign_task_ptr task) {
|
||||
if (task.get() == nullptr) {
|
||||
co_return coroutine::return_exception(httpd::bad_param_exception("Task not found"));
|
||||
}
|
||||
auto progress = co_await task->get_progress();
|
||||
full_task_status s;
|
||||
s.task_status = task->get_status();
|
||||
s.type = task->type();
|
||||
s.parent_id = task->get_parent_id();
|
||||
s.abortable = task->is_abortable();
|
||||
s.module = task->get_module_name();
|
||||
s.progress.completed = progress.completed;
|
||||
s.progress.total = progress.total;
|
||||
std::vector<std::string> ct{task->get_children().size()};
|
||||
boost::transform(task->get_children(), ct.begin(), [] (const auto& child) {
|
||||
return child->id().to_sstring();
|
||||
});
|
||||
s.children_ids = std::move(ct);
|
||||
co_return s;
|
||||
co_return make_status(s);
|
||||
}
|
||||
|
||||
void set_task_manager(http_context& ctx, routes& r, db::config& cfg) {
|
||||
tm::get_modules.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
void set_task_manager(http_context& ctx, routes& r) {
|
||||
tm::get_modules.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
std::vector<std::string> v = boost::copy_range<std::vector<std::string>>(ctx.tm.local().get_modules() | boost::adaptors::map_keys);
|
||||
co_return v;
|
||||
});
|
||||
|
||||
tm::get_tasks.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
tm::get_tasks.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
using chunked_stats = utils::chunked_vector<task_stats>;
|
||||
auto internal = tasks::is_internal{req_param<bool>(*req, "internal", false)};
|
||||
std::vector<chunked_stats> res = co_await ctx.tm.map([&req, internal] (tasks::task_manager& tm) {
|
||||
std::vector<chunked_stats> res = co_await ctx.tm.map([&req] (tasks::task_manager& tm) {
|
||||
chunked_stats local_res;
|
||||
auto module = tm.find_module(req->param["module"]);
|
||||
const auto& filtered_tasks = module->get_tasks() | boost::adaptors::filtered([¶ms = req->query_parameters, internal] (const auto& task) {
|
||||
return (internal || !task.second->is_internal()) && filter_tasks(task.second, params);
|
||||
const auto& filtered_tasks = module->get_tasks() | boost::adaptors::filtered([¶ms = req->query_parameters] (const auto& task) {
|
||||
return filter_tasks(task.second, params);
|
||||
});
|
||||
for (auto& [task_id, task] : filtered_tasks) {
|
||||
local_res.push_back(task_stats{task});
|
||||
@@ -148,7 +124,7 @@ void set_task_manager(http_context& ctx, routes& r, db::config& cfg) {
|
||||
co_return std::move(f);
|
||||
});
|
||||
|
||||
tm::get_task_status.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
tm::get_task_status.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
auto id = tasks::task_id{utils::UUID{req->param["task_id"]}};
|
||||
auto task = co_await tasks::task_manager::invoke_on_task(ctx.tm, id, std::function([] (tasks::task_manager::task_ptr task) -> future<tasks::task_manager::foreign_task_ptr> {
|
||||
auto state = task->get_status().state;
|
||||
@@ -157,11 +133,10 @@ void set_task_manager(http_context& ctx, routes& r, db::config& cfg) {
|
||||
}
|
||||
co_return std::move(task);
|
||||
}));
|
||||
auto s = co_await retrieve_status(task);
|
||||
co_return make_status(s);
|
||||
co_return co_await retrieve_status(std::move(task));
|
||||
});
|
||||
|
||||
tm::abort_task.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
tm::abort_task.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
auto id = tasks::task_id{utils::UUID{req->param["task_id"]}};
|
||||
co_await tasks::task_manager::invoke_on_task(ctx.tm, id, [] (tasks::task_manager::task_ptr task) -> future<> {
|
||||
if (!task->is_abortable()) {
|
||||
@@ -172,7 +147,7 @@ void set_task_manager(http_context& ctx, routes& r, db::config& cfg) {
|
||||
co_return json_void();
|
||||
});
|
||||
|
||||
tm::wait_task.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
tm::wait_task.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
auto id = tasks::task_id{utils::UUID{req->param["task_id"]}};
|
||||
auto task = co_await tasks::task_manager::invoke_on_task(ctx.tm, id, std::function([] (tasks::task_manager::task_ptr task) {
|
||||
return task->done().then_wrapped([task] (auto f) {
|
||||
@@ -181,55 +156,7 @@ void set_task_manager(http_context& ctx, routes& r, db::config& cfg) {
|
||||
return make_foreign(task);
|
||||
});
|
||||
}));
|
||||
auto s = co_await retrieve_status(task);
|
||||
co_return make_status(s);
|
||||
});
|
||||
|
||||
tm::get_task_status_recursively.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
auto& _ctx = ctx;
|
||||
auto id = tasks::task_id{utils::UUID{req->param["task_id"]}};
|
||||
std::queue<tasks::task_manager::foreign_task_ptr> q;
|
||||
utils::chunked_vector<full_task_status> res;
|
||||
|
||||
// Get requested task.
|
||||
auto task = co_await tasks::task_manager::invoke_on_task(_ctx.tm, id, std::function([] (tasks::task_manager::task_ptr task) -> future<tasks::task_manager::foreign_task_ptr> {
|
||||
auto state = task->get_status().state;
|
||||
if (state == tasks::task_manager::task_state::done || state == tasks::task_manager::task_state::failed) {
|
||||
task->unregister_task();
|
||||
}
|
||||
co_return task;
|
||||
}));
|
||||
|
||||
// Push children's statuses in BFS order.
|
||||
q.push(co_await task.copy()); // Task cannot be moved since we need it to be alive during whole loop execution.
|
||||
while (!q.empty()) {
|
||||
auto& current = q.front();
|
||||
res.push_back(co_await retrieve_status(current));
|
||||
for (size_t i = 0; i < current->get_children().size(); ++i) {
|
||||
q.push(co_await current->get_children()[i].copy());
|
||||
}
|
||||
q.pop();
|
||||
}
|
||||
|
||||
std::function<future<>(output_stream<char>&&)> f = [r = std::move(res)] (output_stream<char>&& os) -> future<> {
|
||||
auto s = std::move(os);
|
||||
auto res = std::move(r);
|
||||
co_await s.write("[");
|
||||
std::string delim = "";
|
||||
for (auto& status: res) {
|
||||
co_await s.write(std::exchange(delim, ", "));
|
||||
co_await formatter::write(s, make_status(status));
|
||||
}
|
||||
co_await s.write("]");
|
||||
co_await s.close();
|
||||
};
|
||||
co_return f;
|
||||
});
|
||||
|
||||
tm::get_and_update_ttl.set(r, [&cfg] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
uint32_t ttl = cfg.task_ttl_seconds();
|
||||
co_await cfg.task_ttl_seconds.set_value_on_all_shards(req->query_parameters["ttl"], utils::config_file::config_source::API);
|
||||
co_return json::json_return_type(ttl);
|
||||
co_return co_await retrieve_status(std::move(task));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "api.hh"
|
||||
#include "db/config.hh"
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_task_manager(http_context& ctx, httpd::routes& r, db::config& cfg);
|
||||
void set_task_manager(http_context& ctx, routes& r);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,10 +18,9 @@ namespace api {
|
||||
|
||||
namespace tmt = httpd::task_manager_test_json;
|
||||
using namespace json;
|
||||
using namespace seastar::httpd;
|
||||
|
||||
void set_task_manager_test(http_context& ctx, routes& r) {
|
||||
tmt::register_test_module.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
void set_task_manager_test(http_context& ctx, routes& r, db::config& cfg) {
|
||||
tmt::register_test_module.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
co_await ctx.tm.invoke_on_all([] (tasks::task_manager& tm) {
|
||||
auto m = make_shared<tasks::test_module>(tm);
|
||||
tm.register_module("test", m);
|
||||
@@ -29,7 +28,7 @@ void set_task_manager_test(http_context& ctx, routes& r) {
|
||||
co_return json_void();
|
||||
});
|
||||
|
||||
tmt::unregister_test_module.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
tmt::unregister_test_module.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
co_await ctx.tm.invoke_on_all([] (tasks::task_manager& tm) -> future<> {
|
||||
auto module_name = "test";
|
||||
auto module = tm.find_module(module_name);
|
||||
@@ -38,7 +37,7 @@ void set_task_manager_test(http_context& ctx, routes& r) {
|
||||
co_return json_void();
|
||||
});
|
||||
|
||||
tmt::register_test_task.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
tmt::register_test_task.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
sharded<tasks::task_manager>& tms = ctx.tm;
|
||||
auto it = req->query_parameters.find("task_id");
|
||||
auto id = it != req->query_parameters.end() ? tasks::task_id{utils::UUID{it->second}} : tasks::task_id::create_null_id();
|
||||
@@ -48,10 +47,12 @@ void set_task_manager_test(http_context& ctx, routes& r) {
|
||||
std::string keyspace = it != req->query_parameters.end() ? it->second : "";
|
||||
it = req->query_parameters.find("table");
|
||||
std::string table = it != req->query_parameters.end() ? it->second : "";
|
||||
it = req->query_parameters.find("type");
|
||||
std::string type = it != req->query_parameters.end() ? it->second : "";
|
||||
it = req->query_parameters.find("entity");
|
||||
std::string entity = it != req->query_parameters.end() ? it->second : "";
|
||||
it = req->query_parameters.find("parent_id");
|
||||
tasks::task_info data;
|
||||
tasks::task_manager::parent_data data;
|
||||
if (it != req->query_parameters.end()) {
|
||||
data.id = tasks::task_id{utils::UUID{it->second}};
|
||||
auto parent_ptr = co_await tasks::task_manager::lookup_task_on_all_shards(ctx.tm, data.id);
|
||||
@@ -59,7 +60,7 @@ void set_task_manager_test(http_context& ctx, routes& r) {
|
||||
}
|
||||
|
||||
auto module = tms.local().find_module("test");
|
||||
id = co_await module->make_task<tasks::test_task_impl>(shard, id, keyspace, table, entity, data);
|
||||
id = co_await module->make_task<tasks::test_task_impl>(shard, id, keyspace, table, type, entity, data);
|
||||
co_await tms.invoke_on(shard, [id] (tasks::task_manager& tm) {
|
||||
auto it = tm.get_all_tasks().find(id);
|
||||
if (it != tm.get_all_tasks().end()) {
|
||||
@@ -69,7 +70,7 @@ void set_task_manager_test(http_context& ctx, routes& r) {
|
||||
co_return id.to_sstring();
|
||||
});
|
||||
|
||||
tmt::unregister_test_task.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
tmt::unregister_test_task.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
auto id = tasks::task_id{utils::UUID{req->query_parameters["task_id"]}};
|
||||
co_await tasks::task_manager::invoke_on_task(ctx.tm, id, [] (tasks::task_manager::task_ptr task) -> future<> {
|
||||
tasks::test_task test_task{task};
|
||||
@@ -78,7 +79,7 @@ void set_task_manager_test(http_context& ctx, routes& r) {
|
||||
co_return json_void();
|
||||
});
|
||||
|
||||
tmt::finish_test_task.set(r, [&ctx] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
|
||||
tmt::finish_test_task.set(r, [&ctx] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
auto id = tasks::task_id{utils::UUID{req->param["task_id"]}};
|
||||
auto it = req->query_parameters.find("error");
|
||||
bool fail = it != req->query_parameters.end();
|
||||
@@ -95,6 +96,12 @@ void set_task_manager_test(http_context& ctx, routes& r) {
|
||||
});
|
||||
co_return json_void();
|
||||
});
|
||||
|
||||
tmt::get_and_update_ttl.set(r, [&ctx, &cfg] (std::unique_ptr<request> req) -> future<json::json_return_type> {
|
||||
uint32_t ttl = cfg.task_ttl_seconds();
|
||||
cfg.task_ttl_seconds.set(boost::lexical_cast<uint32_t>(req->query_parameters["ttl"]));
|
||||
co_return json::json_return_type(ttl);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,10 +11,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "api.hh"
|
||||
#include "db/config.hh"
|
||||
|
||||
namespace api {
|
||||
|
||||
void set_task_manager_test(http_context& ctx, httpd::routes& r);
|
||||
void set_task_manager_test(http_context& ctx, routes& r, db::config& cfg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "atomic_cell.hh"
|
||||
#include "atomic_cell_or_collection.hh"
|
||||
#include "counters.hh"
|
||||
#include "types/types.hh"
|
||||
#include "types.hh"
|
||||
|
||||
atomic_cell atomic_cell::make_dead(api::timestamp_type timestamp, gc_clock::time_point deletion_time) {
|
||||
return atomic_cell_type::make_dead(timestamp, deletion_time);
|
||||
@@ -194,13 +194,14 @@ operator<<(std::ostream& os, const atomic_cell_view::printer& acvp) {
|
||||
std::ostringstream cell_value_string_builder;
|
||||
if (type.is_counter()) {
|
||||
if (acv.is_counter_update()) {
|
||||
fmt::print(cell_value_string_builder, "counter_update_value={}", acv.counter_update_value());
|
||||
cell_value_string_builder << "counter_update_value=" << acv.counter_update_value();
|
||||
} else {
|
||||
cell_value_string_builder << "shards: ";
|
||||
auto ccv = counter_cell_view(acv);
|
||||
fmt::print(cell_value_string_builder, "shards: {}", fmt::join(ccv.shards(), ", "));
|
||||
cell_value_string_builder << ::join(", ", ccv.shards());
|
||||
}
|
||||
} else {
|
||||
fmt::print(cell_value_string_builder, "{}", type.to_string(to_bytes(acv.value())));
|
||||
cell_value_string_builder << type.to_string(to_bytes(acv.value()));
|
||||
}
|
||||
fmt::print(os, "atomic_cell{{{},ts={:d},expiry={:d},ttl={:d}}}",
|
||||
cell_value_string_builder.str(),
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "bytes.hh"
|
||||
#include "timestamp.hh"
|
||||
#include "mutation/tombstone.hh"
|
||||
#include "tombstone.hh"
|
||||
#include "gc_clock.hh"
|
||||
#include "utils/managed_bytes.hh"
|
||||
#include <seastar/net//byteorder.hh>
|
||||
@@ -10,11 +10,11 @@
|
||||
|
||||
// Not part of atomic_cell.hh to avoid cyclic dependency between types.hh and atomic_cell.hh
|
||||
|
||||
#include "types/types.hh"
|
||||
#include "types.hh"
|
||||
#include "types/collection.hh"
|
||||
#include "atomic_cell.hh"
|
||||
#include "atomic_cell_or_collection.hh"
|
||||
#include "utils/hashing.hh"
|
||||
#include "hashing.hh"
|
||||
#include "counters.hh"
|
||||
|
||||
template<>
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "atomic_cell.hh"
|
||||
#include "collection_mutation.hh"
|
||||
#include "schema/schema.hh"
|
||||
#include "schema.hh"
|
||||
|
||||
// A variant type that can hold either an atomic_cell, or a serialized collection.
|
||||
// Which type is stored is determined by the schema.
|
||||
@@ -1,35 +0,0 @@
|
||||
include(add_whole_archive)
|
||||
|
||||
add_library(scylla_auth STATIC)
|
||||
target_sources(scylla_auth
|
||||
PRIVATE
|
||||
allow_all_authenticator.cc
|
||||
allow_all_authorizer.cc
|
||||
authenticated_user.cc
|
||||
authenticator.cc
|
||||
common.cc
|
||||
default_authorizer.cc
|
||||
password_authenticator.cc
|
||||
passwords.cc
|
||||
permission.cc
|
||||
permissions_cache.cc
|
||||
resource.cc
|
||||
role_or_anonymous.cc
|
||||
roles-metadata.cc
|
||||
sasl_challenge.cc
|
||||
service.cc
|
||||
standard_role_manager.cc
|
||||
transitional.cc)
|
||||
target_include_directories(scylla_auth
|
||||
PUBLIC
|
||||
${CMAKE_SOURCE_DIR})
|
||||
target_link_libraries(scylla_auth
|
||||
PUBLIC
|
||||
Seastar::seastar
|
||||
xxHash::xxhash
|
||||
PRIVATE
|
||||
cql3
|
||||
idl
|
||||
wasmtime_bindings)
|
||||
|
||||
add_whole_archive(auth scylla_auth)
|
||||
@@ -10,12 +10,24 @@
|
||||
|
||||
#include "auth/authenticated_user.hh"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace auth {
|
||||
|
||||
authenticated_user::authenticated_user(std::string_view name)
|
||||
: name(sstring(name)) {
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const authenticated_user& u) {
|
||||
if (!u.name) {
|
||||
os << "anonymous";
|
||||
} else {
|
||||
os << *u.name;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
static const authenticated_user the_anonymous_user{};
|
||||
|
||||
const authenticated_user& anonymous_user() noexcept {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <string_view>
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <optional>
|
||||
|
||||
#include <seastar/core/sstring.hh>
|
||||
@@ -37,6 +38,11 @@ public:
|
||||
explicit authenticated_user(std::string_view name);
|
||||
};
|
||||
|
||||
///
|
||||
/// The user name, or "anonymous".
|
||||
///
|
||||
std::ostream& operator<<(std::ostream&, const authenticated_user&);
|
||||
|
||||
inline bool operator==(const authenticated_user& u1, const authenticated_user& u2) noexcept {
|
||||
return u1.name == u2.name;
|
||||
}
|
||||
@@ -53,21 +59,6 @@ inline bool is_anonymous(const authenticated_user& u) noexcept {
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
/// The user name, or "anonymous".
|
||||
///
|
||||
template <>
|
||||
struct fmt::formatter<auth::authenticated_user> : fmt::formatter<std::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const auth::authenticated_user& u, FormatContext& ctx) const {
|
||||
if (u.name) {
|
||||
return fmt::format_to(ctx.out(), "{}", *u.name);
|
||||
} else {
|
||||
return fmt::format_to(ctx.out(), "{}", "anonymous");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
|
||||
24
auth/authentication_options.cc
Normal file
24
auth/authentication_options.cc
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2018-present ScyllaDB
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "auth/authentication_options.hh"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace auth {
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, authentication_option a) {
|
||||
switch (a) {
|
||||
case authentication_option::password: os << "PASSWORD"; break;
|
||||
case authentication_option::options: os << "OPTIONS"; break;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,8 @@ enum class authentication_option {
|
||||
options
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream&, authentication_option);
|
||||
|
||||
using authentication_option_set = std::unordered_set<authentication_option>;
|
||||
|
||||
using custom_options = std::unordered_map<sstring, sstring>;
|
||||
@@ -47,18 +49,3 @@ public:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<auth::authentication_option> : fmt::formatter<std::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const auth::authentication_option a, FormatContext& ctx) const {
|
||||
using enum auth::authentication_option;
|
||||
switch (a) {
|
||||
case password:
|
||||
return formatter<std::string_view>::format("PASSWORD", ctx);
|
||||
case options:
|
||||
return formatter<std::string_view>::format("OPTIONS", ctx);
|
||||
}
|
||||
std::abort();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "cql3/query_processor.hh"
|
||||
#include "cql3/statements/create_table_statement.hh"
|
||||
#include "replica/database.hh"
|
||||
#include "schema/schema_builder.hh"
|
||||
#include "schema_builder.hh"
|
||||
#include "service/migration_manager.hh"
|
||||
#include "timeout_config.hh"
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace replica {
|
||||
class database;
|
||||
}
|
||||
|
||||
class timeout_config;
|
||||
|
||||
namespace service {
|
||||
class migration_manager;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ future<bool> default_authorizer::any_granted() const {
|
||||
query,
|
||||
db::consistency_level::LOCAL_ONE,
|
||||
{},
|
||||
cql3::query_processor::cache_internal::yes).then([](::shared_ptr<cql3::untyped_result_set> results) {
|
||||
cql3::query_processor::cache_internal::yes).then([this](::shared_ptr<cql3::untyped_result_set> results) {
|
||||
return !results->empty();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ extern "C" {
|
||||
|
||||
namespace auth::passwords {
|
||||
|
||||
static thread_local crypt_data tlcrypt = {};
|
||||
static thread_local crypt_data tlcrypt = { 0, };
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
@@ -21,8 +21,7 @@ const auth::permission_set auth::permissions::ALL = auth::permission_set::of<
|
||||
auth::permission::SELECT,
|
||||
auth::permission::MODIFY,
|
||||
auth::permission::AUTHORIZE,
|
||||
auth::permission::DESCRIBE,
|
||||
auth::permission::EXECUTE>();
|
||||
auth::permission::DESCRIBE>();
|
||||
|
||||
const auth::permission_set auth::permissions::NONE;
|
||||
|
||||
@@ -35,8 +34,7 @@ static const std::unordered_map<sstring, auth::permission> permission_names({
|
||||
{"SELECT", auth::permission::SELECT},
|
||||
{"MODIFY", auth::permission::MODIFY},
|
||||
{"AUTHORIZE", auth::permission::AUTHORIZE},
|
||||
{"DESCRIBE", auth::permission::DESCRIBE},
|
||||
{"EXECUTE", auth::permission::EXECUTE}});
|
||||
{"DESCRIBE", auth::permission::DESCRIBE}});
|
||||
|
||||
const sstring& auth::permissions::to_string(permission p) {
|
||||
for (auto& v : permission_names) {
|
||||
|
||||
@@ -38,8 +38,6 @@ enum class permission {
|
||||
AUTHORIZE, // required for GRANT and REVOKE.
|
||||
DESCRIBE, // required on the root-level role resource to list all roles.
|
||||
|
||||
// function/aggregate/procedure calls
|
||||
EXECUTE,
|
||||
};
|
||||
|
||||
typedef enum_set<
|
||||
@@ -53,8 +51,7 @@ typedef enum_set<
|
||||
permission::SELECT,
|
||||
permission::MODIFY,
|
||||
permission::AUTHORIZE,
|
||||
permission::DESCRIBE,
|
||||
permission::EXECUTE>> permission_set;
|
||||
permission::DESCRIBE>> permission_set;
|
||||
|
||||
bool operator<(const permission_set&, const permission_set&);
|
||||
|
||||
|
||||
159
auth/resource.cc
159
auth/resource.cc
@@ -16,26 +16,30 @@
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
|
||||
#include "service/storage_proxy.hh"
|
||||
#include "data_dictionary/user_types_metadata.hh"
|
||||
#include "cql3/util.hh"
|
||||
#include "db/marshal/type_parser.hh"
|
||||
|
||||
namespace auth {
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, resource_kind kind) {
|
||||
switch (kind) {
|
||||
case resource_kind::data: os << "data"; break;
|
||||
case resource_kind::role: os << "role"; break;
|
||||
case resource_kind::service_level: os << "service_level"; break;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
static const std::unordered_map<resource_kind, std::string_view> roots{
|
||||
{resource_kind::data, "data"},
|
||||
{resource_kind::role, "roles"},
|
||||
{resource_kind::service_level, "service_levels"},
|
||||
{resource_kind::functions, "functions"}};
|
||||
{resource_kind::service_level, "service_levels"}};
|
||||
|
||||
static const std::unordered_map<resource_kind, std::size_t> max_parts{
|
||||
{resource_kind::data, 2},
|
||||
{resource_kind::role, 1},
|
||||
{resource_kind::service_level, 0},
|
||||
{resource_kind::functions, 2}};
|
||||
{resource_kind::service_level, 0}};
|
||||
|
||||
static permission_set applicable_permissions(const data_resource_view& dv) {
|
||||
if (dv.table()) {
|
||||
@@ -78,15 +82,6 @@ static permission_set applicable_permissions(const service_level_resource_view &
|
||||
permission::AUTHORIZE>();
|
||||
}
|
||||
|
||||
static permission_set applicable_permissions(const functions_resource_view& fv) {
|
||||
return permission_set::of<
|
||||
permission::CREATE,
|
||||
permission::ALTER,
|
||||
permission::DROP,
|
||||
permission::AUTHORIZE,
|
||||
permission::EXECUTE>();
|
||||
}
|
||||
|
||||
resource::resource(resource_kind kind) : _kind(kind) {
|
||||
_parts.emplace_back(roots.at(kind));
|
||||
}
|
||||
@@ -111,31 +106,6 @@ resource::resource(role_resource_t, std::string_view role) : resource(resource_k
|
||||
resource::resource(service_level_resource_t): resource(resource_kind::service_level) {
|
||||
}
|
||||
|
||||
resource::resource(functions_resource_t) : resource(resource_kind::functions) {
|
||||
}
|
||||
|
||||
resource::resource(functions_resource_t, std::string_view keyspace) : resource(resource_kind::functions) {
|
||||
_parts.emplace_back(keyspace);
|
||||
}
|
||||
|
||||
resource::resource(functions_resource_t, std::string_view keyspace, std::string_view function_signature) : resource(resource_kind::functions) {
|
||||
_parts.emplace_back(keyspace);
|
||||
_parts.emplace_back(function_signature);
|
||||
}
|
||||
|
||||
resource::resource(functions_resource_t, std::string_view keyspace, std::string_view function_name, std::vector<::shared_ptr<cql3::cql3_type::raw>> function_args) : resource(resource_kind::functions) {
|
||||
_parts.emplace_back(keyspace);
|
||||
_parts.emplace_back(function_name);
|
||||
if (function_args.empty()) {
|
||||
_parts.emplace_back("");
|
||||
return;
|
||||
}
|
||||
for (auto& arg_type : function_args) {
|
||||
// We can't validate the UDTs here, so we just use the raw cql type names.
|
||||
_parts.emplace_back(arg_type->to_string());
|
||||
}
|
||||
}
|
||||
|
||||
sstring resource::name() const {
|
||||
return boost::algorithm::join(_parts, "/");
|
||||
}
|
||||
@@ -157,7 +127,6 @@ permission_set resource::applicable_permissions() const {
|
||||
case resource_kind::data: ps = ::auth::applicable_permissions(data_resource_view(*this)); break;
|
||||
case resource_kind::role: ps = ::auth::applicable_permissions(role_resource_view(*this)); break;
|
||||
case resource_kind::service_level: ps = ::auth::applicable_permissions(service_level_resource_view(*this)); break;
|
||||
case resource_kind::functions: ps = ::auth::applicable_permissions(functions_resource_view(*this)); break;
|
||||
}
|
||||
|
||||
return ps;
|
||||
@@ -180,7 +149,6 @@ std::ostream& operator<<(std::ostream& os, const resource& r) {
|
||||
case resource_kind::data: return os << data_resource_view(r);
|
||||
case resource_kind::role: return os << role_resource_view(r);
|
||||
case resource_kind::service_level: return os << service_level_resource_view(r);
|
||||
case resource_kind::functions: return os << functions_resource_view(r);
|
||||
}
|
||||
|
||||
return os;
|
||||
@@ -197,109 +165,6 @@ std::ostream &operator<<(std::ostream &os, const service_level_resource_view &v)
|
||||
return os;
|
||||
}
|
||||
|
||||
sstring encode_signature(std::string_view name, std::vector<data_type> args) {
|
||||
return format("{}[{}]", name,
|
||||
fmt::join(args | boost::adaptors::transformed([] (const data_type t) {
|
||||
return t->name();
|
||||
}), "^"));
|
||||
}
|
||||
|
||||
std::pair<sstring, std::vector<data_type>> decode_signature(std::string_view encoded_signature) {
|
||||
auto name_delim = encoded_signature.find_last_of('[');
|
||||
std::string_view function_name = encoded_signature.substr(0, name_delim);
|
||||
encoded_signature.remove_prefix(name_delim + 1);
|
||||
encoded_signature.remove_suffix(1);
|
||||
if (encoded_signature.empty()) {
|
||||
return {sstring(function_name), {}};
|
||||
}
|
||||
std::vector<std::string_view> raw_types;
|
||||
boost::split(raw_types, encoded_signature, boost::is_any_of("^"));
|
||||
std::vector<data_type> decoded_types = boost::copy_range<std::vector<data_type>>(
|
||||
raw_types | boost::adaptors::transformed([] (std::string_view raw_type) {
|
||||
return db::marshal::type_parser::parse(raw_type);
|
||||
})
|
||||
);
|
||||
return {sstring(function_name), decoded_types};
|
||||
}
|
||||
|
||||
// Purely for Cassandra compatibility, types in the function signature are
|
||||
// decoded from their verbose form (org.apache.cassandra.db.marshal.Int32Type)
|
||||
// to the short form (int)
|
||||
static sstring decoded_signature_string(std::string_view encoded_signature) {
|
||||
auto [function_name, arg_types] = decode_signature(encoded_signature);
|
||||
return format("{}({})", cql3::util::maybe_quote(sstring(function_name)),
|
||||
boost::algorithm::join(arg_types | boost::adaptors::transformed([] (data_type t) {
|
||||
return t->cql3_type_name();
|
||||
}), ", "));
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const functions_resource_view &v) {
|
||||
const auto keyspace = v.keyspace();
|
||||
const auto function_signature = v.function_signature();
|
||||
const auto name = v.function_name();
|
||||
const auto args = v.function_args();
|
||||
|
||||
if (!keyspace) {
|
||||
os << "<all functions>";
|
||||
} else if (name) {
|
||||
os << "<function " << *keyspace << '.' << cql3::util::maybe_quote(sstring(*name)) << '(';
|
||||
for (auto arg : *args) {
|
||||
os << arg << ',';
|
||||
}
|
||||
os << ")>";
|
||||
} else if (!function_signature) {
|
||||
os << "<all functions in " << *keyspace << '>';
|
||||
} else {
|
||||
os << "<function " << *keyspace << '.' << decoded_signature_string(*function_signature) << '>';
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
functions_resource_view::functions_resource_view(const resource& r) : _resource(r) {
|
||||
if (r._kind != resource_kind::functions) {
|
||||
throw resource_kind_mismatch(resource_kind::functions, r._kind);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string_view> functions_resource_view::keyspace() const {
|
||||
if (_resource._parts.size() == 1) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return _resource._parts[1];
|
||||
}
|
||||
|
||||
std::optional<std::string_view> functions_resource_view::function_signature() const {
|
||||
if (_resource._parts.size() <= 2 || _resource._parts.size() > 3) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return _resource._parts[2];
|
||||
}
|
||||
|
||||
std::optional<std::string_view> functions_resource_view::function_name() const {
|
||||
if (_resource._parts.size() <= 3) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return _resource._parts[2];
|
||||
}
|
||||
|
||||
std::optional<std::vector<std::string_view>> functions_resource_view::function_args() const {
|
||||
if (_resource._parts.size() <= 3) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::string_view> parts;
|
||||
if (_resource._parts[3] == "") {
|
||||
return {};
|
||||
}
|
||||
for (size_t i = 3; i < _resource._parts.size(); i++) {
|
||||
parts.push_back(_resource._parts[i]);
|
||||
}
|
||||
return parts;
|
||||
}
|
||||
|
||||
data_resource_view::data_resource_view(const resource& r) : _resource(r) {
|
||||
if (r._kind != resource_kind::data) {
|
||||
throw resource_kind_mismatch(resource_kind::data, r._kind);
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
#include <seastar/core/print.hh>
|
||||
#include <seastar/core/sstring.hh>
|
||||
|
||||
@@ -26,7 +25,6 @@
|
||||
#include "seastarx.hh"
|
||||
#include "utils/hash.hh"
|
||||
#include "utils/small_vector.hh"
|
||||
#include "cql3/cql3_type.hh"
|
||||
|
||||
namespace auth {
|
||||
|
||||
@@ -38,9 +36,11 @@ public:
|
||||
};
|
||||
|
||||
enum class resource_kind {
|
||||
data, role, service_level, functions
|
||||
data, role, service_level
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream&, resource_kind);
|
||||
|
||||
///
|
||||
/// Type tag for constructing data resources.
|
||||
///
|
||||
@@ -56,15 +56,10 @@ struct role_resource_t final {};
|
||||
///
|
||||
struct service_level_resource_t final {};
|
||||
|
||||
///
|
||||
/// Type tag for constructing function resources.
|
||||
///
|
||||
struct functions_resource_t final {};
|
||||
|
||||
///
|
||||
/// Resources are entities that users can be granted permissions on.
|
||||
///
|
||||
/// There are data (keyspaces and tables), role and function resources. There may be other kinds of resources in the future.
|
||||
/// There are data (keyspaces and tables) and role resources. There may be other kinds of resources in the future.
|
||||
///
|
||||
/// When they are stored as system metadata, resources have the form `root/part_0/part_1/.../part_n`. Each kind of
|
||||
/// resource has a specific root prefix, followed by a maximum of `n` parts (where `n` is distinct for each kind of
|
||||
@@ -88,11 +83,6 @@ public:
|
||||
resource(data_resource_t, std::string_view keyspace, std::string_view table);
|
||||
resource(role_resource_t, std::string_view role);
|
||||
resource(service_level_resource_t);
|
||||
explicit resource(functions_resource_t);
|
||||
resource(functions_resource_t, std::string_view keyspace);
|
||||
resource(functions_resource_t, std::string_view keyspace, std::string_view function_signature);
|
||||
resource(functions_resource_t, std::string_view keyspace, std::string_view function_name,
|
||||
std::vector<::shared_ptr<cql3::cql3_type::raw>> function_args);
|
||||
|
||||
resource_kind kind() const noexcept {
|
||||
return _kind;
|
||||
@@ -114,7 +104,6 @@ private:
|
||||
friend class data_resource_view;
|
||||
friend class role_resource_view;
|
||||
friend class service_level_resource_view;
|
||||
friend class functions_resource_view;
|
||||
|
||||
friend bool operator<(const resource&, const resource&);
|
||||
friend bool operator==(const resource&, const resource&);
|
||||
@@ -193,25 +182,6 @@ public:
|
||||
|
||||
std::ostream& operator<<(std::ostream&, const service_level_resource_view&);
|
||||
|
||||
///
|
||||
/// A "function" view of \ref resource.
|
||||
///
|
||||
class functions_resource_view final {
|
||||
const resource& _resource;
|
||||
public:
|
||||
///
|
||||
/// \throws \ref resource_kind_mismatch if the argument is not a "function" resource.
|
||||
///
|
||||
explicit functions_resource_view(const resource&);
|
||||
|
||||
std::optional<std::string_view> keyspace() const;
|
||||
std::optional<std::string_view> function_signature() const;
|
||||
std::optional<std::string_view> function_name() const;
|
||||
std::optional<std::vector<std::string_view>> function_args() const;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream&, const functions_resource_view&);
|
||||
|
||||
///
|
||||
/// Parse a resource from its name.
|
||||
///
|
||||
@@ -240,49 +210,8 @@ inline resource make_service_level_resource() {
|
||||
return resource(service_level_resource_t{});
|
||||
}
|
||||
|
||||
const resource& root_function_resource();
|
||||
|
||||
inline resource make_functions_resource() {
|
||||
return resource(functions_resource_t{});
|
||||
}
|
||||
|
||||
inline resource make_functions_resource(std::string_view keyspace) {
|
||||
return resource(functions_resource_t{}, keyspace);
|
||||
}
|
||||
|
||||
inline resource make_functions_resource(std::string_view keyspace, std::string_view function_signature) {
|
||||
return resource(functions_resource_t{}, keyspace, function_signature);
|
||||
}
|
||||
|
||||
inline resource make_functions_resource(std::string_view keyspace, std::string_view function_name, std::vector<::shared_ptr<cql3::cql3_type::raw>> function_signature) {
|
||||
return resource(functions_resource_t{}, keyspace, function_name, function_signature);
|
||||
}
|
||||
|
||||
sstring encode_signature(std::string_view name, std::vector<data_type> args);
|
||||
|
||||
std::pair<sstring, std::vector<data_type>> decode_signature(std::string_view encoded_signature);
|
||||
|
||||
}
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<auth::resource_kind> : fmt::formatter<std::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const auth::resource_kind kind, FormatContext& ctx) const {
|
||||
using enum auth::resource_kind;
|
||||
switch (kind) {
|
||||
case data:
|
||||
return formatter<std::string_view>::format("data", ctx);
|
||||
case role:
|
||||
return formatter<std::string_view>::format("role", ctx);
|
||||
case service_level:
|
||||
return formatter<std::string_view>::format("service_level", ctx);
|
||||
case functions:
|
||||
return formatter<std::string_view>::format("functions", ctx);
|
||||
}
|
||||
std::abort();
|
||||
}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
@@ -299,10 +228,6 @@ struct hash<auth::resource> {
|
||||
return utils::tuple_hash()(std::make_tuple(auth::resource_kind::service_level));
|
||||
}
|
||||
|
||||
static size_t hash_function(const auth::functions_resource_view& fv) {
|
||||
return utils::tuple_hash()(std::make_tuple(auth::resource_kind::functions, fv.keyspace(), fv.function_signature()));
|
||||
}
|
||||
|
||||
size_t operator()(const auth::resource& r) const {
|
||||
std::size_t value;
|
||||
|
||||
@@ -310,7 +235,6 @@ struct hash<auth::resource> {
|
||||
case auth::resource_kind::data: value = hash_data(auth::data_resource_view(r)); break;
|
||||
case auth::resource_kind::role: value = hash_role(auth::role_resource_view(r)); break;
|
||||
case auth::resource_kind::service_level: value = hash_service_level(auth::service_level_resource_view(r)); break;
|
||||
case auth::resource_kind::functions: value = hash_function(auth::functions_resource_view(r)); break;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
@@ -20,19 +20,17 @@
|
||||
#include "auth/allow_all_authorizer.hh"
|
||||
#include "auth/common.hh"
|
||||
#include "auth/role_or_anonymous.hh"
|
||||
#include "cql3/functions/functions.hh"
|
||||
#include "cql3/query_processor.hh"
|
||||
#include "cql3/untyped_result_set.hh"
|
||||
#include "db/config.hh"
|
||||
#include "db/consistency_level_type.hh"
|
||||
#include "db/functions/function_name.hh"
|
||||
#include "exceptions/exceptions.hh"
|
||||
#include "log.hh"
|
||||
#include "service/migration_manager.hh"
|
||||
#include "utils/class_registrator.hh"
|
||||
#include "locator/abstract_replication_strategy.hh"
|
||||
#include "data_dictionary/keyspace_metadata.hh"
|
||||
#include "mutation/mutation.hh"
|
||||
#include "mutation.hh"
|
||||
|
||||
namespace auth {
|
||||
|
||||
@@ -348,22 +346,6 @@ future<bool> service::exists(const resource& r) const {
|
||||
}
|
||||
case resource_kind::service_level:
|
||||
return make_ready_future<bool>(true);
|
||||
|
||||
case resource_kind::functions: {
|
||||
const auto& db = _qp.db();
|
||||
|
||||
functions_resource_view v(r);
|
||||
const auto keyspace = v.keyspace();
|
||||
if (!keyspace) {
|
||||
return make_ready_future<bool>(true);
|
||||
}
|
||||
const auto function_signature = v.function_signature();
|
||||
if (!function_signature) {
|
||||
return make_ready_future<bool>(db.has_keyspace(sstring(*keyspace)));
|
||||
}
|
||||
auto [name, function_args] = auth::decode_signature(*function_signature);
|
||||
return make_ready_future<bool>(cql3::functions::functions::find(db::functions::function_name{sstring(*keyspace), name}, function_args));
|
||||
}
|
||||
}
|
||||
|
||||
return make_ready_future<bool>(false);
|
||||
|
||||
@@ -470,7 +470,7 @@ standard_role_manager::grant(std::string_view grantee_name, std::string_view rol
|
||||
|
||||
future<>
|
||||
standard_role_manager::revoke(std::string_view revokee_name, std::string_view role_name) {
|
||||
return this->exists(role_name).then([role_name](bool role_exists) {
|
||||
return this->exists(role_name).then([this, revokee_name, role_name](bool role_exists) {
|
||||
if (!role_exists) {
|
||||
throw nonexistant_role(sstring(role_name));
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef STRINGIFY
|
||||
// We need two levels of indirection
|
||||
// We need to levels of indirection
|
||||
// to make a string out of the macro name.
|
||||
// The outer level expands the macro
|
||||
// and the inner level makes a string out of the expanded macro.
|
||||
|
||||
22
bytes.cc
22
bytes.cc
@@ -50,7 +50,15 @@ bytes from_hex(sstring_view s) {
|
||||
}
|
||||
|
||||
sstring to_hex(bytes_view b) {
|
||||
return fmt::to_string(fmt_hex(b));
|
||||
static char digits[] = "0123456789abcdef";
|
||||
sstring out = uninitialized_string(b.size() * 2);
|
||||
unsigned end = b.size();
|
||||
for (unsigned i = 0; i != end; ++i) {
|
||||
uint8_t x = b[i];
|
||||
out[2*i] = digits[x >> 4];
|
||||
out[2*i+1] = digits[x & 0xf];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
sstring to_hex(const bytes& b) {
|
||||
@@ -62,14 +70,12 @@ sstring to_hex(const bytes_opt& b) {
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const bytes& b) {
|
||||
fmt::print(os, "{}", b);
|
||||
return os;
|
||||
return os << to_hex(b);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const bytes_opt& b) {
|
||||
if (b) {
|
||||
fmt::print(os, "{}", *b);
|
||||
return os;
|
||||
return os << *b;
|
||||
}
|
||||
return os << "null";
|
||||
}
|
||||
@@ -77,13 +83,11 @@ std::ostream& operator<<(std::ostream& os, const bytes_opt& b) {
|
||||
namespace std {
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const bytes_view& b) {
|
||||
fmt::print(os, "{}", fmt_hex(b));
|
||||
return os;
|
||||
return os << to_hex(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const fmt_hex& b) {
|
||||
fmt::print(os, "{}", b);
|
||||
return os;
|
||||
return os << to_hex(b.v);
|
||||
}
|
||||
|
||||
90
bytes.hh
90
bytes.hh
@@ -9,9 +9,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "seastarx.hh"
|
||||
#include <fmt/format.h>
|
||||
#include <seastar/core/sstring.hh>
|
||||
#include "utils/hashing.hh"
|
||||
#include "hashing.hh"
|
||||
#include <optional>
|
||||
#include <iosfwd>
|
||||
#include <functional>
|
||||
@@ -38,8 +37,8 @@ inline bytes_view to_bytes_view(sstring_view view) {
|
||||
}
|
||||
|
||||
struct fmt_hex {
|
||||
const bytes_view& v;
|
||||
fmt_hex(const bytes_view& v) noexcept : v(v) {}
|
||||
bytes_view& v;
|
||||
fmt_hex(bytes_view& v) noexcept : v(v) {}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const fmt_hex& hex);
|
||||
@@ -52,89 +51,6 @@ sstring to_hex(const bytes_opt& b);
|
||||
std::ostream& operator<<(std::ostream& os, const bytes& b);
|
||||
std::ostream& operator<<(std::ostream& os, const bytes_opt& b);
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<fmt_hex> {
|
||||
size_t _group_size_in_bytes = 0;
|
||||
char _delimiter = ' ';
|
||||
public:
|
||||
// format_spec := [group_size[delimeter]]
|
||||
// group_size := a char from '0' to '9'
|
||||
// delimeter := a char other than '{' or '}'
|
||||
//
|
||||
// by default, the given bytes are printed without delimeter, just
|
||||
// like a string. so a string view of {0x20, 0x01, 0x0d, 0xb8} is
|
||||
// printed like:
|
||||
// "20010db8".
|
||||
//
|
||||
// but the format specifier can be used to customize how the bytes
|
||||
// are printed. for instance, to print an bytes_view like IPv6. so
|
||||
// the format specfier would be "{:2:}", where
|
||||
// - "2": bytes are printed in groups of 2 bytes
|
||||
// - ":": each group is delimeted by ":"
|
||||
// and the formatted output will look like:
|
||||
// "2001:0db8:0000"
|
||||
//
|
||||
// or we can mimic how the default format of used by hexdump using
|
||||
// "{:2 }", where
|
||||
// - "2": bytes are printed in group of 2 bytes
|
||||
// - " ": each group is delimeted by " "
|
||||
// and the formatted output will look like:
|
||||
// "2001 0db8 0000"
|
||||
//
|
||||
// or we can just print each bytes and separate them by a dash using
|
||||
// "{:1-}"
|
||||
// and the formatted output will look like:
|
||||
// "20-01-0b-b8-00-00"
|
||||
constexpr auto parse(fmt::format_parse_context& ctx) {
|
||||
// get the delimeter if any
|
||||
auto it = ctx.begin();
|
||||
auto end = ctx.end();
|
||||
if (it != end) {
|
||||
int group_size = *it++ - '0';
|
||||
if (group_size < 0 ||
|
||||
static_cast<size_t>(group_size) > sizeof(uint64_t)) {
|
||||
throw format_error("invalid group_size");
|
||||
}
|
||||
_group_size_in_bytes = group_size;
|
||||
if (it != end) {
|
||||
// optional delimiter
|
||||
_delimiter = *it++;
|
||||
}
|
||||
}
|
||||
if (it != end && *it != '}') {
|
||||
throw format_error("invalid format");
|
||||
}
|
||||
return it;
|
||||
}
|
||||
template <typename FormatContext>
|
||||
auto format(const ::fmt_hex& s, FormatContext& ctx) const {
|
||||
auto out = ctx.out();
|
||||
const auto& v = s.v;
|
||||
if (_group_size_in_bytes > 0) {
|
||||
for (size_t i = 0, size = v.size(); i < size; i++) {
|
||||
if (i != 0 && i % _group_size_in_bytes == 0) {
|
||||
fmt::format_to(out, "{}{:02x}", _delimiter, std::byte(v[i]));
|
||||
} else {
|
||||
fmt::format_to(out, "{:02x}", std::byte(v[i]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto b : v) {
|
||||
fmt::format_to(out, "{:02x}", std::byte(b));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<bytes> : fmt::formatter<fmt_hex> {
|
||||
template <typename FormatContext>
|
||||
auto format(const ::bytes& s, FormatContext& ctx) const {
|
||||
return fmt::formatter<::fmt_hex>::format(::fmt_hex(bytes_view(s)), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
|
||||
// Must be in std:: namespace, or ADL fails
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include "bytes.hh"
|
||||
#include "utils/managed_bytes.hh"
|
||||
#include "utils/hashing.hh"
|
||||
#include "hashing.hh"
|
||||
#include <seastar/core/simple-stream.hh>
|
||||
#include <seastar/core/loop.hh>
|
||||
#include <bit>
|
||||
@@ -457,9 +457,7 @@ public:
|
||||
_begin.ptr->size = _size;
|
||||
_current = nullptr;
|
||||
_size = 0;
|
||||
auto begin_ptr = _begin.ptr;
|
||||
_begin.ptr = nullptr;
|
||||
return managed_bytes(begin_ptr);
|
||||
return managed_bytes(std::exchange(_begin.ptr, {}));
|
||||
} else {
|
||||
return managed_bytes();
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
|
||||
#include <vector>
|
||||
#include "row_cache.hh"
|
||||
#include "mutation/mutation_fragment.hh"
|
||||
#include "mutation_fragment.hh"
|
||||
#include "query-request.hh"
|
||||
#include "partition_snapshot_row_cursor.hh"
|
||||
#include "mutation/range_tombstone_assembler.hh"
|
||||
#include "range_tombstone_assembler.hh"
|
||||
#include "read_context.hh"
|
||||
#include "readers/delegating_v2.hh"
|
||||
#include "clustering_key_filter.hh"
|
||||
@@ -41,7 +41,7 @@ class cache_flat_mutation_reader final : public flat_mutation_reader_v2::impl {
|
||||
move_to_underlying,
|
||||
|
||||
// Invariants:
|
||||
// - Upper bound of the read is *_underlying_upper_bound
|
||||
// - Upper bound of the read is min(_next_row.position(), _upper_bound)
|
||||
// - _next_row_in_range = _next.position() < _upper_bound
|
||||
// - _last_row points at a direct predecessor of the next row which is going to be read.
|
||||
// Used for populating continuity.
|
||||
@@ -51,6 +51,46 @@ class cache_flat_mutation_reader final : public flat_mutation_reader_v2::impl {
|
||||
|
||||
end_of_stream
|
||||
};
|
||||
enum class source {
|
||||
cache = 0,
|
||||
underlying = 1,
|
||||
};
|
||||
// Merges range tombstone change streams coming from underlying and the cache.
|
||||
// Ensures no range tombstone change fragment is emitted when there is no
|
||||
// actual change in the effective tombstone.
|
||||
class range_tombstone_change_merger {
|
||||
const schema& _schema;
|
||||
position_in_partition _pos;
|
||||
tombstone _current_tombstone;
|
||||
std::array<tombstone, 2> _tombstones;
|
||||
private:
|
||||
std::optional<range_tombstone_change> do_flush(position_in_partition pos, bool end_of_range) {
|
||||
std::optional<range_tombstone_change> ret;
|
||||
position_in_partition::tri_compare cmp(_schema);
|
||||
const auto res = cmp(_pos, pos);
|
||||
const auto should_flush = end_of_range ? res <= 0 : res < 0;
|
||||
if (should_flush) {
|
||||
auto merged_tomb = std::max(_tombstones.front(), _tombstones.back());
|
||||
if (merged_tomb != _current_tombstone) {
|
||||
_current_tombstone = merged_tomb;
|
||||
ret.emplace(_pos, _current_tombstone);
|
||||
}
|
||||
_pos = std::move(pos);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
public:
|
||||
range_tombstone_change_merger(const schema& s) : _schema(s), _pos(position_in_partition::before_all_clustered_rows()), _tombstones{}
|
||||
{ }
|
||||
std::optional<range_tombstone_change> apply(source src, range_tombstone_change&& rtc) {
|
||||
auto ret = do_flush(rtc.position(), false);
|
||||
_tombstones[static_cast<size_t>(src)] = rtc.tombstone();
|
||||
return ret;
|
||||
}
|
||||
std::optional<range_tombstone_change> flush(position_in_partition_view pos, bool end_of_range) {
|
||||
return do_flush(position_in_partition(pos), end_of_range);
|
||||
}
|
||||
};
|
||||
partition_snapshot_ptr _snp;
|
||||
|
||||
query::clustering_key_filter_ranges _ck_ranges; // Query schema domain, reversed reads use native order
|
||||
@@ -63,11 +103,8 @@ class cache_flat_mutation_reader final : public flat_mutation_reader_v2::impl {
|
||||
|
||||
// Holds the lower bound of a position range which hasn't been processed yet.
|
||||
// Only rows with positions < _lower_bound have been emitted, and only
|
||||
// range_tombstone_changes with positions <= _lower_bound.
|
||||
//
|
||||
// Invariant: !_lower_bound.is_clustering_row()
|
||||
// range_tombstones with positions <= _lower_bound.
|
||||
position_in_partition _lower_bound; // Query schema domain
|
||||
// Invariant: !_upper_bound.is_clustering_row()
|
||||
position_in_partition_view _upper_bound; // Query schema domain
|
||||
std::optional<position_in_partition> _underlying_upper_bound; // Query schema domain
|
||||
|
||||
@@ -84,19 +121,22 @@ class cache_flat_mutation_reader final : public flat_mutation_reader_v2::impl {
|
||||
read_context& _read_context;
|
||||
partition_snapshot_row_cursor _next_row;
|
||||
|
||||
// Holds the currently active range tombstone of the output mutation fragment stream.
|
||||
// While producing the stream, at any given time, _current_tombstone applies to the
|
||||
// key range which extends at least to _lower_bound. When consuming subsequent interval,
|
||||
// which will advance _lower_bound further, be it from underlying or from cache,
|
||||
// a decision is made whether the range tombstone in the next interval is the same as
|
||||
// the current one or not. If it is different, then range_tombstone_change is emitted
|
||||
// with the old _lower_bound value (start of the next interval).
|
||||
tombstone _current_tombstone;
|
||||
range_tombstone_change_generator _rt_gen; // cache -> reader
|
||||
range_tombstone_assembler _rt_assembler; // underlying -> cache
|
||||
range_tombstone_change_merger _rt_merger; // {cache, underlying} -> reader
|
||||
|
||||
// When the read moves to the underlying, the read range will be
|
||||
// (_lower_bound, x], where x is either _next_row.position() or _upper_bound.
|
||||
// In the former case (x is _next_row.position()), underlying can emit
|
||||
// a range tombstone change for after_key(x), which is outside the range.
|
||||
// We can't push this fragment into the buffer straight away, the cache may
|
||||
// have fragments with smaller position. So we save it here and flush it when
|
||||
// a fragment with a larger position is seen.
|
||||
std::optional<mutation_fragment_v2> _queued_underlying_fragment;
|
||||
|
||||
state _state = state::before_static_row;
|
||||
|
||||
bool _next_row_in_range = false;
|
||||
bool _has_rt = false;
|
||||
|
||||
// True iff current population interval, since the previous clustering row, starts before all clustered rows.
|
||||
// We cannot just look at _lower_bound, because emission of range tombstones changes _lower_bound and
|
||||
@@ -105,6 +145,11 @@ class cache_flat_mutation_reader final : public flat_mutation_reader_v2::impl {
|
||||
// Valid when _state == reading_from_underlying.
|
||||
bool _population_range_starts_before_all_rows;
|
||||
|
||||
// Whether _lower_bound was changed within current fill_buffer().
|
||||
// If it did not then we cannot break out of it (e.g. on preemption) because
|
||||
// forward progress is not guaranteed in case iterators are getting constantly invalidated.
|
||||
bool _lower_bound_changed = false;
|
||||
|
||||
// Points to the underlying reader conforming to _schema,
|
||||
// either to *_underlying_holder or _read_context.underlying().underlying().
|
||||
flat_mutation_reader_v2* _underlying = nullptr;
|
||||
@@ -118,11 +163,14 @@ class cache_flat_mutation_reader final : public flat_mutation_reader_v2::impl {
|
||||
void move_to_next_range();
|
||||
void move_to_range(query::clustering_row_ranges::const_iterator);
|
||||
void move_to_next_entry();
|
||||
void maybe_drop_last_entry(tombstone) noexcept;
|
||||
void maybe_drop_last_entry() noexcept;
|
||||
void flush_tombstones(position_in_partition_view, bool end_of_range = false);
|
||||
void add_to_buffer(const partition_snapshot_row_cursor&);
|
||||
void add_clustering_row_to_buffer(mutation_fragment_v2&&);
|
||||
void add_to_buffer(range_tombstone_change&&);
|
||||
void offer_from_underlying(mutation_fragment_v2&&);
|
||||
void add_to_buffer(range_tombstone_change&&, source);
|
||||
void do_add_to_buffer(range_tombstone_change&&);
|
||||
void add_range_tombstone_to_buffer(range_tombstone&&);
|
||||
void add_to_buffer(mutation_fragment_v2&&);
|
||||
future<> read_from_underlying();
|
||||
void start_reading_from_underlying();
|
||||
bool after_current_range(position_in_partition_view position);
|
||||
@@ -141,7 +189,7 @@ class cache_flat_mutation_reader final : public flat_mutation_reader_v2::impl {
|
||||
bool ensure_population_lower_bound();
|
||||
void maybe_add_to_cache(const mutation_fragment_v2& mf);
|
||||
void maybe_add_to_cache(const clustering_row& cr);
|
||||
bool maybe_add_to_cache(const range_tombstone_change& rtc);
|
||||
void maybe_add_to_cache(const range_tombstone_change& rtc);
|
||||
void maybe_add_to_cache(const static_row& sr);
|
||||
void maybe_set_static_row_continuous();
|
||||
void finish_reader() {
|
||||
@@ -196,6 +244,8 @@ public:
|
||||
, _read_context_holder()
|
||||
, _read_context(ctx) // ctx is owned by the caller, who's responsible for closing it.
|
||||
, _next_row(*_schema, *_snp, false, _read_context.is_reversed())
|
||||
, _rt_gen(*_schema)
|
||||
, _rt_merger(*_schema)
|
||||
{
|
||||
clogger.trace("csm {}: table={}.{}, reversed={}, snap={}", fmt::ptr(this), _schema->ks_name(), _schema->cf_name(), _read_context.is_reversed(),
|
||||
fmt::ptr(&*_snp));
|
||||
@@ -323,31 +373,13 @@ future<> cache_flat_mutation_reader::do_fill_buffer() {
|
||||
}
|
||||
_state = state::reading_from_underlying;
|
||||
_population_range_starts_before_all_rows = _lower_bound.is_before_all_clustered_rows(*_schema) && !_read_context.is_reversed();
|
||||
_underlying_upper_bound = _next_row_in_range ? position_in_partition::before_key(_next_row.position())
|
||||
: position_in_partition(_upper_bound);
|
||||
if (!_read_context.partition_exists()) {
|
||||
clogger.trace("csm {}: partition does not exist", fmt::ptr(this));
|
||||
if (_current_tombstone) {
|
||||
clogger.trace("csm {}: move_to_underlying: emit rtc({}, null)", fmt::ptr(this), _lower_bound);
|
||||
push_mutation_fragment(mutation_fragment_v2(*_schema, _permit, range_tombstone_change(_lower_bound, {})));
|
||||
_current_tombstone = {};
|
||||
}
|
||||
return read_from_underlying();
|
||||
}
|
||||
_underlying_upper_bound = _next_row_in_range ? position_in_partition(_next_row.position())
|
||||
: position_in_partition(_upper_bound);
|
||||
return _underlying->fast_forward_to(position_range{_lower_bound, *_underlying_upper_bound}).then([this] {
|
||||
if (!_current_tombstone) {
|
||||
return read_from_underlying();
|
||||
}
|
||||
return _underlying->peek().then([this] (mutation_fragment_v2* mf) {
|
||||
position_in_partition::equal_compare eq(*_schema);
|
||||
if (!mf || !mf->is_range_tombstone_change()
|
||||
|| !eq(mf->as_range_tombstone_change().position(), _lower_bound)) {
|
||||
clogger.trace("csm {}: move_to_underlying: emit rtc({}, null)", fmt::ptr(this), _lower_bound);
|
||||
push_mutation_fragment(mutation_fragment_v2(*_schema, _permit, range_tombstone_change(_lower_bound, {})));
|
||||
_current_tombstone = {};
|
||||
}
|
||||
return read_from_underlying();
|
||||
});
|
||||
return read_from_underlying();
|
||||
});
|
||||
}
|
||||
if (_state == state::reading_from_underlying) {
|
||||
@@ -356,8 +388,8 @@ future<> cache_flat_mutation_reader::do_fill_buffer() {
|
||||
// assert(_state == state::reading_from_cache)
|
||||
return _lsa_manager.run_in_read_section([this] {
|
||||
auto next_valid = _next_row.iterators_valid();
|
||||
clogger.trace("csm {}: reading_from_cache, range=[{}, {}), next={}, valid={}, rt={}", fmt::ptr(this), _lower_bound,
|
||||
_upper_bound, _next_row.position(), next_valid, _current_tombstone);
|
||||
clogger.trace("csm {}: reading_from_cache, range=[{}, {}), next={}, valid={}", fmt::ptr(this), _lower_bound,
|
||||
_upper_bound, _next_row.position(), next_valid);
|
||||
// We assume that if there was eviction, and thus the range may
|
||||
// no longer be continuous, the cursor was invalidated.
|
||||
if (!next_valid) {
|
||||
@@ -371,9 +403,13 @@ future<> cache_flat_mutation_reader::do_fill_buffer() {
|
||||
}
|
||||
_next_row.maybe_refresh();
|
||||
clogger.trace("csm {}: next={}", fmt::ptr(this), _next_row);
|
||||
_lower_bound_changed = false;
|
||||
while (_state == state::reading_from_cache) {
|
||||
copy_from_cache_to_buffer();
|
||||
if (need_preempt() || is_buffer_full()) {
|
||||
// We need to check _lower_bound_changed even if is_buffer_full() because
|
||||
// we may have emitted only a range tombstone which overlapped with _lower_bound
|
||||
// and thus didn't cause _lower_bound to change.
|
||||
if ((need_preempt() || is_buffer_full()) && _lower_bound_changed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -387,38 +423,37 @@ future<> cache_flat_mutation_reader::read_from_underlying() {
|
||||
[this] { return _state != state::reading_from_underlying || is_buffer_full(); },
|
||||
[this] (mutation_fragment_v2 mf) {
|
||||
_read_context.cache().on_row_miss();
|
||||
offer_from_underlying(std::move(mf));
|
||||
maybe_add_to_cache(mf);
|
||||
add_to_buffer(std::move(mf));
|
||||
},
|
||||
[this] {
|
||||
_lower_bound = std::move(*_underlying_upper_bound);
|
||||
_underlying_upper_bound.reset();
|
||||
_state = state::reading_from_cache;
|
||||
_lsa_manager.run_in_update_section([this] {
|
||||
auto same_pos = _next_row.maybe_refresh();
|
||||
clogger.trace("csm {}: underlying done, in_range={}, same={}, next={}", fmt::ptr(this), _next_row_in_range, same_pos, _next_row);
|
||||
if (!same_pos) {
|
||||
_read_context.cache().on_mispopulate(); // FIXME: Insert dummy entry at _lower_bound.
|
||||
_read_context.cache().on_mispopulate(); // FIXME: Insert dummy entry at _upper_bound.
|
||||
_next_row_in_range = !after_current_range(_next_row.position());
|
||||
if (!_next_row.continuous()) {
|
||||
_last_row = nullptr; // We did not populate the full range up to _lower_bound, break continuity
|
||||
start_reading_from_underlying();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (_next_row_in_range) {
|
||||
maybe_update_continuity();
|
||||
if (!_next_row.dummy()) {
|
||||
_lower_bound = position_in_partition::before_key(_next_row.key());
|
||||
} else {
|
||||
_lower_bound = _next_row.position();
|
||||
}
|
||||
} else {
|
||||
if (can_populate()) {
|
||||
if (no_clustering_row_between(*_schema, _upper_bound, _next_row.position())) {
|
||||
this->maybe_update_continuity();
|
||||
} else if (can_populate()) {
|
||||
const schema& table_s = table_schema();
|
||||
rows_entry::tri_compare cmp(table_s);
|
||||
auto& rows = _snp->version()->partition().mutable_clustered_rows();
|
||||
if (query::is_single_row(*_schema, *_ck_ranges_curr)) {
|
||||
// If there are range tombstones which apply to the row then
|
||||
// we cannot insert an empty entry here because if those range
|
||||
// tombstones got evicted by now, we will insert an entry
|
||||
// with missing range tombstone information.
|
||||
// FIXME: try to set the range tombstone when possible.
|
||||
if (!_has_rt) {
|
||||
with_allocator(_snp->region().allocator(), [&] {
|
||||
auto e = alloc_strategy_unique_ptr<rows_entry>(
|
||||
current_allocator().construct<rows_entry>(_ck_ranges_curr->start()->value()));
|
||||
@@ -431,10 +466,9 @@ future<> cache_flat_mutation_reader::read_from_underlying() {
|
||||
// Also works in reverse read mode.
|
||||
// It preserves the continuity of the range the entry falls into.
|
||||
it->set_continuous(next->continuous());
|
||||
clogger.trace("csm {}: inserted empty row at {}, cont={}, rt={}", fmt::ptr(this), it->position(), it->continuous(), it->range_tombstone());
|
||||
clogger.trace("csm {}: inserted empty row at {}, cont={}", fmt::ptr(this), it->position(), it->continuous());
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (ensure_population_lower_bound()) {
|
||||
with_allocator(_snp->region().allocator(), [&] {
|
||||
auto e = alloc_strategy_unique_ptr<rows_entry>(
|
||||
@@ -442,19 +476,17 @@ future<> cache_flat_mutation_reader::read_from_underlying() {
|
||||
// Use _next_row iterator only as a hint, because there could be insertions after _upper_bound.
|
||||
auto insert_result = rows.insert_before_hint(_next_row.get_iterator_in_latest_version(), std::move(e), cmp);
|
||||
if (insert_result.second) {
|
||||
clogger.trace("csm {}: L{}: inserted dummy at {}", fmt::ptr(this), __LINE__, _upper_bound);
|
||||
clogger.trace("csm {}: inserted dummy at {}", fmt::ptr(this), _upper_bound);
|
||||
_snp->tracker()->insert(*insert_result.first);
|
||||
}
|
||||
if (_read_context.is_reversed()) [[unlikely]] {
|
||||
clogger.trace("csm {}: set_continuous({}), prev={}, rt={}", fmt::ptr(this), _last_row.position(), insert_result.first->position(), _current_tombstone);
|
||||
clogger.trace("csm {}: set_continuous({})", fmt::ptr(this), _last_row.position());
|
||||
_last_row->set_continuous(true);
|
||||
_last_row->set_range_tombstone(_current_tombstone);
|
||||
} else {
|
||||
clogger.trace("csm {}: set_continuous({}), prev={}, rt={}", fmt::ptr(this), insert_result.first->position(), _last_row.position(), _current_tombstone);
|
||||
clogger.trace("csm {}: set_continuous({})", fmt::ptr(this), insert_result.first->position());
|
||||
insert_result.first->set_continuous(true);
|
||||
insert_result.first->set_range_tombstone(_current_tombstone);
|
||||
}
|
||||
maybe_drop_last_entry(_current_tombstone);
|
||||
maybe_drop_last_entry();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@@ -483,103 +515,55 @@ bool cache_flat_mutation_reader::ensure_population_lower_bound() {
|
||||
// Continuity flag we will later set for the upper bound extends to the previous row in the same version,
|
||||
// so we need to ensure we have an entry in the latest version.
|
||||
if (!_last_row.is_in_latest_version()) {
|
||||
rows_entry::tri_compare cmp(*_schema);
|
||||
partition_snapshot_row_cursor cur(*_schema, *_snp, false, _read_context.is_reversed());
|
||||
|
||||
if (!cur.advance_to(_last_row.position())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cmp(cur.position(), _last_row.position()) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto res = with_allocator(_snp->region().allocator(), [&] {
|
||||
return cur.ensure_entry_in_latest();
|
||||
with_allocator(_snp->region().allocator(), [&] {
|
||||
auto& rows = _snp->version()->partition().mutable_clustered_rows();
|
||||
rows_entry::tri_compare cmp(table_schema());
|
||||
// FIXME: Avoid the copy by inserting an incomplete clustering row
|
||||
auto e = alloc_strategy_unique_ptr<rows_entry>(
|
||||
current_allocator().construct<rows_entry>(table_schema(), *_last_row));
|
||||
e->set_continuous(false);
|
||||
auto insert_result = rows.insert_before_hint(rows.end(), std::move(e), cmp);
|
||||
if (insert_result.second) {
|
||||
auto it = insert_result.first;
|
||||
clogger.trace("csm {}: inserted lower bound dummy at {}", fmt::ptr(this), it->position());
|
||||
_snp->tracker()->insert(*it);
|
||||
}
|
||||
_last_row.set_latest(insert_result.first);
|
||||
});
|
||||
|
||||
_last_row.set_latest(res.it);
|
||||
if (res.inserted) {
|
||||
clogger.trace("csm {}: inserted lower bound dummy at {}", fmt::ptr(this), _last_row.position());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::maybe_update_continuity() {
|
||||
position_in_partition::equal_compare eq(*_schema);
|
||||
if (can_populate()
|
||||
&& ensure_population_lower_bound()
|
||||
&& !eq(_last_row.position(), _next_row.position())) {
|
||||
if (can_populate() && ensure_population_lower_bound()) {
|
||||
with_allocator(_snp->region().allocator(), [&] {
|
||||
rows_entry& e = _next_row.ensure_entry_in_latest().row;
|
||||
auto& rows = _snp->version()->partition().mutable_clustered_rows();
|
||||
const schema& table_s = table_schema();
|
||||
rows_entry::tri_compare table_cmp(table_s);
|
||||
|
||||
if (_read_context.is_reversed()) [[unlikely]] {
|
||||
if (_current_tombstone != _last_row->range_tombstone() && !_last_row->dummy()) {
|
||||
with_allocator(_snp->region().allocator(), [&] {
|
||||
auto e2 = alloc_strategy_unique_ptr<rows_entry>(
|
||||
current_allocator().construct<rows_entry>(table_s,
|
||||
position_in_partition_view::before_key(_last_row->position()),
|
||||
is_dummy::yes,
|
||||
is_continuous::yes));
|
||||
auto insert_result = rows.insert(std::move(e2), table_cmp);
|
||||
if (insert_result.second) {
|
||||
clogger.trace("csm {}: L{}: inserted dummy at {}", fmt::ptr(this), __LINE__, insert_result.first->position());
|
||||
_snp->tracker()->insert(*insert_result.first);
|
||||
}
|
||||
clogger.trace("csm {}: set_continuous({}), prev={}, rt={}", fmt::ptr(this), insert_result.first->position(),
|
||||
_last_row.position(), _current_tombstone);
|
||||
insert_result.first->set_continuous(true);
|
||||
insert_result.first->set_range_tombstone(_current_tombstone);
|
||||
clogger.trace("csm {}: set_continuous({})", fmt::ptr(this), _last_row.position());
|
||||
_last_row->set_continuous(true);
|
||||
});
|
||||
} else {
|
||||
clogger.trace("csm {}: set_continuous({}), rt={}", fmt::ptr(this), _last_row.position(), _current_tombstone);
|
||||
_last_row->set_continuous(true);
|
||||
_last_row->set_range_tombstone(_current_tombstone);
|
||||
}
|
||||
clogger.trace("csm {}: set_continuous({})", fmt::ptr(this), _last_row.position());
|
||||
_last_row->set_continuous(true);
|
||||
} else {
|
||||
if (_current_tombstone != e.range_tombstone() && !e.dummy()) {
|
||||
with_allocator(_snp->region().allocator(), [&] {
|
||||
auto e2 = alloc_strategy_unique_ptr<rows_entry>(
|
||||
current_allocator().construct<rows_entry>(table_s,
|
||||
position_in_partition_view::before_key(e.position()),
|
||||
is_dummy::yes,
|
||||
is_continuous::yes));
|
||||
// Use _next_row iterator only as a hint because there could be insertions before
|
||||
// _next_row.get_iterator_in_latest_version(), either from concurrent reads,
|
||||
// from _next_row.ensure_entry_in_latest().
|
||||
auto insert_result = rows.insert_before_hint(_next_row.get_iterator_in_latest_version(), std::move(e2), table_cmp);
|
||||
if (insert_result.second) {
|
||||
clogger.trace("csm {}: L{}: inserted dummy at {}", fmt::ptr(this), __LINE__, insert_result.first->position());
|
||||
_snp->tracker()->insert(*insert_result.first);
|
||||
}
|
||||
clogger.trace("csm {}: set_continuous({}), prev={}, rt={}", fmt::ptr(this), insert_result.first->position(),
|
||||
_last_row.position(), _current_tombstone);
|
||||
insert_result.first->set_continuous(true);
|
||||
insert_result.first->set_range_tombstone(_current_tombstone);
|
||||
clogger.trace("csm {}: set_continuous({})", fmt::ptr(this), e.position());
|
||||
e.set_continuous(true);
|
||||
});
|
||||
} else {
|
||||
clogger.trace("csm {}: set_continuous({}), rt={}", fmt::ptr(this), e.position(), _current_tombstone);
|
||||
e.set_range_tombstone(_current_tombstone);
|
||||
e.set_continuous(true);
|
||||
}
|
||||
clogger.trace("csm {}: set_continuous({})", fmt::ptr(this), e.position());
|
||||
e.set_continuous(true);
|
||||
}
|
||||
maybe_drop_last_entry(_current_tombstone);
|
||||
maybe_drop_last_entry();
|
||||
});
|
||||
} else {
|
||||
_read_context.cache().on_mispopulate();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::maybe_add_to_cache(const mutation_fragment_v2& mf) {
|
||||
if (mf.is_range_tombstone_change()) {
|
||||
maybe_add_to_cache(mf.as_range_tombstone_change());
|
||||
} else {
|
||||
assert(mf.is_clustering_row());
|
||||
const clustering_row& cr = mf.as_clustering_row();
|
||||
maybe_add_to_cache(cr);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::maybe_add_to_cache(const clustering_row& cr) {
|
||||
if (!can_populate()) {
|
||||
@@ -588,9 +572,16 @@ void cache_flat_mutation_reader::maybe_add_to_cache(const clustering_row& cr) {
|
||||
_read_context.cache().on_mispopulate();
|
||||
return;
|
||||
}
|
||||
clogger.trace("csm {}: populate({}), rt={}", fmt::ptr(this), clustering_row::printer(*_schema, cr), _current_tombstone);
|
||||
_lsa_manager.run_in_update_section_with_allocator([this, &cr] {
|
||||
mutation_partition_v2& mp = _snp->version()->partition();
|
||||
auto rt_opt = _rt_assembler.flush(*_schema, position_in_partition::after_key(cr.key()));
|
||||
clogger.trace("csm {}: populate({})", fmt::ptr(this), clustering_row::printer(*_schema, cr));
|
||||
_lsa_manager.run_in_update_section_with_allocator([this, &cr, &rt_opt] {
|
||||
mutation_partition& mp = _snp->version()->partition();
|
||||
|
||||
if (rt_opt) {
|
||||
clogger.trace("csm {}: populate flushed rt({})", fmt::ptr(this), *rt_opt);
|
||||
mp.mutable_row_tombstones().apply_monotonically(table_schema(), to_table_domain(range_tombstone(*rt_opt)));
|
||||
}
|
||||
|
||||
rows_entry::tri_compare cmp(table_schema());
|
||||
|
||||
if (_read_context.digest_requested()) {
|
||||
@@ -599,7 +590,6 @@ void cache_flat_mutation_reader::maybe_add_to_cache(const clustering_row& cr) {
|
||||
auto new_entry = alloc_strategy_unique_ptr<rows_entry>(
|
||||
current_allocator().construct<rows_entry>(table_schema(), cr.key(), cr.as_deletable_row()));
|
||||
new_entry->set_continuous(false);
|
||||
new_entry->set_range_tombstone(_current_tombstone);
|
||||
auto it = _next_row.iterators_valid() ? _next_row.get_iterator_in_latest_version()
|
||||
: mp.clustered_rows().lower_bound(cr.key(), cmp);
|
||||
auto insert_result = mp.mutable_clustered_rows().insert_before_hint(it, std::move(new_entry), cmp);
|
||||
@@ -613,14 +603,9 @@ void cache_flat_mutation_reader::maybe_add_to_cache(const clustering_row& cr) {
|
||||
if (_read_context.is_reversed()) [[unlikely]] {
|
||||
clogger.trace("csm {}: set_continuous({})", fmt::ptr(this), _last_row.position());
|
||||
_last_row->set_continuous(true);
|
||||
// _current_tombstone must also apply to _last_row itself (if it's non-dummy)
|
||||
// because otherwise there would be a rtc after it, either creating a different entry,
|
||||
// or clearing _last_row if population did not happen.
|
||||
_last_row->set_range_tombstone(_current_tombstone);
|
||||
} else {
|
||||
clogger.trace("csm {}: set_continuous({})", fmt::ptr(this), e.position());
|
||||
e.set_continuous(true);
|
||||
e.set_range_tombstone(_current_tombstone);
|
||||
}
|
||||
} else {
|
||||
_read_context.cache().on_mispopulate();
|
||||
@@ -632,72 +617,6 @@ void cache_flat_mutation_reader::maybe_add_to_cache(const clustering_row& cr) {
|
||||
});
|
||||
}
|
||||
|
||||
inline
|
||||
bool cache_flat_mutation_reader::maybe_add_to_cache(const range_tombstone_change& rtc) {
|
||||
rows_entry::tri_compare q_cmp(*_schema);
|
||||
|
||||
clogger.trace("csm {}: maybe_add_to_cache({})", fmt::ptr(this), rtc);
|
||||
|
||||
// Don't emit the closing range tombstone change, we may continue from cache with the same tombstone.
|
||||
// The following relies on !_underlying_upper_bound->is_clustering_row()
|
||||
if (q_cmp(rtc.position(), *_underlying_upper_bound) == 0) {
|
||||
_lower_bound = rtc.position();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto prev = std::exchange(_current_tombstone, rtc.tombstone());
|
||||
if (_current_tombstone == prev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!can_populate()) {
|
||||
// _current_tombstone is now invalid and remains so for this reader. No need to change it.
|
||||
_last_row = nullptr;
|
||||
_population_range_starts_before_all_rows = false;
|
||||
_read_context.cache().on_mispopulate();
|
||||
return true;
|
||||
}
|
||||
|
||||
_lsa_manager.run_in_update_section_with_allocator([&] {
|
||||
mutation_partition_v2& mp = _snp->version()->partition();
|
||||
rows_entry::tri_compare cmp(table_schema());
|
||||
|
||||
auto new_entry = alloc_strategy_unique_ptr<rows_entry>(
|
||||
current_allocator().construct<rows_entry>(table_schema(), to_table_domain(rtc.position()), is_dummy::yes, is_continuous::no));
|
||||
auto it = _next_row.iterators_valid() ? _next_row.get_iterator_in_latest_version()
|
||||
: mp.clustered_rows().lower_bound(to_table_domain(rtc.position()), cmp);
|
||||
auto insert_result = mp.mutable_clustered_rows().insert_before_hint(it, std::move(new_entry), cmp);
|
||||
it = insert_result.first;
|
||||
if (insert_result.second) {
|
||||
_snp->tracker()->insert(*it);
|
||||
}
|
||||
|
||||
rows_entry& e = *it;
|
||||
if (ensure_population_lower_bound()) {
|
||||
// underlying may emit range_tombstone_change fragments with the same position.
|
||||
// In such case, the range to which the tombstone from the first fragment applies is empty and should be ignored.
|
||||
if (q_cmp(_last_row.position(), it->position()) < 0) {
|
||||
if (_read_context.is_reversed()) [[unlikely]] {
|
||||
clogger.trace("csm {}: set_continuous({}), rt={}", fmt::ptr(this), _last_row.position(), prev);
|
||||
_last_row->set_continuous(true);
|
||||
_last_row->set_range_tombstone(prev);
|
||||
} else {
|
||||
clogger.trace("csm {}: set_continuous({}), rt={}", fmt::ptr(this), e.position(), prev);
|
||||
e.set_continuous(true);
|
||||
e.set_range_tombstone(prev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_read_context.cache().on_mispopulate();
|
||||
}
|
||||
with_allocator(standard_allocator(), [&] {
|
||||
_last_row = partition_snapshot_row_weakref(*_snp, it, true);
|
||||
});
|
||||
_population_range_starts_before_all_rows = false;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool cache_flat_mutation_reader::after_current_range(position_in_partition_view p) {
|
||||
position_in_partition::tri_compare cmp(*_schema);
|
||||
@@ -713,35 +632,19 @@ void cache_flat_mutation_reader::start_reading_from_underlying() {
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::copy_from_cache_to_buffer() {
|
||||
clogger.trace("csm {}: copy_from_cache, next_row_in_range={}, next={}", fmt::ptr(this), _next_row_in_range, _next_row);
|
||||
clogger.trace("csm {}: copy_from_cache, next={}, next_row_in_range={}", fmt::ptr(this), _next_row.position(), _next_row_in_range);
|
||||
_next_row.touch();
|
||||
|
||||
if (_next_row.range_tombstone() != _current_tombstone) {
|
||||
position_in_partition::equal_compare eq(*_schema);
|
||||
auto upper_bound = _next_row_in_range ? position_in_partition_view::before_key(_next_row.position()) : _upper_bound;
|
||||
if (!eq(_lower_bound, upper_bound)) {
|
||||
position_in_partition new_lower_bound(upper_bound);
|
||||
auto tomb = _next_row.range_tombstone();
|
||||
clogger.trace("csm {}: rtc({}, {}) ...{}", fmt::ptr(this), _lower_bound, tomb, new_lower_bound);
|
||||
push_mutation_fragment(mutation_fragment_v2(*_schema, _permit, range_tombstone_change(_lower_bound, tomb)));
|
||||
_current_tombstone = tomb;
|
||||
_lower_bound = std::move(new_lower_bound);
|
||||
_read_context.cache()._tracker.on_range_tombstone_read();
|
||||
}
|
||||
position_in_partition_view next_lower_bound = _next_row.dummy() ? _next_row.position() : position_in_partition_view::after_key(_next_row.key());
|
||||
auto upper_bound = _next_row_in_range ? next_lower_bound : _upper_bound;
|
||||
if (_snp->range_tombstones(_lower_bound, upper_bound, [&] (range_tombstone rts) {
|
||||
add_range_tombstone_to_buffer(std::move(rts));
|
||||
return stop_iteration(_lower_bound_changed && is_buffer_full());
|
||||
}, _read_context.is_reversed()) == stop_iteration::no) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We add the row to the buffer even when it's full.
|
||||
// This simplifies the code. For more info see #3139.
|
||||
if (_next_row_in_range) {
|
||||
if (_next_row.range_tombstone_for_row() != _current_tombstone) [[unlikely]] {
|
||||
auto tomb = _next_row.range_tombstone_for_row();
|
||||
auto new_lower_bound = position_in_partition::before_key(_next_row.position());
|
||||
clogger.trace("csm {}: rtc({}, {})", fmt::ptr(this), new_lower_bound, tomb);
|
||||
push_mutation_fragment(mutation_fragment_v2(*_schema, _permit, range_tombstone_change(new_lower_bound, tomb)));
|
||||
_lower_bound = std::move(new_lower_bound);
|
||||
_current_tombstone = tomb;
|
||||
_read_context.cache()._tracker.on_range_tombstone_read();
|
||||
}
|
||||
add_to_buffer(_next_row);
|
||||
move_to_next_entry();
|
||||
} else {
|
||||
@@ -757,11 +660,10 @@ void cache_flat_mutation_reader::move_to_end() {
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::move_to_next_range() {
|
||||
if (_current_tombstone) {
|
||||
clogger.trace("csm {}: move_to_next_range: emit rtc({}, null)", fmt::ptr(this), _upper_bound);
|
||||
push_mutation_fragment(mutation_fragment_v2(*_schema, _permit, range_tombstone_change(_upper_bound, {})));
|
||||
_current_tombstone = {};
|
||||
if (_queued_underlying_fragment) {
|
||||
add_to_buffer(*std::exchange(_queued_underlying_fragment, {}));
|
||||
}
|
||||
flush_tombstones(position_in_partition::for_range_end(*_ck_ranges_curr), true);
|
||||
auto next_it = std::next(_ck_ranges_curr);
|
||||
if (next_it == _ck_ranges_end) {
|
||||
move_to_end();
|
||||
@@ -778,6 +680,8 @@ void cache_flat_mutation_reader::move_to_range(query::clustering_row_ranges::con
|
||||
_last_row = nullptr;
|
||||
_lower_bound = std::move(lb);
|
||||
_upper_bound = std::move(ub);
|
||||
_rt_gen.trim(_lower_bound);
|
||||
_lower_bound_changed = true;
|
||||
_ck_ranges_curr = next_it;
|
||||
auto adjacent = _next_row.advance_to(_lower_bound);
|
||||
_next_row_in_range = !after_current_range(_next_row.position());
|
||||
@@ -818,7 +722,7 @@ void cache_flat_mutation_reader::move_to_range(query::clustering_row_ranges::con
|
||||
// _next_row must have a greater position than _last_row.
|
||||
// Invalidates references but keeps the _next_row valid.
|
||||
inline
|
||||
void cache_flat_mutation_reader::maybe_drop_last_entry(tombstone rt) noexcept {
|
||||
void cache_flat_mutation_reader::maybe_drop_last_entry() noexcept {
|
||||
// Drop dummy entry if it falls inside a continuous range.
|
||||
// This prevents unnecessary dummy entries from accumulating in cache and slowing down scans.
|
||||
//
|
||||
@@ -829,12 +733,9 @@ void cache_flat_mutation_reader::maybe_drop_last_entry(tombstone rt) noexcept {
|
||||
&& !_read_context.is_reversed() // FIXME
|
||||
&& _last_row->dummy()
|
||||
&& _last_row->continuous()
|
||||
&& _last_row->range_tombstone() == rt
|
||||
&& _snp->at_latest_version()
|
||||
&& _snp->at_oldest_version()) {
|
||||
|
||||
clogger.trace("csm {}: dropping unnecessary dummy at {}", fmt::ptr(this), _last_row->position());
|
||||
|
||||
with_allocator(_snp->region().allocator(), [&] {
|
||||
cache_tracker& tracker = _read_context.cache()._tracker;
|
||||
tracker.get_lru().remove(*_last_row);
|
||||
@@ -868,38 +769,57 @@ void cache_flat_mutation_reader::move_to_next_entry() {
|
||||
if (!_next_row.continuous()) {
|
||||
start_reading_from_underlying();
|
||||
} else {
|
||||
maybe_drop_last_entry(_next_row.range_tombstone());
|
||||
maybe_drop_last_entry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cache_flat_mutation_reader::flush_tombstones(position_in_partition_view pos, bool end_of_range) {
|
||||
// Ensure position is appropriate for range tombstone bound
|
||||
pos = position_in_partition_view::after_key(pos);
|
||||
clogger.trace("csm {}: flush_tombstones({}) end_of_range: {}", fmt::ptr(this), pos, end_of_range);
|
||||
_rt_gen.flush(pos, [this] (range_tombstone_change&& rtc) {
|
||||
add_to_buffer(std::move(rtc), source::cache);
|
||||
}, end_of_range);
|
||||
if (auto rtc_opt = _rt_merger.flush(pos, end_of_range)) {
|
||||
do_add_to_buffer(std::move(*rtc_opt));
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::offer_from_underlying(mutation_fragment_v2&& mf) {
|
||||
clogger.trace("csm {}: offer_from_underlying({})", fmt::ptr(this), mutation_fragment_v2::printer(*_schema, mf));
|
||||
void cache_flat_mutation_reader::add_to_buffer(mutation_fragment_v2&& mf) {
|
||||
clogger.trace("csm {}: add_to_buffer({})", fmt::ptr(this), mutation_fragment_v2::printer(*_schema, mf));
|
||||
position_in_partition::less_compare less(*_schema);
|
||||
if (_underlying_upper_bound && less(*_underlying_upper_bound, mf.position())) {
|
||||
_queued_underlying_fragment = std::move(mf);
|
||||
return;
|
||||
}
|
||||
flush_tombstones(mf.position());
|
||||
if (mf.is_clustering_row()) {
|
||||
maybe_add_to_cache(mf.as_clustering_row());
|
||||
add_clustering_row_to_buffer(std::move(mf));
|
||||
} else {
|
||||
assert(mf.is_range_tombstone_change());
|
||||
auto& chg = mf.as_range_tombstone_change();
|
||||
if (maybe_add_to_cache(chg)) {
|
||||
add_to_buffer(std::move(mf).as_range_tombstone_change());
|
||||
}
|
||||
add_to_buffer(std::move(mf).as_range_tombstone_change(), source::underlying);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::add_to_buffer(const partition_snapshot_row_cursor& row) {
|
||||
position_in_partition::less_compare less(*_schema);
|
||||
if (_queued_underlying_fragment && less(_queued_underlying_fragment->position(), row.position())) {
|
||||
add_to_buffer(*std::exchange(_queued_underlying_fragment, {}));
|
||||
}
|
||||
if (!row.dummy()) {
|
||||
_read_context.cache().on_row_hit();
|
||||
if (_read_context.digest_requested()) {
|
||||
row.latest_row().cells().prepare_hash(table_schema(), column_kind::regular_column);
|
||||
}
|
||||
flush_tombstones(position_in_partition_view::for_key(row.key()));
|
||||
add_clustering_row_to_buffer(mutation_fragment_v2(*_schema, _permit, row.row()));
|
||||
} else {
|
||||
if (less(_lower_bound, row.position())) {
|
||||
_lower_bound = row.position();
|
||||
_lower_bound_changed = true;
|
||||
}
|
||||
_read_context.cache()._tracker.on_dummy_row_hit();
|
||||
}
|
||||
@@ -912,24 +832,67 @@ inline
|
||||
void cache_flat_mutation_reader::add_clustering_row_to_buffer(mutation_fragment_v2&& mf) {
|
||||
clogger.trace("csm {}: add_clustering_row_to_buffer({})", fmt::ptr(this), mutation_fragment_v2::printer(*_schema, mf));
|
||||
auto& row = mf.as_clustering_row();
|
||||
auto new_lower_bound = position_in_partition::after_key(*_schema, row.key());
|
||||
auto new_lower_bound = position_in_partition::after_key(row.key());
|
||||
push_mutation_fragment(std::move(mf));
|
||||
_lower_bound = std::move(new_lower_bound);
|
||||
_lower_bound_changed = true;
|
||||
if (row.tomb()) {
|
||||
_read_context.cache()._tracker.on_row_tombstone_read();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::add_to_buffer(range_tombstone_change&& rtc) {
|
||||
void cache_flat_mutation_reader::add_to_buffer(range_tombstone_change&& rtc, source src) {
|
||||
clogger.trace("csm {}: add_to_buffer({})", fmt::ptr(this), rtc);
|
||||
_has_rt = true;
|
||||
if (auto rtc_opt = _rt_merger.apply(src, std::move(rtc))) {
|
||||
do_add_to_buffer(std::move(*rtc_opt));
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::do_add_to_buffer(range_tombstone_change&& rtc) {
|
||||
clogger.trace("csm {}: push({})", fmt::ptr(this), rtc);
|
||||
position_in_partition::less_compare less(*_schema);
|
||||
auto lower_bound_changed = less(_lower_bound, rtc.position());
|
||||
_lower_bound = position_in_partition(rtc.position());
|
||||
_lower_bound_changed = lower_bound_changed;
|
||||
push_mutation_fragment(*_schema, _permit, std::move(rtc));
|
||||
_read_context.cache()._tracker.on_range_tombstone_read();
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::add_range_tombstone_to_buffer(range_tombstone&& rt) {
|
||||
position_in_partition::less_compare less(*_schema);
|
||||
if (_queued_underlying_fragment && less(_queued_underlying_fragment->position(), rt.position())) {
|
||||
add_to_buffer(*std::exchange(_queued_underlying_fragment, {}));
|
||||
}
|
||||
clogger.trace("csm {}: add_to_buffer({})", fmt::ptr(this), rt);
|
||||
if (!less(_lower_bound, rt.position())) {
|
||||
rt.set_start(_lower_bound);
|
||||
}
|
||||
flush_tombstones(rt.position());
|
||||
_rt_gen.consume(std::move(rt));
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::maybe_add_to_cache(const range_tombstone_change& rtc) {
|
||||
clogger.trace("csm {}: maybe_add_to_cache({})", fmt::ptr(this), rtc);
|
||||
auto rt_opt = _rt_assembler.consume(*_schema, range_tombstone_change(rtc));
|
||||
if (!rt_opt) {
|
||||
return;
|
||||
}
|
||||
const auto& rt = *rt_opt;
|
||||
if (can_populate()) {
|
||||
clogger.trace("csm {}: maybe_add_to_cache({})", fmt::ptr(this), rt);
|
||||
_lsa_manager.run_in_update_section_with_allocator([&] {
|
||||
_snp->version()->partition().mutable_row_tombstones().apply_monotonically(
|
||||
table_schema(), to_table_domain(rt));
|
||||
});
|
||||
} else {
|
||||
_read_context.cache().on_mispopulate();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void cache_flat_mutation_reader::maybe_add_to_cache(const static_row& sr) {
|
||||
if (can_populate()) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user