mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 00:30:49 +00:00
Merge branch 'master' into mvcc_prototype
This commit is contained in:
commit
e9a5a64a71
121
.github/workflows/docs_release.yml
vendored
Normal file
121
.github/workflows/docs_release.yml
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
name: DocsReleaseChecks
|
||||
|
||||
env:
|
||||
# Force the stdout and stderr streams to be unbuffered
|
||||
PYTHONUNBUFFERED: 1
|
||||
|
||||
concurrency:
|
||||
group: master-release
|
||||
cancel-in-progress: true
|
||||
on: # yamllint disable-line rule:truthy
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'website/**'
|
||||
- 'benchmark/**'
|
||||
- 'docker/**'
|
||||
- '.github/**'
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
DockerHubPushAarch64:
|
||||
runs-on: [self-hosted, func-tester-aarch64]
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: |
|
||||
sudo rm -fr "$GITHUB_WORKSPACE" && mkdir "$GITHUB_WORKSPACE"
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Images check
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||
python3 docker_images_check.py --suffix aarch64
|
||||
- name: Upload images files to artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: changed_images_aarch64
|
||||
path: ${{ runner.temp }}/docker_images_check/changed_images_aarch64.json
|
||||
DockerHubPushAmd64:
|
||||
runs-on: [self-hosted, style-checker]
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: |
|
||||
sudo rm -fr "$GITHUB_WORKSPACE" && mkdir "$GITHUB_WORKSPACE"
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Images check
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||
python3 docker_images_check.py --suffix amd64
|
||||
- name: Upload images files to artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: changed_images_amd64
|
||||
path: ${{ runner.temp }}/docker_images_check/changed_images_amd64.json
|
||||
DockerHubPush:
|
||||
needs: [DockerHubPushAmd64, DockerHubPushAarch64]
|
||||
runs-on: [self-hosted, style-checker]
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: |
|
||||
sudo rm -fr "$GITHUB_WORKSPACE" && mkdir "$GITHUB_WORKSPACE"
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Download changed aarch64 images
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: changed_images_aarch64
|
||||
path: ${{ runner.temp }}
|
||||
- name: Download changed amd64 images
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: changed_images_amd64
|
||||
path: ${{ runner.temp }}
|
||||
- name: Images check
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||
python3 docker_manifests_merge.py --suffix amd64 --suffix aarch64
|
||||
- name: Upload images files to artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: changed_images
|
||||
path: ${{ runner.temp }}/changed_images.json
|
||||
DocsRelease:
|
||||
needs: DockerHubPush
|
||||
runs-on: [self-hosted, func-tester]
|
||||
steps:
|
||||
- name: Set envs
|
||||
# https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#multiline-strings
|
||||
run: |
|
||||
cat >> "$GITHUB_ENV" << 'EOF'
|
||||
TEMP_PATH=${{runner.temp}}/docs_release
|
||||
REPO_COPY=${{runner.temp}}/docs_release/ClickHouse
|
||||
CLOUDFLARE_TOKEN=${{secrets.CLOUDFLARE}}
|
||||
ROBOT_CLICKHOUSE_SSH_KEY<<RCSK
|
||||
${{secrets.ROBOT_CLICKHOUSE_SSH_KEY}}
|
||||
RCSK
|
||||
EOF
|
||||
- name: Clear repository
|
||||
run: |
|
||||
sudo rm -fr "$GITHUB_WORKSPACE" && mkdir "$GITHUB_WORKSPACE"
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Download changed images
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: changed_images
|
||||
path: ${{ env.TEMP_PATH }}
|
||||
- name: Docs Release
|
||||
run: |
|
||||
sudo rm -fr "$TEMP_PATH"
|
||||
mkdir -p "$TEMP_PATH"
|
||||
cp -r "$GITHUB_WORKSPACE" "$TEMP_PATH"
|
||||
cd "$REPO_COPY/tests/ci"
|
||||
python3 docs_release.py
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: |
|
||||
docker kill "$(docker ps -q)" ||:
|
||||
docker rm -f "$(docker ps -a -q)" ||:
|
||||
sudo rm -fr "$TEMP_PATH"
|
150
.github/workflows/release.yml
vendored
150
.github/workflows/release.yml
vendored
@ -1,121 +1,39 @@
|
||||
name: DocsReleaseChecks
|
||||
name: ReleaseWorkflow
|
||||
# - Gets artifacts from S3
|
||||
# - Sends it to JFROG Artifactory
|
||||
# - Adds them to the release assets
|
||||
|
||||
env:
|
||||
# Force the stdout and stderr streams to be unbuffered
|
||||
PYTHONUNBUFFERED: 1
|
||||
|
||||
concurrency:
|
||||
group: master-release
|
||||
cancel-in-progress: true
|
||||
on: # yamllint disable-line rule:truthy
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'website/**'
|
||||
- 'benchmark/**'
|
||||
- 'docker/**'
|
||||
- '.github/**'
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
DockerHubPushAarch64:
|
||||
runs-on: [self-hosted, func-tester-aarch64]
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: |
|
||||
sudo rm -fr "$GITHUB_WORKSPACE" && mkdir "$GITHUB_WORKSPACE"
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Images check
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||
python3 docker_images_check.py --suffix aarch64
|
||||
- name: Upload images files to artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: changed_images_aarch64
|
||||
path: ${{ runner.temp }}/docker_images_check/changed_images_aarch64.json
|
||||
DockerHubPushAmd64:
|
||||
ReleasePublish:
|
||||
runs-on: [self-hosted, style-checker]
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: |
|
||||
sudo rm -fr "$GITHUB_WORKSPACE" && mkdir "$GITHUB_WORKSPACE"
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Images check
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||
python3 docker_images_check.py --suffix amd64
|
||||
- name: Upload images files to artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: changed_images_amd64
|
||||
path: ${{ runner.temp }}/docker_images_check/changed_images_amd64.json
|
||||
DockerHubPush:
|
||||
needs: [DockerHubPushAmd64, DockerHubPushAarch64]
|
||||
runs-on: [self-hosted, style-checker]
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: |
|
||||
sudo rm -fr "$GITHUB_WORKSPACE" && mkdir "$GITHUB_WORKSPACE"
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Download changed aarch64 images
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: changed_images_aarch64
|
||||
path: ${{ runner.temp }}
|
||||
- name: Download changed amd64 images
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: changed_images_amd64
|
||||
path: ${{ runner.temp }}
|
||||
- name: Images check
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||
python3 docker_manifests_merge.py --suffix amd64 --suffix aarch64
|
||||
- name: Upload images files to artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: changed_images
|
||||
path: ${{ runner.temp }}/changed_images.json
|
||||
DocsRelease:
|
||||
needs: DockerHubPush
|
||||
runs-on: [self-hosted, func-tester]
|
||||
steps:
|
||||
- name: Set envs
|
||||
# https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#multiline-strings
|
||||
run: |
|
||||
cat >> "$GITHUB_ENV" << 'EOF'
|
||||
TEMP_PATH=${{runner.temp}}/docs_release
|
||||
REPO_COPY=${{runner.temp}}/docs_release/ClickHouse
|
||||
CLOUDFLARE_TOKEN=${{secrets.CLOUDFLARE}}
|
||||
ROBOT_CLICKHOUSE_SSH_KEY<<RCSK
|
||||
${{secrets.ROBOT_CLICKHOUSE_SSH_KEY}}
|
||||
RCSK
|
||||
EOF
|
||||
- name: Clear repository
|
||||
run: |
|
||||
sudo rm -fr "$GITHUB_WORKSPACE" && mkdir "$GITHUB_WORKSPACE"
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Download changed images
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: changed_images
|
||||
path: ${{ env.TEMP_PATH }}
|
||||
- name: Docs Release
|
||||
run: |
|
||||
sudo rm -fr "$TEMP_PATH"
|
||||
mkdir -p "$TEMP_PATH"
|
||||
cp -r "$GITHUB_WORKSPACE" "$TEMP_PATH"
|
||||
cd "$REPO_COPY/tests/ci"
|
||||
python3 docs_release.py
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: |
|
||||
docker kill "$(docker ps -q)" ||:
|
||||
docker rm -f "$(docker ps -a -q)" ||:
|
||||
sudo rm -fr "$TEMP_PATH"
|
||||
- name: Set envs
|
||||
run: |
|
||||
cat >> "$GITHUB_ENV" << 'EOF'
|
||||
JFROG_API_KEY=${{ secrets.JFROG_KEY_API_PACKAGES }}
|
||||
TEMP_PATH=${{runner.temp}}/release_packages
|
||||
REPO_COPY=${{runner.temp}}/release_packages/ClickHouse
|
||||
EOF
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Download packages and push to Artifactory
|
||||
env:
|
||||
run: |
|
||||
rm -rf "$TEMP_PATH" && mkdir -p "$REPO_COPY"
|
||||
cp -r "$GITHUB_WORKSPACE" "$REPO_COPY"
|
||||
cd "$REPO_COPY"
|
||||
python3 ./tests/ci/push_to_artifactory.py --release "${{ github.ref }}" \
|
||||
--commit '${{ github.sha }}' --all
|
||||
- name: Upload packages to release assets
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ${{runner.temp}}/release_packages/*
|
||||
overwrite: true
|
||||
tag: ${{ github.ref }}
|
||||
file_glob: true
|
||||
|
8
.github/workflows/release_branches.yml
vendored
8
.github/workflows/release_branches.yml
vendored
@ -7,10 +7,10 @@ env:
|
||||
on: # yamllint disable-line rule:truthy
|
||||
push:
|
||||
branches:
|
||||
- '21.[1-9][1-9]'
|
||||
- '22.[1-9][1-9]'
|
||||
- '23.[1-9][1-9]'
|
||||
- '24.[1-9][1-9]'
|
||||
# 22.1 and 22.10
|
||||
- '2[1-9].[1-9][0-9]'
|
||||
- '2[1-9].[1-9]'
|
||||
|
||||
jobs:
|
||||
DockerHubPushAarch64:
|
||||
runs-on: [self-hosted, func-tester-aarch64]
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,7 @@
|
||||
/build_*
|
||||
/build-*
|
||||
/tests/venv
|
||||
/obj-x86_64-linux-gnu/
|
||||
|
||||
# logs
|
||||
*.log
|
||||
|
2176
CHANGELOG.md
2176
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@ -415,13 +415,14 @@ else ()
|
||||
endif ()
|
||||
|
||||
if (WERROR)
|
||||
add_warning(error)
|
||||
# Don't pollute CMAKE_CXX_FLAGS with -Werror as it will break some CMake checks.
|
||||
# Instead, adopt modern cmake usage requirement.
|
||||
target_compile_options(global-libs INTERFACE "-Werror")
|
||||
endif ()
|
||||
|
||||
# Make this extra-checks for correct library dependencies.
|
||||
if (OS_LINUX AND NOT SANITIZE)
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
|
||||
target_link_options(global-libs INTERFACE "-Wl,--no-undefined")
|
||||
endif ()
|
||||
|
||||
# Increase stack size on Musl. We need big stack for our recursive-descend parser.
|
||||
@ -521,7 +522,7 @@ include (cmake/find/curl.cmake)
|
||||
include (cmake/find/s3.cmake)
|
||||
include (cmake/find/blob_storage.cmake)
|
||||
include (cmake/find/base64.cmake)
|
||||
include (cmake/find/parquet.cmake) # uses protobuf
|
||||
include (cmake/find/parquet.cmake) # uses protobuf and thrift
|
||||
include (cmake/find/simdjson.cmake)
|
||||
include (cmake/find/fast_float.cmake)
|
||||
include (cmake/find/rapidjson.cmake)
|
||||
|
@ -25,8 +25,11 @@ endif ()
|
||||
|
||||
if (USE_DEBUG_HELPERS)
|
||||
get_target_property(MAGIC_ENUM_INCLUDE_DIR magic_enum INTERFACE_INCLUDE_DIRECTORIES)
|
||||
set (INCLUDE_DEBUG_HELPERS "-I\"${MAGIC_ENUM_INCLUDE_DIR}\" -include \"${ClickHouse_SOURCE_DIR}/base/base/iostream_debug_helpers.h\"")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${INCLUDE_DEBUG_HELPERS}")
|
||||
# CMake generator expression will do insane quoting when it encounters special character like quotes, spaces, etc.
|
||||
# Prefixing "SHELL:" will force it to use the original text.
|
||||
set (INCLUDE_DEBUG_HELPERS "SHELL:-I\"${MAGIC_ENUM_INCLUDE_DIR}\" -include \"${ClickHouse_SOURCE_DIR}/base/base/iostream_debug_helpers.h\"")
|
||||
# Use generator expression as we don't want to pollute CMAKE_CXX_FLAGS, which will interfere with CMake check system.
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${INCLUDE_DEBUG_HELPERS}>)
|
||||
endif ()
|
||||
|
||||
add_library (common ${SRCS})
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "strong_typedef.h"
|
||||
#include "extended_types.h"
|
||||
#include <base/strong_typedef.h>
|
||||
#include <base/extended_types.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <base/scope_guard.h>
|
||||
#include <base/logger_useful.h>
|
||||
#include <Common/MemoryTracker.h>
|
||||
#include <Common/LockMemoryExceptionInThread.h>
|
||||
|
||||
/// Same as SCOPE_EXIT() but block the MEMORY_LIMIT_EXCEEDED errors.
|
||||
///
|
||||
@ -12,8 +12,7 @@
|
||||
///
|
||||
/// NOTE: it should be used with caution.
|
||||
#define SCOPE_EXIT_MEMORY(...) SCOPE_EXIT( \
|
||||
MemoryTracker::LockExceptionInThread \
|
||||
lock_memory_tracker(VariableContext::Global); \
|
||||
LockMemoryExceptionInThread lock_memory_tracker(VariableContext::Global); \
|
||||
__VA_ARGS__; \
|
||||
)
|
||||
|
||||
@ -57,8 +56,7 @@
|
||||
#define SCOPE_EXIT_MEMORY_SAFE(...) SCOPE_EXIT( \
|
||||
try \
|
||||
{ \
|
||||
MemoryTracker::LockExceptionInThread \
|
||||
lock_memory_tracker(VariableContext::Global); \
|
||||
LockMemoryExceptionInThread lock_memory_tracker(VariableContext::Global); \
|
||||
__VA_ARGS__; \
|
||||
} \
|
||||
catch (...) \
|
||||
|
@ -125,11 +125,11 @@ public:
|
||||
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
|
||||
struct common_type<wide::integer<Bits, Signed>, wide::integer<Bits2, Signed2>>
|
||||
{
|
||||
using type = std::conditional_t < Bits == Bits2,
|
||||
wide::integer<
|
||||
Bits,
|
||||
std::conditional_t<(std::is_same_v<Signed, Signed2> && std::is_same_v<Signed2, signed>), signed, unsigned>>,
|
||||
std::conditional_t<Bits2<Bits, wide::integer<Bits, Signed>, wide::integer<Bits2, Signed2>>>;
|
||||
using type = std::conditional_t<Bits == Bits2,
|
||||
wide::integer<
|
||||
Bits,
|
||||
std::conditional_t<(std::is_same_v<Signed, Signed2> && std::is_same_v<Signed2, signed>), signed, unsigned>>,
|
||||
std::conditional_t<Bits2<Bits, wide::integer<Bits, Signed>, wide::integer<Bits2, Signed2>>>;
|
||||
};
|
||||
|
||||
template <size_t Bits, typename Signed, typename Arithmetic>
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include <Common/getExecutablePath.h>
|
||||
#include <Common/getHashOfLoadedBinary.h>
|
||||
#include <Common/Elf.h>
|
||||
#include <Common/setThreadName.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include <loggers/OwnFormattingChannel.h>
|
||||
|
@ -5,9 +5,11 @@
|
||||
#include <Poco/Util/AbstractConfiguration.h>
|
||||
#include "OwnFormattingChannel.h"
|
||||
#include "OwnPatternFormatter.h"
|
||||
#include "OwnSplitChannel.h"
|
||||
#include <Poco/ConsoleChannel.h>
|
||||
#include <Poco/Logger.h>
|
||||
#include <Poco/Net/RemoteSyslogChannel.h>
|
||||
#include <Interpreters/TextLog.h>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
@ -5,9 +5,12 @@
|
||||
#include <Poco/AutoPtr.h>
|
||||
#include <Poco/FileChannel.h>
|
||||
#include <Poco/Util/Application.h>
|
||||
#include <Interpreters/TextLog.h>
|
||||
#include "OwnSplitChannel.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class TextLog;
|
||||
}
|
||||
|
||||
namespace Poco::Util
|
||||
{
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <Poco/Message.h>
|
||||
#include <Common/CurrentThread.h>
|
||||
#include <Common/DNSResolver.h>
|
||||
#include <Common/setThreadName.h>
|
||||
#include <Common/LockMemoryExceptionInThread.h>
|
||||
#include <base/getThreadId.h>
|
||||
#include <Common/SensitiveDataMasker.h>
|
||||
#include <Common/IO.h>
|
||||
@ -57,7 +59,7 @@ void OwnSplitChannel::tryLogSplit(const Poco::Message & msg)
|
||||
/// but let's log it into the stderr at least.
|
||||
catch (...)
|
||||
{
|
||||
MemoryTracker::LockExceptionInThread lock_memory_tracker(VariableContext::Global);
|
||||
LockMemoryExceptionInThread lock_memory_tracker(VariableContext::Global);
|
||||
|
||||
const std::string & exception_message = getCurrentExceptionMessage(true);
|
||||
const std::string & message = msg.getText();
|
||||
|
@ -1,11 +1,16 @@
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <Poco/AutoPtr.h>
|
||||
#include <Poco/Channel.h>
|
||||
#include "ExtendedLogChannel.h"
|
||||
#include <Interpreters/TextLog.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class TextLog;
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
# NOTE: has nothing common with DBMS_TCP_PROTOCOL_VERSION,
|
||||
# only DBMS_TCP_PROTOCOL_VERSION should be incremented on protocol changes.
|
||||
SET(VERSION_REVISION 54458)
|
||||
SET(VERSION_REVISION 54459)
|
||||
SET(VERSION_MAJOR 22)
|
||||
SET(VERSION_MINOR 1)
|
||||
SET(VERSION_MINOR 2)
|
||||
SET(VERSION_PATCH 1)
|
||||
SET(VERSION_GITHASH 4cc45c1e15912ee300bca7cc8b8da2b888a70e2a)
|
||||
SET(VERSION_DESCRIBE v22.1.1.1-prestable)
|
||||
SET(VERSION_STRING 22.1.1.1)
|
||||
SET(VERSION_GITHASH dfe64a2789bbf51046bb6b5476f874f7b59d124c)
|
||||
SET(VERSION_DESCRIBE v22.2.1.1-prestable)
|
||||
SET(VERSION_STRING 22.2.1.1)
|
||||
# end of autochange
|
||||
|
@ -14,9 +14,9 @@ set (TOOLCHAIN_PATH "${CMAKE_CURRENT_LIST_DIR}/../../contrib/sysroot/linux-aarch
|
||||
|
||||
set (CMAKE_SYSROOT "${TOOLCHAIN_PATH}/aarch64-linux-gnu/libc")
|
||||
|
||||
set (CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_ASM_FLAGS_INIT "${CMAKE_ASM_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
|
||||
set (HAS_PRE_1970_EXITCODE "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
set (HAS_PRE_1970_EXITCODE__TRYRUN_OUTPUT "" CACHE STRING "Output from TRY_RUN" FORCE)
|
||||
|
@ -14,9 +14,9 @@ set (TOOLCHAIN_PATH "${CMAKE_CURRENT_LIST_DIR}/../../contrib/sysroot/linux-power
|
||||
|
||||
set (CMAKE_SYSROOT "${TOOLCHAIN_PATH}/powerpc64le-linux-gnu/libc")
|
||||
|
||||
set (CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_ASM_FLAGS_INIT "${CMAKE_ASM_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
|
||||
set (HAS_PRE_1970_EXITCODE "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
set (HAS_PRE_1970_EXITCODE__TRYRUN_OUTPUT "" CACHE STRING "Output from TRY_RUN" FORCE)
|
||||
|
@ -14,9 +14,9 @@ set (TOOLCHAIN_PATH "${CMAKE_CURRENT_LIST_DIR}/../../contrib/sysroot/linux-riscv
|
||||
|
||||
set (CMAKE_SYSROOT "${TOOLCHAIN_PATH}")
|
||||
|
||||
set (CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_ASM_FLAGS_INIT "${CMAKE_ASM_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
|
||||
set (CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=bfd")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=bfd")
|
||||
|
@ -14,9 +14,9 @@ set (TOOLCHAIN_PATH "${CMAKE_CURRENT_LIST_DIR}/../../contrib/sysroot/linux-x86_6
|
||||
|
||||
set (CMAKE_SYSROOT "${TOOLCHAIN_PATH}")
|
||||
|
||||
set (CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_ASM_FLAGS_INIT "${CMAKE_ASM_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} --gcc-toolchain=${TOOLCHAIN_PATH}")
|
||||
|
||||
set (HAS_PRE_1970_EXITCODE "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
set (HAS_PRE_1970_EXITCODE__TRYRUN_OUTPUT "" CACHE STRING "Output from TRY_RUN" FORCE)
|
||||
|
@ -345,7 +345,7 @@ if (USE_INTERNAL_PROTOBUF_LIBRARY)
|
||||
add_dependencies(${ARROW_LIBRARY} protoc)
|
||||
endif ()
|
||||
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PUBLIC "${ClickHouse_SOURCE_DIR}/contrib/arrow/cpp/src")
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PUBLIC ${ARROW_SRC_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/cpp/src")
|
||||
target_link_libraries(${ARROW_LIBRARY} PRIVATE ${DOUBLE_CONVERSION_LIBRARIES} ${Protobuf_LIBRARY})
|
||||
target_link_libraries(${ARROW_LIBRARY} PRIVATE lz4)
|
||||
@ -360,16 +360,15 @@ if (ARROW_WITH_ZSTD)
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM BEFORE PRIVATE ${ZLIB_INCLUDE_DIR})
|
||||
endif ()
|
||||
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${ORC_INCLUDE_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${ORC_SOURCE_SRC_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${ORC_SOURCE_WRAP_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${GOOGLE_PROTOBUF_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${ORC_BUILD_SRC_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${ORC_BUILD_INCLUDE_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${ORC_ADDITION_SOURCE_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${ARROW_SRC_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${FLATBUFFERS_INCLUDE_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} PRIVATE SYSTEM ${HDFS_INCLUDE_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PRIVATE ${ORC_INCLUDE_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PRIVATE ${ORC_SOURCE_SRC_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PRIVATE ${ORC_SOURCE_WRAP_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PRIVATE ${GOOGLE_PROTOBUF_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PRIVATE ${ORC_BUILD_SRC_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PRIVATE ${ORC_BUILD_INCLUDE_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PRIVATE ${ORC_ADDITION_SOURCE_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PRIVATE ${FLATBUFFERS_INCLUDE_DIR})
|
||||
target_include_directories(${ARROW_LIBRARY} SYSTEM PRIVATE ${HDFS_INCLUDE_DIR})
|
||||
|
||||
# === parquet
|
||||
|
||||
@ -414,50 +413,6 @@ set(PARQUET_SRCS
|
||||
#list(TRANSFORM PARQUET_SRCS PREPEND "${LIBRARY_DIR}/") # cmake 3.12
|
||||
add_library(${PARQUET_LIBRARY} ${PARQUET_SRCS})
|
||||
target_include_directories(${PARQUET_LIBRARY} SYSTEM PUBLIC "${ClickHouse_SOURCE_DIR}/contrib/arrow/cpp/src" "${CMAKE_CURRENT_SOURCE_DIR}/cpp/src" PRIVATE ${OPENSSL_INCLUDE_DIR})
|
||||
# include("${ClickHouse_SOURCE_DIR}/contrib/thrift/build/cmake/ConfigureChecks.cmake") # makes config.h
|
||||
|
||||
set (HAVE_ARPA_INET_H 1)
|
||||
set (HAVE_FCNTL_H 1)
|
||||
set (HAVE_GETOPT_H 1)
|
||||
set (HAVE_INTTYPES_H 1)
|
||||
set (HAVE_NETDB_H 1)
|
||||
set (HAVE_NETINET_IN_H 1)
|
||||
set (HAVE_SIGNAL_H 1)
|
||||
set (HAVE_STDINT_H 1)
|
||||
set (HAVE_UNISTD_H 1)
|
||||
set (HAVE_PTHREAD_H 1)
|
||||
set (HAVE_SYS_IOCTL_H 1)
|
||||
set (HAVE_SYS_PARAM_H 1)
|
||||
set (HAVE_SYS_RESOURCE_H 1)
|
||||
set (HAVE_SYS_SOCKET_H 1)
|
||||
set (HAVE_SYS_STAT_H 1)
|
||||
set (HAVE_SYS_TIME_H 1)
|
||||
set (HAVE_SYS_UN_H 1)
|
||||
set (HAVE_POLL_H 1)
|
||||
set (HAVE_SYS_POLL_H 1)
|
||||
set (HAVE_SYS_SELECT_H 1)
|
||||
set (HAVE_SCHED_H 1)
|
||||
set (HAVE_STRING_H 1)
|
||||
set (HAVE_STRINGS_H 1)
|
||||
set (HAVE_GETHOSTBYNAME 1)
|
||||
set (HAVE_STRERROR_R 1)
|
||||
set (HAVE_SCHED_GET_PRIORITY_MAX 1)
|
||||
set (HAVE_SCHED_GET_PRIORITY_MIN 1)
|
||||
|
||||
if (OS_LINUX AND NOT USE_MUSL)
|
||||
set (STRERROR_R_CHAR_P 1)
|
||||
endif ()
|
||||
|
||||
#set(PACKAGE ${PACKAGE_NAME})
|
||||
#set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||
#set(VERSION ${thrift_VERSION})
|
||||
|
||||
# generate a config.h file
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/thrift/config.h")
|
||||
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
|
||||
target_link_libraries(${PARQUET_LIBRARY} PUBLIC ${ARROW_LIBRARY} PRIVATE ${THRIFT_LIBRARY} boost::headers_only boost::regex ${OPENSSL_LIBRARIES})
|
||||
|
||||
if (SANITIZE STREQUAL "undefined")
|
||||
|
@ -81,7 +81,7 @@ set(S3_INCLUDES
|
||||
)
|
||||
|
||||
add_library(aws_s3_checksums ${AWS_CHECKSUMS_SOURCES})
|
||||
target_include_directories(aws_s3_checksums PUBLIC "${AWS_CHECKSUMS_LIBRARY_DIR}/include/")
|
||||
target_include_directories(aws_s3_checksums SYSTEM PUBLIC "${AWS_CHECKSUMS_LIBRARY_DIR}/include/")
|
||||
if(CMAKE_BUILD_TYPE_UC STREQUAL "DEBUG")
|
||||
target_compile_definitions(aws_s3_checksums PRIVATE "-DDEBUG_BUILD")
|
||||
endif()
|
||||
@ -93,7 +93,7 @@ add_library(aws_s3 ${S3_UNIFIED_SRC})
|
||||
target_compile_definitions(aws_s3 PUBLIC "AWS_SDK_VERSION_MAJOR=1")
|
||||
target_compile_definitions(aws_s3 PUBLIC "AWS_SDK_VERSION_MINOR=7")
|
||||
target_compile_definitions(aws_s3 PUBLIC "AWS_SDK_VERSION_PATCH=231")
|
||||
target_include_directories(aws_s3 PUBLIC ${S3_INCLUDES})
|
||||
target_include_directories(aws_s3 SYSTEM PUBLIC ${S3_INCLUDES})
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
target_compile_definitions(aws_s3 PUBLIC -DENABLE_OPENSSL_ENCRYPTION)
|
||||
|
@ -131,8 +131,6 @@ if(BUILD_SHARED_LIBS)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
endif()
|
||||
|
||||
include_directories("${BORINGSSL_SOURCE_DIR}/include")
|
||||
|
||||
set(
|
||||
CRYPTO_ios_aarch64_SOURCES
|
||||
|
||||
|
@ -57,7 +57,7 @@ if (NOT EXTERNAL_CCTZ_LIBRARY_FOUND OR NOT EXTERNAL_CCTZ_LIBRARY_WORKS)
|
||||
)
|
||||
|
||||
add_library (cctz ${SRCS})
|
||||
target_include_directories (cctz PUBLIC "${LIBRARY_DIR}/include")
|
||||
target_include_directories (cctz SYSTEM PUBLIC "${LIBRARY_DIR}/include")
|
||||
|
||||
if (OS_FREEBSD)
|
||||
# yes, need linux, because bsd check inside linux in time_zone_libc.cc:24
|
||||
|
@ -4,5 +4,5 @@ add_library(cityhash
|
||||
include/city.h
|
||||
src/config.h)
|
||||
|
||||
target_include_directories(cityhash BEFORE PUBLIC include)
|
||||
target_include_directories(cityhash PRIVATE src)
|
||||
target_include_directories(cityhash SYSTEM BEFORE PUBLIC include)
|
||||
target_include_directories(cityhash SYSTEM PRIVATE src)
|
||||
|
@ -1,2 +1,2 @@
|
||||
add_library(consistent-hashing consistent_hashing.cpp popcount.cpp)
|
||||
target_include_directories(consistent-hashing PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(consistent-hashing SYSTEM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
@ -153,7 +153,7 @@ target_compile_definitions (curl PRIVATE
|
||||
libcurl_EXPORTS
|
||||
OS="${CMAKE_SYSTEM_NAME}"
|
||||
)
|
||||
target_include_directories (curl PUBLIC
|
||||
target_include_directories (curl SYSTEM PUBLIC
|
||||
"${LIBRARY_DIR}/include"
|
||||
"${LIBRARY_DIR}/lib"
|
||||
. # curl_config.h
|
||||
|
@ -6,4 +6,4 @@ set(SRCS
|
||||
)
|
||||
|
||||
add_library(lemmagen STATIC ${SRCS})
|
||||
target_include_directories(lemmagen PUBLIC "${LEMMAGEN_INCLUDE_DIR}")
|
||||
target_include_directories(lemmagen SYSTEM PUBLIC "${LEMMAGEN_INCLUDE_DIR}")
|
||||
|
@ -55,8 +55,8 @@ set(SRCS
|
||||
|
||||
add_library(libpq ${SRCS})
|
||||
|
||||
target_include_directories (libpq PUBLIC ${LIBPQ_SOURCE_DIR})
|
||||
target_include_directories (libpq PUBLIC "${LIBPQ_SOURCE_DIR}/include")
|
||||
target_include_directories (libpq PRIVATE "${LIBPQ_SOURCE_DIR}/configs")
|
||||
target_include_directories (libpq SYSTEM PUBLIC ${LIBPQ_SOURCE_DIR})
|
||||
target_include_directories (libpq SYSTEM PUBLIC "${LIBPQ_SOURCE_DIR}/include")
|
||||
target_include_directories (libpq SYSTEM PRIVATE "${LIBPQ_SOURCE_DIR}/configs")
|
||||
|
||||
target_link_libraries (libpq PRIVATE ssl)
|
||||
|
2
contrib/libpqxx
vendored
2
contrib/libpqxx
vendored
@ -1 +1 @@
|
||||
Subproject commit 63e20f9485b8cbeabf99008123248fc9f033e766
|
||||
Subproject commit a4e834839270a8c1f7ff1db351ba85afced3f0e2
|
@ -68,12 +68,3 @@ add_library(libpqxx ${SRCS} ${HDRS})
|
||||
target_link_libraries(libpqxx PUBLIC ${LIBPQ_LIBRARY})
|
||||
target_include_directories (libpqxx SYSTEM PRIVATE "${LIBRARY_DIR}/include")
|
||||
|
||||
# crutch
|
||||
set(CM_CONFIG_H_IN "${LIBRARY_DIR}/include/pqxx/config.h.in")
|
||||
set(CM_CONFIG_PUB "${LIBRARY_DIR}/include/pqxx/config-public-compiler.h")
|
||||
set(CM_CONFIG_INT "${LIBRARY_DIR}/include/pqxx/config-internal-compiler.h")
|
||||
set(CM_CONFIG_PQ "${LIBRARY_DIR}/include/pqxx/config-internal-libpq.h")
|
||||
|
||||
configure_file("${CM_CONFIG_H_IN}" "${CM_CONFIG_INT}" @ONLY)
|
||||
configure_file("${CM_CONFIG_H_IN}" "${CM_CONFIG_PUB}" @ONLY)
|
||||
configure_file("${CM_CONFIG_H_IN}" "${CM_CONFIG_PQ}" @ONLY)
|
||||
|
@ -28,4 +28,4 @@ endforeach ()
|
||||
|
||||
# all the sources parsed. Now just add the lib
|
||||
add_library ( stemmer STATIC ${_SOURCES} ${_HEADERS} )
|
||||
target_include_directories (stemmer PUBLIC "${STEMMER_INCLUDE_DIR}")
|
||||
target_include_directories (stemmer SYSTEM PUBLIC "${STEMMER_INCLUDE_DIR}")
|
||||
|
@ -1,3 +1,3 @@
|
||||
set (LIBRARY_DIR "${ClickHouse_SOURCE_DIR}/contrib/magic_enum")
|
||||
add_library (magic_enum INTERFACE)
|
||||
target_include_directories(magic_enum INTERFACE ${LIBRARY_DIR}/include)
|
||||
target_include_directories(magic_enum SYSTEM INTERFACE ${LIBRARY_DIR}/include)
|
||||
|
@ -40,5 +40,5 @@ target_sources(snappy
|
||||
"${SOURCE_DIR}/snappy-stubs-internal.cc"
|
||||
"${SOURCE_DIR}/snappy.cc")
|
||||
|
||||
target_include_directories(snappy PUBLIC ${SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(snappy SYSTEM PUBLIC ${SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_compile_definitions(snappy PRIVATE -DHAVE_CONFIG_H)
|
||||
|
@ -1,4 +1,3 @@
|
||||
# === thrift
|
||||
set(LIBRARY_DIR "${ClickHouse_SOURCE_DIR}/contrib/thrift/lib/cpp")
|
||||
set(thriftcpp_SOURCES
|
||||
"${LIBRARY_DIR}/src/thrift/TApplicationException.cpp"
|
||||
@ -42,6 +41,47 @@ set(thriftcpp_threads_SOURCES
|
||||
|
||||
include("${ClickHouse_SOURCE_DIR}/contrib/thrift/build/cmake/ConfigureChecks.cmake") # makes config.h
|
||||
|
||||
set (HAVE_ARPA_INET_H 1)
|
||||
set (HAVE_FCNTL_H 1)
|
||||
set (HAVE_GETOPT_H 1)
|
||||
set (HAVE_INTTYPES_H 1)
|
||||
set (HAVE_NETDB_H 1)
|
||||
set (HAVE_NETINET_IN_H 1)
|
||||
set (HAVE_SIGNAL_H 1)
|
||||
set (HAVE_STDINT_H 1)
|
||||
set (HAVE_UNISTD_H 1)
|
||||
set (HAVE_PTHREAD_H 1)
|
||||
set (HAVE_SYS_IOCTL_H 1)
|
||||
set (HAVE_SYS_PARAM_H 1)
|
||||
set (HAVE_SYS_RESOURCE_H 1)
|
||||
set (HAVE_SYS_SOCKET_H 1)
|
||||
set (HAVE_SYS_STAT_H 1)
|
||||
set (HAVE_SYS_TIME_H 1)
|
||||
set (HAVE_SYS_UN_H 1)
|
||||
set (HAVE_POLL_H 1)
|
||||
set (HAVE_SYS_POLL_H 1)
|
||||
set (HAVE_SYS_SELECT_H 1)
|
||||
set (HAVE_SCHED_H 1)
|
||||
set (HAVE_STRING_H 1)
|
||||
set (HAVE_STRINGS_H 1)
|
||||
set (HAVE_GETHOSTBYNAME 1)
|
||||
set (HAVE_STRERROR_R 1)
|
||||
set (HAVE_SCHED_GET_PRIORITY_MAX 1)
|
||||
set (HAVE_SCHED_GET_PRIORITY_MIN 1)
|
||||
|
||||
if (OS_LINUX AND NOT USE_MUSL)
|
||||
set (STRERROR_R_CHAR_P 1)
|
||||
endif ()
|
||||
|
||||
#set(PACKAGE ${PACKAGE_NAME})
|
||||
#set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||
#set(VERSION ${thrift_VERSION})
|
||||
|
||||
# generate a config.h file
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/thrift/config.h")
|
||||
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
add_library(${THRIFT_LIBRARY} ${thriftcpp_SOURCES} ${thriftcpp_threads_SOURCES})
|
||||
target_include_directories(${THRIFT_LIBRARY} SYSTEM PUBLIC "${THRIFT_INCLUDE_DIR}" ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_link_libraries (${THRIFT_LIBRARY} PUBLIC boost::headers_only)
|
||||
|
@ -23,6 +23,7 @@ set (SRCS_LTDL
|
||||
add_library (ltdl ${SRCS_LTDL})
|
||||
|
||||
target_include_directories(ltdl
|
||||
SYSTEM
|
||||
PRIVATE
|
||||
linux_x86_64/libltdl
|
||||
PUBLIC
|
||||
@ -276,6 +277,7 @@ target_link_libraries (unixodbc PRIVATE ltdl)
|
||||
# SYSTEM_FILE_PATH was changed to /etc
|
||||
|
||||
target_include_directories (unixodbc
|
||||
SYSTEM
|
||||
PRIVATE
|
||||
linux_x86_64/private
|
||||
PUBLIC
|
||||
|
@ -10,4 +10,4 @@ add_library(wnb ${SRCS})
|
||||
|
||||
target_link_libraries(wnb PRIVATE boost::headers_only boost::graph)
|
||||
|
||||
target_include_directories(wnb PUBLIC "${LIBRARY_DIR}")
|
||||
target_include_directories(wnb SYSTEM PUBLIC "${LIBRARY_DIR}")
|
||||
|
@ -241,7 +241,7 @@ add_library(liblzma
|
||||
${SRC_DIR}/src/liblzma/simple/x86.c
|
||||
)
|
||||
|
||||
target_include_directories(liblzma PRIVATE
|
||||
target_include_directories(liblzma SYSTEM PUBLIC
|
||||
${SRC_DIR}/src/liblzma/api
|
||||
${SRC_DIR}/src/liblzma/common
|
||||
${SRC_DIR}/src/liblzma/check
|
||||
|
@ -158,4 +158,4 @@ if (ARCH_AMD64 OR ARCH_AARCH64)
|
||||
target_compile_definitions (zlib PUBLIC X86_64 UNALIGNED_OK)
|
||||
endif ()
|
||||
|
||||
target_include_directories(zlib PUBLIC ${SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(zlib SYSTEM PUBLIC ${SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
7
debian/.gitignore
vendored
7
debian/.gitignore
vendored
@ -2,9 +2,16 @@ control
|
||||
copyright
|
||||
tmp/
|
||||
clickhouse-benchmark/
|
||||
clickhouse-client.docs
|
||||
clickhouse-client/
|
||||
clickhouse-common-static-dbg/
|
||||
clickhouse-common-static.docs
|
||||
clickhouse-common-static/
|
||||
clickhouse-server-base/
|
||||
clickhouse-server-common/
|
||||
clickhouse-server/
|
||||
clickhouse-test/
|
||||
debhelper-build-stamp
|
||||
files
|
||||
*.debhelper.log
|
||||
*.debhelper
|
||||
|
6
debian/.pbuilderrc
vendored
6
debian/.pbuilderrc
vendored
@ -104,8 +104,7 @@ ALLOWUNTRUSTED=${SET_ALLOWUNTRUSTED:=${ALLOWUNTRUSTED}}
|
||||
if $(echo ${DEBIAN_SUITES[@]} | grep -q $DIST); then
|
||||
# Debian configuration
|
||||
OSNAME=debian
|
||||
#MIRRORSITE=${SET_MIRRORSITE="http://deb.debian.org/$OSNAME/"}
|
||||
MIRRORSITE=${SET_MIRRORSITE="http://mirror.yandex.ru/$OSNAME/"}
|
||||
MIRRORSITE=${SET_MIRRORSITE="http://deb.debian.org/$OSNAME/"}
|
||||
COMPONENTS="main contrib non-free"
|
||||
if $(echo "$STABLE_CODENAME stable" | grep -q $DIST); then
|
||||
OTHERMIRROR="$OTHERMIRROR | deb $MIRRORSITE $STABLE_BACKPORTS_SUITE $COMPONENTS"
|
||||
@ -125,8 +124,7 @@ elif $(echo ${UBUNTU_SUITES[@]} | grep -q $DIST); then
|
||||
OSNAME=ubuntu
|
||||
|
||||
if [[ "$ARCH" == "amd64" || "$ARCH" == "i386" ]]; then
|
||||
#MIRRORSITE=${SET_MIRRORSITE="http://archive.ubuntu.com/$OSNAME/"}
|
||||
MIRRORSITE=${SET_MIRRORSITE="http://mirror.yandex.ru/$OSNAME/"}
|
||||
MIRRORSITE=${SET_MIRRORSITE="http://archive.ubuntu.com/$OSNAME/"}
|
||||
else
|
||||
MIRRORSITE=${SET_MIRRORSITE="http://ports.ubuntu.com/ubuntu-ports/"}
|
||||
fi
|
||||
|
2
debian/clickhouse-server.init
vendored
2
debian/clickhouse-server.init
vendored
@ -5,7 +5,7 @@
|
||||
# Default-Stop: 0 1 6
|
||||
# Should-Start: $time $network
|
||||
# Should-Stop: $network
|
||||
# Short-Description: Yandex clickhouse-server daemon
|
||||
# Short-Description: clickhouse-server daemon
|
||||
### END INIT INFO
|
||||
#
|
||||
# NOTES:
|
||||
|
6
debian/control
vendored
6
debian/control
vendored
@ -18,7 +18,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, clickhouse-common-static (= ${binar
|
||||
Replaces: clickhouse-compressor
|
||||
Conflicts: clickhouse-compressor
|
||||
Description: Client binary for ClickHouse
|
||||
Yandex ClickHouse is a column-oriented database management system
|
||||
ClickHouse is a column-oriented database management system
|
||||
that allows generating analytical data reports in real time.
|
||||
.
|
||||
This package provides clickhouse-client , clickhouse-local and clickhouse-benchmark
|
||||
@ -30,7 +30,7 @@ Suggests: clickhouse-common-static-dbg
|
||||
Replaces: clickhouse-common, clickhouse-server-base
|
||||
Provides: clickhouse-common, clickhouse-server-base
|
||||
Description: Common files for ClickHouse
|
||||
Yandex ClickHouse is a column-oriented database management system
|
||||
ClickHouse is a column-oriented database management system
|
||||
that allows generating analytical data reports in real time.
|
||||
.
|
||||
This package provides common files for both clickhouse server and client
|
||||
@ -42,7 +42,7 @@ Recommends: libcap2-bin
|
||||
Replaces: clickhouse-server-common, clickhouse-server-base
|
||||
Provides: clickhouse-server-common
|
||||
Description: Server binary for ClickHouse
|
||||
Yandex ClickHouse is a column-oriented database management system
|
||||
ClickHouse is a column-oriented database management system
|
||||
that allows generating analytical data reports in real time.
|
||||
.
|
||||
This package provides clickhouse common configuration files
|
||||
|
3
debian/rules
vendored
3
debian/rules
vendored
@ -96,6 +96,9 @@ ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
|
||||
cd $(BUILDDIR) && ctest -j$(THREADS_COUNT) -V
|
||||
endif
|
||||
|
||||
# Disable config.guess and config.sub update
|
||||
override_dh_update_autotools_config:
|
||||
|
||||
override_dh_clean:
|
||||
rm -rf debian/copyright debian/clickhouse-client.docs debian/clickhouse-common-static.docs
|
||||
dh_clean # -X contrib
|
||||
|
@ -1,5 +1,5 @@
|
||||
# rebuild in #33610
|
||||
# docker build -t clickhouse/docs-build .
|
||||
# docker build -t clickhouse/docs-builder .
|
||||
FROM ubuntu:20.04
|
||||
|
||||
# ARG for quick switch to a given ubuntu mirror
|
||||
@ -10,8 +10,6 @@ ENV LANG=C.UTF-8
|
||||
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends \
|
||||
python3-setuptools \
|
||||
virtualenv \
|
||||
wget \
|
||||
bash \
|
||||
python \
|
||||
|
@ -2,6 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
cd $REPO_PATH/docs/tools
|
||||
rm -rf venv
|
||||
mkdir venv
|
||||
virtualenv -p $(which python3) venv
|
||||
source venv/bin/activate
|
||||
|
@ -30,10 +30,10 @@ def pull_image(image_name):
|
||||
|
||||
def build_image(image_name, filepath):
|
||||
context = os.path.dirname(filepath)
|
||||
build_cmd = "docker build --network=host -t {} -f {} {}".format(image_name, filepath, context)
|
||||
logging.info("Will build image with cmd: '{}'".format(build_cmd))
|
||||
subprocess.check_call(
|
||||
"docker build --network=host -t {} -f {} {}".format(
|
||||
image_name, filepath, context
|
||||
),
|
||||
build_cmd,
|
||||
shell=True,
|
||||
)
|
||||
|
||||
@ -61,7 +61,6 @@ def run_docker_image_with_env(image_name, output, env_variables, ch_root, ccache
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
|
||||
def parse_env_variables(build_type, compiler, sanitizer, package_type, image_type, cache, distcc_hosts, split_binary, clang_tidy, version, author, official, alien_pkgs, with_coverage, with_binaries):
|
||||
CLANG_PREFIX = "clang"
|
||||
DARWIN_SUFFIX = "-darwin"
|
||||
DARWIN_ARM_SUFFIX = "-darwin-aarch64"
|
||||
ARM_SUFFIX = "-aarch64"
|
||||
@ -71,13 +70,11 @@ def parse_env_variables(build_type, compiler, sanitizer, package_type, image_typ
|
||||
result = []
|
||||
cmake_flags = ['$CMAKE_FLAGS']
|
||||
|
||||
is_clang = compiler.startswith(CLANG_PREFIX)
|
||||
is_cross_darwin = compiler.endswith(DARWIN_SUFFIX)
|
||||
is_cross_darwin_arm = compiler.endswith(DARWIN_ARM_SUFFIX)
|
||||
is_cross_arm = compiler.endswith(ARM_SUFFIX)
|
||||
is_cross_ppc = compiler.endswith(PPC_SUFFIX)
|
||||
is_cross_freebsd = compiler.endswith(FREEBSD_SUFFIX)
|
||||
is_cross_compile = is_cross_darwin or is_cross_darwin_arm or is_cross_arm or is_cross_freebsd or is_cross_ppc
|
||||
|
||||
if is_cross_darwin:
|
||||
cc = compiler[:-len(DARWIN_SUFFIX)]
|
||||
|
@ -6,7 +6,6 @@ RUN sed -i "s|http://archive.ubuntu.com|$apt_archive|g" /etc/apt/sources.list
|
||||
|
||||
ARG repository="deb https://repo.clickhouse.com/deb/stable/ main/"
|
||||
ARG version=22.1.1.*
|
||||
ARG gosu_ver=1.10
|
||||
|
||||
# set non-empty deb_location_url url to create a docker image
|
||||
# from debs created by CI build, for example:
|
||||
@ -30,6 +29,23 @@ ARG DEBIAN_FRONTEND=noninteractive
|
||||
# installed to prevent picking those uid / gid by some unrelated software.
|
||||
# The same uid / gid (101) is used both for alpine and ubuntu.
|
||||
|
||||
# To drop privileges, we need 'su' command, that simply changes uid and gid.
|
||||
# In fact, the 'su' command from Linux is not so simple, due to inherent vulnerability in Linux:
|
||||
# https://ruderich.org/simon/notes/su-sudo-from-root-tty-hijacking
|
||||
# It has to mitigate this drawback of Linux, and to do this, 'su' command is creating it's own pseudo-terminal
|
||||
# and forwarding commands. Due to some ridiculous curcumstances, it does not work in Docker (or it does)
|
||||
# and for these reasons people are using alternatives to the 'su' command in Docker,
|
||||
# that don't mess with the terminal, don't care about closing the opened files, etc...
|
||||
# but can only be safe to drop privileges inside Docker.
|
||||
# The question - what implementation of 'su' command to use.
|
||||
# It should be a simple script doing about just two syscalls.
|
||||
# Some people tend to use 'gosu' tool that is written in Go.
|
||||
# It is not used for several reasons:
|
||||
# 1. Dependency on some foreign code in yet another programming language - does not sound alright.
|
||||
# 2. Anselmo D. Adams suggested not to use it due to false positive alarms in some undisclosed security scanners.
|
||||
|
||||
COPY su-exec.c /su-exec.c
|
||||
|
||||
RUN groupadd -r clickhouse --gid=101 \
|
||||
&& useradd -r -g clickhouse --uid=101 --home-dir=/var/lib/clickhouse --shell=/bin/bash clickhouse \
|
||||
&& apt-get update \
|
||||
@ -68,8 +84,12 @@ RUN groupadd -r clickhouse --gid=101 \
|
||||
clickhouse-client=$version \
|
||||
clickhouse-server=$version ; \
|
||||
fi \
|
||||
&& wget --progress=bar:force:noscroll "https://github.com/tianon/gosu/releases/download/$gosu_ver/gosu-$(dpkg --print-architecture)" -O /bin/gosu \
|
||||
&& chmod +x /bin/gosu \
|
||||
&& apt-get install -y --no-install-recommends tcc libc-dev && \
|
||||
tcc /su-exec.c -o /bin/su-exec && \
|
||||
chown root:root /bin/su-exec && \
|
||||
chmod 0755 /bin/su-exec && \
|
||||
rm /su-exec.c && \
|
||||
apt-get purge -y --auto-remove tcc libc-dev libc-dev-bin libc6-dev linux-libc-dev \
|
||||
&& clickhouse-local -q 'SELECT * FROM system.build_options' \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
@ -100,4 +120,3 @@ VOLUME /var/lib/clickhouse
|
||||
ENV CLICKHOUSE_CONFIG /etc/clickhouse-server/config.xml
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
# Middle steps are performed by the bash script.
|
||||
|
||||
FROM ubuntu:18.04 as clickhouse-server-base
|
||||
ARG gosu_ver=1.10
|
||||
ARG gosu_ver=1.14
|
||||
|
||||
VOLUME /packages/
|
||||
|
||||
|
138
docker/server/su-exec.c
Normal file
138
docker/server/su-exec.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
|
||||
https://github.com/ncopa/su-exec
|
||||
The file is copy-pasted verbatim to avoid supply chain attacks.
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 ncopa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
/* set user and group id and exec */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static char *argv0;
|
||||
|
||||
static void usage(int exitcode)
|
||||
{
|
||||
printf("Usage: %s user-spec command [args]\n", argv0);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *user, *group, **cmdargv;
|
||||
char *end;
|
||||
|
||||
uid_t uid = getuid();
|
||||
gid_t gid = getgid();
|
||||
|
||||
argv0 = argv[0];
|
||||
if (argc < 3)
|
||||
usage(0);
|
||||
|
||||
user = argv[1];
|
||||
group = strchr(user, ':');
|
||||
if (group)
|
||||
*group++ = '\0';
|
||||
|
||||
cmdargv = &argv[2];
|
||||
|
||||
struct passwd *pw = NULL;
|
||||
if (user[0] != '\0') {
|
||||
uid_t nuid = strtol(user, &end, 10);
|
||||
if (*end == '\0')
|
||||
uid = nuid;
|
||||
else {
|
||||
pw = getpwnam(user);
|
||||
if (pw == NULL)
|
||||
err(1, "getpwnam(%s)", user);
|
||||
}
|
||||
}
|
||||
if (pw == NULL) {
|
||||
pw = getpwuid(uid);
|
||||
}
|
||||
if (pw != NULL) {
|
||||
uid = pw->pw_uid;
|
||||
gid = pw->pw_gid;
|
||||
}
|
||||
|
||||
setenv("HOME", pw != NULL ? pw->pw_dir : "/", 1);
|
||||
|
||||
if (group && group[0] != '\0') {
|
||||
/* group was specified, ignore grouplist for setgroups later */
|
||||
pw = NULL;
|
||||
|
||||
gid_t ngid = strtol(group, &end, 10);
|
||||
if (*end == '\0')
|
||||
gid = ngid;
|
||||
else {
|
||||
struct group *gr = getgrnam(group);
|
||||
if (gr == NULL)
|
||||
err(1, "getgrnam(%s)", group);
|
||||
gid = gr->gr_gid;
|
||||
}
|
||||
}
|
||||
|
||||
if (pw == NULL) {
|
||||
if (setgroups(1, &gid) < 0)
|
||||
err(1, "setgroups(%i)", gid);
|
||||
} else {
|
||||
int ngroups = 0;
|
||||
gid_t *glist = NULL;
|
||||
|
||||
while (1) {
|
||||
int r = getgrouplist(pw->pw_name, gid, glist, &ngroups);
|
||||
|
||||
if (r >= 0) {
|
||||
if (setgroups(ngroups, glist) < 0)
|
||||
err(1, "setgroups");
|
||||
break;
|
||||
}
|
||||
|
||||
glist = realloc(glist, ngroups * sizeof(gid_t));
|
||||
if (glist == NULL)
|
||||
err(1, "malloc");
|
||||
}
|
||||
}
|
||||
|
||||
if (setgid(gid) < 0)
|
||||
err(1, "setgid(%i)", gid);
|
||||
|
||||
if (setuid(uid) < 0)
|
||||
err(1, "setuid(%i)", uid);
|
||||
|
||||
execvp(cmdargv[0], cmdargv);
|
||||
err(1, "%s", cmdargv[0]);
|
||||
|
||||
return 1;
|
||||
}
|
@ -14,4 +14,4 @@ services:
|
||||
image: mongo:5.0
|
||||
restart: always
|
||||
ports:
|
||||
- "27018:27017"
|
||||
- ${MONGO_NO_CRED_EXTERNAL_PORT}:${MONGO_NO_CRED_INTERNAL_PORT}
|
||||
|
@ -6,8 +6,8 @@ Minimal ClickHouse build example:
|
||||
|
||||
```bash
|
||||
cmake .. \
|
||||
-DCMAKE_C_COMPILER=$(which clang-11) \
|
||||
-DCMAKE_CXX_COMPILER=$(which clang++-11) \
|
||||
-DCMAKE_C_COMPILER=$(which clang-13) \
|
||||
-DCMAKE_CXX_COMPILER=$(which clang++-13) \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DENABLE_CLICKHOUSE_ALL=OFF \
|
||||
-DENABLE_CLICKHOUSE_SERVER=ON \
|
||||
|
@ -5,7 +5,7 @@ toc_title: Build on Mac OS X
|
||||
|
||||
# How to Build ClickHouse on Mac OS X {#how-to-build-clickhouse-on-mac-os-x}
|
||||
|
||||
!!! info "You don't have to build ClickHouse yourself!"
|
||||
!!! info "You don't have to build ClickHouse yourself"
|
||||
You can install pre-built ClickHouse as described in [Quick Start](https://clickhouse.com/#quick-start).
|
||||
Follow `macOS (Intel)` or `macOS (Apple silicon)` installation instructions.
|
||||
|
||||
|
@ -26,7 +26,7 @@ ENGINE = MaterializedPostgreSQL('host:port', 'database', 'user', 'password') [SE
|
||||
## Example of Use {#example-of-use}
|
||||
|
||||
``` sql
|
||||
CREATE DATABASE postgresql;
|
||||
CREATE DATABASE postgres_db
|
||||
ENGINE = MaterializedPostgreSQL('postgres1:5432', 'postgres_database', 'postgres_user', 'postgres_password');
|
||||
|
||||
SHOW TABLES FROM postgres_db;
|
||||
|
@ -153,6 +153,7 @@ toc_title: Adopters
|
||||
| <a href="https://www.spotify.com" class="favicon">Spotify</a> | Music | Experimentation | — | — | [Slides, July 2018](https://www.slideshare.net/glebus/using-clickhouse-for-experimentation-104247173) |
|
||||
| <a href="https://www.staffcop.ru/" class="favicon">Staffcop</a> | Information Security | Main Product | — | — | [Official website, Documentation](https://www.staffcop.ru/sce43) |
|
||||
| <a href="https://www.suning.com/" class="favicon">Suning</a> | E-Commerce | User behaviour analytics | — | — | [Blog article](https://www.sohu.com/a/434152235_411876) |
|
||||
| <a href="https://superwall.me/" class="favicon">Superwall</a> | Monetization Tooling | Main product | — | — | [Word of mouth, Jan 2022](https://github.com/ClickHouse/ClickHouse/pull/33573) |
|
||||
| <a href="https://www.teralytics.net/" class="favicon">Teralytics</a> | Mobility | Analytics | — | — | [Tech blog](https://www.teralytics.net/knowledge-hub/visualizing-mobility-data-the-scalability-challenge) |
|
||||
| <a href="https://www.tencent.com" class="favicon">Tencent</a> | Big Data | Data processing | — | — | [Slides in Chinese, October 2018](https://github.com/ClickHouse/clickhouse-presentations/blob/master/meetup19/5.%20ClickHouse大数据集群应用_李俊飞腾讯网媒事业部.pdf) |
|
||||
| <a href="https://www.tencent.com" class="favicon">Tencent</a> | Messaging | Logging | — | — | [Talk in Chinese, November 2019](https://youtu.be/T-iVQRuw-QY?t=5050) |
|
||||
|
@ -36,7 +36,8 @@ Other common parameters are inherited from the ClickHouse server config (`listen
|
||||
Internal coordination settings are located in `<keeper_server>.<coordination_settings>` section:
|
||||
|
||||
- `operation_timeout_ms` — Timeout for a single client operation (ms) (default: 10000).
|
||||
- `session_timeout_ms` — Timeout for client session (ms) (default: 30000).
|
||||
- `min_session_timeout_ms` — Min timeout for client session (ms) (default: 10000).
|
||||
- `session_timeout_ms` — Max timeout for client session (ms) (default: 100000).
|
||||
- `dead_session_check_period_ms` — How often ClickHouse Keeper check dead sessions and remove them (ms) (default: 500).
|
||||
- `heart_beat_interval_ms` — How often a ClickHouse Keeper leader will send heartbeats to followers (ms) (default: 500).
|
||||
- `election_timeout_lower_bound_ms` — If the follower didn't receive heartbeats from the leader in this interval, then it can initiate leader election (default: 1000).
|
||||
|
@ -51,9 +51,6 @@ With filtering by realm:
|
||||
</clickhouse>
|
||||
```
|
||||
|
||||
!!! warning "Note"
|
||||
You can define only one `kerberos` section. The presence of multiple `kerberos` sections will force ClickHouse to disable Kerberos authentication.
|
||||
|
||||
!!! warning "Note"
|
||||
`principal` and `realm` sections cannot be specified at the same time. The presence of both `principal` and `realm` sections will force ClickHouse to disable Kerberos authentication.
|
||||
|
||||
|
@ -740,74 +740,6 @@ Result:
|
||||
└───────┘
|
||||
```
|
||||
|
||||
## h3DegsToRads {#h3degstorads}
|
||||
|
||||
Converts degrees to radians.
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
h3DegsToRads(degrees)
|
||||
```
|
||||
|
||||
**Parameter**
|
||||
|
||||
- `degrees` — Input in degrees. Type: [Float64](../../../sql-reference/data-types/float.md).
|
||||
|
||||
**Returned values**
|
||||
|
||||
- Radians. Type: [Float64](../../../sql-reference/data-types/float.md).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
``` sql
|
||||
SELECT h3DegsToRads(180.0) AS radians;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
``` text
|
||||
┌───────────radians─┐
|
||||
│ 3.141592653589793 │
|
||||
└───────────────────┘
|
||||
```
|
||||
|
||||
## h3RadsToDegs {#h3radstodegs}
|
||||
|
||||
Converts radians to degrees.
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
h3RadsToDegs(radians)
|
||||
```
|
||||
|
||||
**Parameter**
|
||||
|
||||
- `radians` — Input in radians. Type: [Float64](../../../sql-reference/data-types/float.md).
|
||||
|
||||
**Returned values**
|
||||
|
||||
- Degrees. Type: [Float64](../../../sql-reference/data-types/float.md).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
``` sql
|
||||
SELECT h3RadsToDegs(3.141592653589793) AS degrees;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
``` text
|
||||
┌─degrees─┐
|
||||
│ 180 │
|
||||
└─────────┘
|
||||
```
|
||||
|
||||
## h3CellAreaM2 {#h3cellaream2}
|
||||
|
||||
Returns the exact area of a specific cell in square meters corresponding to the given input H3 index.
|
||||
@ -880,4 +812,41 @@ Result:
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
## h3ToCenterChild {#h3tocenterchild}
|
||||
|
||||
Returns the center child (finer) [H3](#h3index) index contained by given [H3](#h3index) at the given resolution.
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
h3ToCenterChild(index, resolution)
|
||||
```
|
||||
|
||||
**Parameter**
|
||||
|
||||
- `index` — Hexagon index number. Type: [UInt64](../../../sql-reference/data-types/int-uint.md).
|
||||
- `resolution` — Index resolution. Range: `[0, 15]`. Type: [UInt8](../../../sql-reference/data-types/int-uint.md).
|
||||
|
||||
**Returned values**
|
||||
|
||||
- [H3](#h3index) index of the center child contained by given [H3](#h3index) at the given resolution.
|
||||
|
||||
Type: [UInt64](../../../sql-reference/data-types/int-uint.md).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
``` sql
|
||||
SELECT h3ToCenterChild(577023702256844799,1) AS centerToChild;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
``` text
|
||||
┌──────centerToChild─┐
|
||||
│ 581496515558637567 │
|
||||
└────────────────────┘
|
||||
```
|
||||
|
||||
[Original article](https://clickhouse.com/docs/en/sql-reference/functions/geo/h3) <!--hide-->
|
||||
|
@ -134,7 +134,23 @@ Tuples should have the same type of the elements.
|
||||
|
||||
- The Hamming distance.
|
||||
|
||||
Type: [UInt8](../../sql-reference/data-types/int-uint.md).
|
||||
Type: The result type is calculed the same way it is for [Arithmetic functions](../../sql-reference/functions/arithmetic-functions.md), based on the number of elements in the input tuples.
|
||||
|
||||
``` sql
|
||||
SELECT
|
||||
toTypeName(tupleHammingDistance(tuple(0), tuple(0))) AS t1,
|
||||
toTypeName(tupleHammingDistance((0, 0), (0, 0))) AS t2,
|
||||
toTypeName(tupleHammingDistance((0, 0, 0), (0, 0, 0))) AS t3,
|
||||
toTypeName(tupleHammingDistance((0, 0, 0, 0), (0, 0, 0, 0))) AS t4,
|
||||
toTypeName(tupleHammingDistance((0, 0, 0, 0, 0), (0, 0, 0, 0, 0))) AS t5
|
||||
```
|
||||
|
||||
``` text
|
||||
┌─t1────┬─t2─────┬─t3─────┬─t4─────┬─t5─────┐
|
||||
│ UInt8 │ UInt16 │ UInt32 │ UInt64 │ UInt64 │
|
||||
└───────┴────────┴────────┴────────┴────────┘
|
||||
```
|
||||
|
||||
|
||||
**Examples**
|
||||
|
||||
@ -240,6 +256,7 @@ Result:
|
||||
┌─tupleToNameValuePairs(tuple(3, 2, 1))─┐
|
||||
│ [('1',3),('2',2),('3',1)] │
|
||||
└───────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## tuplePlus {#tupleplus}
|
||||
|
||||
|
@ -55,7 +55,11 @@ SELECT * FROM insert_select_testtable;
|
||||
└───┴───┴───┘
|
||||
```
|
||||
|
||||
In this example, we see that the second inserted row has `a` and `c` columns filled by the passed values, and `b` filled with value by default.
|
||||
In this example, we see that the second inserted row has `a` and `c` columns filled by the passed values, and `b` filled with value by default. It is also possible to use `DEFAULT` keyword to insert default values:
|
||||
|
||||
``` sql
|
||||
INSERT INTO insert_select_testtable VALUES (1, DEFAULT, 1) ;
|
||||
```
|
||||
|
||||
If a list of columns does not include all existing columns, the rest of the columns are filled with:
|
||||
|
||||
|
@ -3,14 +3,14 @@ toc_priority: 53
|
||||
toc_title: USE
|
||||
---
|
||||
|
||||
# USE Statement {#use}
|
||||
# USE 语句 {#use}
|
||||
|
||||
``` sql
|
||||
USE db
|
||||
```
|
||||
|
||||
Lets you set the current database for the session.
|
||||
用于设置会话的当前数据库。
|
||||
|
||||
The current database is used for searching for tables if the database is not explicitly defined in the query with a dot before the table name.
|
||||
如果查询语句中没有在表名前面以加点的方式指明数据库名, 则用当前数据库进行搜索。
|
||||
|
||||
This query can’t be made when using the HTTP protocol, since there is no concept of a session.
|
||||
使用 HTTP 协议时无法进行此查询,因为没有会话的概念。
|
||||
|
@ -3,7 +3,7 @@ toc_priority: 62
|
||||
toc_title: Window Functions
|
||||
---
|
||||
|
||||
# [experimental] Window Functions
|
||||
# Window Functions
|
||||
|
||||
ClickHouse supports the standard grammar for defining windows and window functions. The following features are currently supported:
|
||||
|
||||
|
2053
docs/en/whats-new/changelog/2021.md
Normal file
2053
docs/en/whats-new/changelog/2021.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
---
|
||||
toc_folder_title: Changelog
|
||||
toc_priority: 74
|
||||
toc_title: '2021'
|
||||
toc_title: '2022'
|
||||
---
|
||||
|
||||
{% include "content/changelog.md" %}
|
||||
|
@ -37,7 +37,7 @@ ClickHouse собирает:
|
||||
|
||||
Можно настроить экспорт метрик из ClickHouse в [Graphite](https://github.com/graphite-project). Смотрите секцию [graphite](server-configuration-parameters/settings.md#server_configuration_parameters-graphite) конфигурационного файла ClickHouse. Перед настройкой экспорта метрик необходимо настроить Graphite, как указано в [официальном руководстве](https://graphite.readthedocs.io/en/latest/install.html).
|
||||
|
||||
Можно настроить экспорт метрик из ClickHouse в [Prometheus](https://prometheus.io). Смотрите [prometheus](server-configuration-parameters/settings.md#server_configuration_parameters-prometheus) конфигурационного файла ClickHouse. Перед настройкой экспорта метрик необходимо настроить Prometheus, как указано в [официальном руководстве](https://prometheus.io/docs/prometheus/latest/installation/).
|
||||
Можно настроить экспорт метрик из ClickHouse в [Prometheus](https://prometheus.io). Смотрите секцию [prometheus](server-configuration-parameters/settings.md#server_configuration_parameters-prometheus) конфигурационного файла ClickHouse. Перед настройкой экспорта метрик необходимо настроить Prometheus, как указано в [официальном руководстве](https://prometheus.io/docs/prometheus/latest/installation/).
|
||||
|
||||
Также, можно отслеживать доступность сервера через HTTP API. Отправьте `HTTP GET` к ресурсу `/ping`. Если сервер доступен, он отвечает `200 OK`.
|
||||
|
||||
|
@ -237,6 +237,7 @@ SELECT tupleToNameValuePairs(tuple(3, 2, 1));
|
||||
┌─tupleToNameValuePairs(tuple(3, 2, 1))─┐
|
||||
│ [('1',3),('2',2),('3',1)] │
|
||||
└───────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## tuplePlus {#tupleplus}
|
||||
|
||||
|
@ -55,7 +55,12 @@ SELECT * FROM insert_select_testtable
|
||||
└───┴───┴───┘
|
||||
```
|
||||
|
||||
В этом примере мы видим, что вторая строка содержит столбцы `a` и `c`, заполненные переданными значениями и `b`, заполненный значением по умолчанию.
|
||||
В этом примере мы видим, что вторая строка содержит столбцы `a` и `c`, заполненные переданными значениями и `b`, заполненный значением по умолчанию. Также можно использовать ключевое слово `DEFAULT` для вставки значений по умолчанию:
|
||||
|
||||
``` sql
|
||||
INSERT INTO insert_select_testtable VALUES (1, DEFAULT, 1) ;
|
||||
```
|
||||
|
||||
Если список столбцов не включает все существующие столбцы, то все остальные столбцы заполняются следующим образом:
|
||||
|
||||
- Значения, вычисляемые из `DEFAULT` выражений, указанных в определении таблицы.
|
||||
|
@ -1,8 +1,32 @@
|
||||
---
|
||||
machine_translated: true
|
||||
machine_translated_rev: 72537a2d527c63c07aa5d2361a8829f3895cf2bd
|
||||
toc_folder_title: "\u8BED\u53E5"
|
||||
toc_folder_title: SQL 语句
|
||||
toc_hidden: true
|
||||
toc_priority: 31
|
||||
---
|
||||
|
||||
# ClickHouse SQL 语句 {#clickhouse-sql-statements}
|
||||
|
||||
语句表示可以使用 SQL 查询执行的各种操作。每种类型的语句都有自己的语法和用法详细信息,这些语法和用法详细信息单独描述如下所示:
|
||||
|
||||
- [SELECT](../../sql-reference/statements/select/index.md)
|
||||
- [INSERT INTO](../../sql-reference/statements/insert-into.md)
|
||||
- [CREATE](../../sql-reference/statements/create/index.md)
|
||||
- [ALTER](../../sql-reference/statements/alter/index.md)
|
||||
- [SYSTEM](../../sql-reference/statements/system.md)
|
||||
- [SHOW](../../sql-reference/statements/show.md)
|
||||
- [GRANT](../../sql-reference/statements/grant.md)
|
||||
- [REVOKE](../../sql-reference/statements/revoke.md)
|
||||
- [ATTACH](../../sql-reference/statements/attach.md)
|
||||
- [CHECK TABLE](../../sql-reference/statements/check-table.md)
|
||||
- [DESCRIBE TABLE](../../sql-reference/statements/describe-table.md)
|
||||
- [DETACH](../../sql-reference/statements/detach.md)
|
||||
- [DROP](../../sql-reference/statements/drop.md)
|
||||
- [EXISTS](../../sql-reference/statements/exists.md)
|
||||
- [KILL](../../sql-reference/statements/kill.md)
|
||||
- [OPTIMIZE](../../sql-reference/statements/optimize.md)
|
||||
- [RENAME](../../sql-reference/statements/rename.md)
|
||||
- [SET](../../sql-reference/statements/set.md)
|
||||
- [SET ROLE](../../sql-reference/statements/set-role.md)
|
||||
- [TRUNCATE](../../sql-reference/statements/truncate.md)
|
||||
- [USE](../../sql-reference/statements/use.md)
|
||||
- [EXPLAIN](../../sql-reference/statements/explain.md)
|
||||
|
@ -38,7 +38,8 @@
|
||||
|
||||
<coordination_settings>
|
||||
<operation_timeout_ms>10000</operation_timeout_ms>
|
||||
<session_timeout_ms>30000</session_timeout_ms>
|
||||
<min_session_timeout_ms>10000</min_session_timeout_ms>
|
||||
<session_timeout_ms>100000</session_timeout_ms>
|
||||
<raft_logs_level>information</raft_logs_level>
|
||||
<!-- All settings listed in https://github.com/ClickHouse/ClickHouse/blob/master/src/Coordination/CoordinationSettings.h -->
|
||||
</coordination_settings>
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <IO/WriteBufferFromFileDescriptor.h>
|
||||
#include <IO/UseSSL.h>
|
||||
#include <Parsers/IAST.h>
|
||||
#include <Parsers/ASTInsertQuery.h>
|
||||
#include <base/ErrorHandlers.h>
|
||||
#include <Functions/registerFunctions.h>
|
||||
#include <AggregateFunctions/registerAggregateFunctions.h>
|
||||
|
@ -75,6 +75,7 @@ public:
|
||||
cache.remove(params);
|
||||
}
|
||||
auto res = std::shared_ptr<ContextAccess>(new ContextAccess(access_control, params));
|
||||
res->initialize();
|
||||
cache.add(params, res);
|
||||
return res;
|
||||
}
|
||||
|
@ -146,17 +146,23 @@ ContextAccess::ContextAccess(const AccessControl & access_control_, const Params
|
||||
: access_control(&access_control_)
|
||||
, params(params_)
|
||||
{
|
||||
std::lock_guard lock{mutex};
|
||||
}
|
||||
|
||||
subscription_for_user_change = access_control->subscribeForChanges(
|
||||
*params.user_id, [this](const UUID &, const AccessEntityPtr & entity)
|
||||
{
|
||||
UserPtr changed_user = entity ? typeid_cast<UserPtr>(entity) : nullptr;
|
||||
std::lock_guard lock2{mutex};
|
||||
setUser(changed_user);
|
||||
});
|
||||
|
||||
setUser(access_control->read<User>(*params.user_id));
|
||||
void ContextAccess::initialize()
|
||||
{
|
||||
std::lock_guard lock{mutex};
|
||||
subscription_for_user_change = access_control->subscribeForChanges(
|
||||
*params.user_id, [weak_ptr = weak_from_this()](const UUID &, const AccessEntityPtr & entity)
|
||||
{
|
||||
auto ptr = weak_ptr.lock();
|
||||
if (!ptr)
|
||||
return;
|
||||
UserPtr changed_user = entity ? typeid_cast<UserPtr>(entity) : nullptr;
|
||||
std::lock_guard lock2{ptr->mutex};
|
||||
ptr->setUser(changed_user);
|
||||
});
|
||||
setUser(access_control->read<User>(*params.user_id));
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,7 +63,7 @@ struct ContextAccessParams
|
||||
};
|
||||
|
||||
|
||||
class ContextAccess
|
||||
class ContextAccess : public std::enable_shared_from_this<ContextAccess>
|
||||
{
|
||||
public:
|
||||
using Params = ContextAccessParams;
|
||||
@ -161,6 +161,7 @@ private:
|
||||
ContextAccess() {}
|
||||
ContextAccess(const AccessControl & access_control_, const Params & params_);
|
||||
|
||||
void initialize();
|
||||
void setUser(const UserPtr & user_) const;
|
||||
void setRolesInfo(const std::shared_ptr<const EnabledRolesInfo> & roles_info_) const;
|
||||
void setSettingsAndConstraints() const;
|
||||
|
@ -353,6 +353,9 @@ bool LDAPAccessStorage::areLDAPCredentialsValidNoLock(const User & user, const C
|
||||
if (credentials.getUserName() != user.getName())
|
||||
return false;
|
||||
|
||||
if (typeid_cast<const AlwaysAllowCredentials *>(&credentials))
|
||||
return true;
|
||||
|
||||
if (const auto * basic_credentials = dynamic_cast<const BasicCredentials *>(&credentials))
|
||||
return external_authenticators.checkLDAPCredentials(ldap_server_name, *basic_credentials, &role_search_params, &role_search_results);
|
||||
|
||||
@ -478,53 +481,53 @@ std::optional<UUID> LDAPAccessStorage::authenticateImpl(
|
||||
const Credentials & credentials,
|
||||
const Poco::Net::IPAddress & address,
|
||||
const ExternalAuthenticators & external_authenticators,
|
||||
bool /* throw_if_user_not_exists */) const
|
||||
bool throw_if_user_not_exists) const
|
||||
{
|
||||
std::scoped_lock lock(mutex);
|
||||
LDAPClient::SearchResultsList external_roles;
|
||||
auto id = memory_storage.find<User>(credentials.getUserName());
|
||||
if (id)
|
||||
UserPtr user = id ? memory_storage.read<User>(*id) : nullptr;
|
||||
|
||||
std::shared_ptr<User> new_user;
|
||||
if (!user)
|
||||
{
|
||||
auto user = memory_storage.read<User>(*id);
|
||||
// User does not exist, so we create one, and will add it if authentication is successful.
|
||||
new_user = std::make_shared<User>();
|
||||
new_user->setName(credentials.getUserName());
|
||||
new_user->auth_data = AuthenticationData(AuthenticationType::LDAP);
|
||||
new_user->auth_data.setLDAPServerName(ldap_server_name);
|
||||
user = new_user;
|
||||
}
|
||||
|
||||
if (!isAddressAllowed(*user, address))
|
||||
throwAddressNotAllowed(address);
|
||||
if (!isAddressAllowed(*user, address))
|
||||
throwAddressNotAllowed(address);
|
||||
|
||||
if (typeid_cast<const AlwaysAllowCredentials *>(&credentials))
|
||||
return id;
|
||||
LDAPClient::SearchResultsList external_roles;
|
||||
if (!areLDAPCredentialsValidNoLock(*user, credentials, external_authenticators, external_roles))
|
||||
{
|
||||
// We don't know why the authentication has just failed:
|
||||
// either there is no such user in LDAP or the password is not correct.
|
||||
// We treat this situation as if there is no such user because we don't want to block
|
||||
// other storages following this LDAPAccessStorage from trying to authenticate on their own.
|
||||
if (throw_if_user_not_exists)
|
||||
throwNotFound(AccessEntityType::USER, credentials.getUserName());
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!areLDAPCredentialsValidNoLock(*user, credentials, external_authenticators, external_roles))
|
||||
throwInvalidCredentials();
|
||||
if (new_user)
|
||||
{
|
||||
// TODO: if these were AlwaysAllowCredentials, then mapped external roles are not available here,
|
||||
// since without a password we can't authenticate and retrieve roles from the LDAP server.
|
||||
|
||||
// Just in case external_roles are changed. This will be no-op if they are not.
|
||||
updateAssignedRolesNoLock(*id, user->getName(), external_roles);
|
||||
|
||||
return id;
|
||||
assignRolesNoLock(*new_user, external_roles);
|
||||
id = memory_storage.insert(new_user);
|
||||
}
|
||||
else
|
||||
{
|
||||
// User does not exist, so we create one, and will add it if authentication is successful.
|
||||
auto user = std::make_shared<User>();
|
||||
user->setName(credentials.getUserName());
|
||||
user->auth_data = AuthenticationData(AuthenticationType::LDAP);
|
||||
user->auth_data.setLDAPServerName(ldap_server_name);
|
||||
|
||||
if (!isAddressAllowed(*user, address))
|
||||
throwAddressNotAllowed(address);
|
||||
|
||||
if (typeid_cast<const AlwaysAllowCredentials *>(&credentials))
|
||||
{
|
||||
// TODO: mapped external roles are not available here. Without a password we can't authenticate and retrieve roles from LDAP server.
|
||||
assignRolesNoLock(*user, external_roles);
|
||||
return memory_storage.insert(user);
|
||||
}
|
||||
|
||||
if (!areLDAPCredentialsValidNoLock(*user, credentials, external_authenticators, external_roles))
|
||||
throwInvalidCredentials();
|
||||
|
||||
assignRolesNoLock(*user, external_roles);
|
||||
|
||||
return memory_storage.insert(user);
|
||||
// Just in case external_roles are changed. This will be no-op if they are not.
|
||||
updateAssignedRolesNoLock(*id, user->getName(), external_roles);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ namespace
|
||||
|
||||
std::recursive_mutex ldap_global_mutex;
|
||||
|
||||
auto escapeForLDAP(const String & src)
|
||||
auto escapeForDN(const String & src)
|
||||
{
|
||||
String dest;
|
||||
dest.reserve(src.size() * 2);
|
||||
@ -96,6 +96,39 @@ namespace
|
||||
return dest;
|
||||
}
|
||||
|
||||
auto escapeForFilter(const String & src)
|
||||
{
|
||||
String dest;
|
||||
dest.reserve(src.size() * 3);
|
||||
|
||||
for (auto ch : src)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '*':
|
||||
dest += "\\2A";
|
||||
break;
|
||||
case '(':
|
||||
dest += "\\28";
|
||||
break;
|
||||
case ')':
|
||||
dest += "\\29";
|
||||
break;
|
||||
case '\\':
|
||||
dest += "\\5C";
|
||||
break;
|
||||
case '\0':
|
||||
dest += "\\00";
|
||||
break;
|
||||
default:
|
||||
dest += ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
auto replacePlaceholders(const String & src, const std::vector<std::pair<String, String>> & pairs)
|
||||
{
|
||||
String dest = src;
|
||||
@ -160,7 +193,7 @@ void LDAPClient::diag(const int rc, String text)
|
||||
}
|
||||
}
|
||||
|
||||
void LDAPClient::openConnection()
|
||||
bool LDAPClient::openConnection()
|
||||
{
|
||||
std::scoped_lock lock(ldap_global_mutex);
|
||||
|
||||
@ -294,7 +327,7 @@ void LDAPClient::openConnection()
|
||||
if (params.enable_tls == LDAPClient::Params::TLSEnable::YES_STARTTLS)
|
||||
diag(ldap_start_tls_s(handle, nullptr, nullptr));
|
||||
|
||||
final_user_name = escapeForLDAP(params.user);
|
||||
final_user_name = escapeForDN(params.user);
|
||||
final_bind_dn = replacePlaceholders(params.bind_dn, { {"{user_name}", final_user_name} });
|
||||
final_user_dn = final_bind_dn; // The default value... may be updated right after a successful bind.
|
||||
|
||||
@ -306,7 +339,15 @@ void LDAPClient::openConnection()
|
||||
cred.bv_val = const_cast<char *>(params.password.c_str());
|
||||
cred.bv_len = params.password.size();
|
||||
|
||||
diag(ldap_sasl_bind_s(handle, final_bind_dn.c_str(), LDAP_SASL_SIMPLE, &cred, nullptr, nullptr, nullptr));
|
||||
{
|
||||
const auto rc = ldap_sasl_bind_s(handle, final_bind_dn.c_str(), LDAP_SASL_SIMPLE, &cred, nullptr, nullptr, nullptr);
|
||||
|
||||
// Handle invalid credentials gracefully.
|
||||
if (rc == LDAP_INVALID_CREDENTIALS)
|
||||
return false;
|
||||
|
||||
diag(rc);
|
||||
}
|
||||
|
||||
// Once bound, run the user DN search query and update the default value, if asked.
|
||||
if (params.user_dn_detection)
|
||||
@ -322,7 +363,7 @@ void LDAPClient::openConnection()
|
||||
final_user_dn = *user_dn_search_results.begin();
|
||||
}
|
||||
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
@ -366,10 +407,10 @@ LDAPClient::SearchResults LDAPClient::search(const SearchParams & search_params)
|
||||
});
|
||||
|
||||
const auto final_search_filter = replacePlaceholders(search_params.search_filter, {
|
||||
{"{user_name}", final_user_name},
|
||||
{"{bind_dn}", final_bind_dn},
|
||||
{"{user_dn}", final_user_dn},
|
||||
{"{base_dn}", final_base_dn}
|
||||
{"{user_name}", escapeForFilter(final_user_name)},
|
||||
{"{bind_dn}", escapeForFilter(final_bind_dn)},
|
||||
{"{user_dn}", escapeForFilter(final_user_dn)},
|
||||
{"{base_dn}", escapeForFilter(final_base_dn)}
|
||||
});
|
||||
|
||||
char * attrs[] = { const_cast<char *>(search_params.attribute.c_str()), nullptr };
|
||||
@ -541,8 +582,9 @@ bool LDAPSimpleAuthClient::authenticate(const RoleSearchParamsList * role_search
|
||||
|
||||
SCOPE_EXIT({ closeConnection(); });
|
||||
|
||||
// Will throw on any error, including invalid credentials.
|
||||
openConnection();
|
||||
// Will return false on invalid credentials, will throw on any other error.
|
||||
if (!openConnection())
|
||||
return false;
|
||||
|
||||
// While connected, run search queries and save the results, if asked.
|
||||
if (role_search_params)
|
||||
@ -574,7 +616,7 @@ void LDAPClient::diag(const int, String)
|
||||
throw Exception("ClickHouse was built without LDAP support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME);
|
||||
}
|
||||
|
||||
void LDAPClient::openConnection()
|
||||
bool LDAPClient::openConnection()
|
||||
{
|
||||
throw Exception("ClickHouse was built without LDAP support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME);
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ public:
|
||||
|
||||
protected:
|
||||
MAYBE_NORETURN void diag(const int rc, String text = "");
|
||||
MAYBE_NORETURN void openConnection();
|
||||
MAYBE_NORETURN bool openConnection();
|
||||
void closeConnection() noexcept;
|
||||
SearchResults search(const SearchParams & search_params);
|
||||
|
||||
|
@ -452,9 +452,11 @@ void MultipleAccessStorage::updateSubscriptionsToNestedStorages(std::unique_lock
|
||||
std::optional<UUID> MultipleAccessStorage::authenticateImpl(const Credentials & credentials, const Poco::Net::IPAddress & address, const ExternalAuthenticators & external_authenticators, bool throw_if_user_not_exists) const
|
||||
{
|
||||
auto storages = getStoragesInternal();
|
||||
for (const auto & storage : *storages)
|
||||
for (size_t i = 0; i != storages->size(); ++i)
|
||||
{
|
||||
auto id = storage->authenticate(credentials, address, external_authenticators, /* throw_if_user_not_exists = */ false);
|
||||
const auto & storage = (*storages)[i];
|
||||
bool is_last_storage = (i == storages->size() - 1);
|
||||
auto id = storage->authenticate(credentials, address, external_authenticators, throw_if_user_not_exists && is_last_storage);
|
||||
if (id)
|
||||
{
|
||||
std::lock_guard lock{mutex};
|
||||
|
@ -29,8 +29,11 @@ configure_file (Core/config_core.h.in "${CMAKE_CURRENT_BINARY_DIR}/Core/include/
|
||||
|
||||
if (USE_DEBUG_HELPERS)
|
||||
get_target_property(MAGIC_ENUM_INCLUDE_DIR magic_enum INTERFACE_INCLUDE_DIRECTORIES)
|
||||
set (INCLUDE_DEBUG_HELPERS "-I\"${ClickHouse_SOURCE_DIR}/base\" -I\"${MAGIC_ENUM_INCLUDE_DIR}\" -include \"${ClickHouse_SOURCE_DIR}/src/Core/iostream_debug_helpers.h\"")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${INCLUDE_DEBUG_HELPERS}")
|
||||
# CMake generator expression will do insane quoting when it encounters special character like quotes, spaces, etc.
|
||||
# Prefixing "SHELL:" will force it to use the original text.
|
||||
set (INCLUDE_DEBUG_HELPERS "SHELL:-I\"${ClickHouse_SOURCE_DIR}/base\" -I\"${MAGIC_ENUM_INCLUDE_DIR}\" -include \"${ClickHouse_SOURCE_DIR}/src/Core/iostream_debug_helpers.h\"")
|
||||
# Use generator expression as we don't want to pollute CMAKE_CXX_FLAGS, which will interfere with CMake check system.
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${INCLUDE_DEBUG_HELPERS}>)
|
||||
endif ()
|
||||
|
||||
if (COMPILER_GCC)
|
||||
@ -385,9 +388,9 @@ dbms_target_link_libraries (
|
||||
target_include_directories(clickhouse_common_io PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/Core/include") # uses some includes from core
|
||||
dbms_target_include_directories(PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/Core/include")
|
||||
|
||||
target_include_directories(clickhouse_common_io BEFORE PUBLIC ${PDQSORT_INCLUDE_DIR})
|
||||
target_include_directories(clickhouse_common_io SYSTEM BEFORE PUBLIC ${PDQSORT_INCLUDE_DIR})
|
||||
dbms_target_include_directories(SYSTEM BEFORE PUBLIC ${PDQSORT_INCLUDE_DIR})
|
||||
target_include_directories(clickhouse_common_io BEFORE PUBLIC ${MINISELECT_INCLUDE_DIR})
|
||||
target_include_directories(clickhouse_common_io SYSTEM BEFORE PUBLIC ${MINISELECT_INCLUDE_DIR})
|
||||
dbms_target_include_directories(SYSTEM BEFORE PUBLIC ${MINISELECT_INCLUDE_DIR})
|
||||
|
||||
if (ZSTD_LIBRARY)
|
||||
@ -584,7 +587,6 @@ if (ENABLE_TESTS AND USE_GTEST)
|
||||
dbms
|
||||
clickhouse_common_config
|
||||
clickhouse_common_zookeeper
|
||||
clickhouse_common_config
|
||||
string_utils)
|
||||
|
||||
add_check(unit_tests_dbms)
|
||||
|
@ -3,9 +3,11 @@
|
||||
#include <Columns/ColumnsCommon.h>
|
||||
#include <Common/PODArray.h>
|
||||
#include <Common/ProfileEvents.h>
|
||||
#include <Common/assert_cast.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <Functions/IFunction.h>
|
||||
|
||||
|
||||
namespace ProfileEvents
|
||||
{
|
||||
extern const Event FunctionExecute;
|
||||
@ -59,6 +61,40 @@ ColumnPtr ColumnFunction::cut(size_t start, size_t length) const
|
||||
return ColumnFunction::create(length, function, capture, is_short_circuit_argument, is_function_compiled);
|
||||
}
|
||||
|
||||
void ColumnFunction::insertFrom(const IColumn & src, size_t n)
|
||||
{
|
||||
const ColumnFunction & src_func = assert_cast<const ColumnFunction &>(src);
|
||||
|
||||
size_t num_captured_columns = captured_columns.size();
|
||||
assert(num_captured_columns == src_func.captured_columns.size());
|
||||
|
||||
for (size_t i = 0; i < num_captured_columns; ++i)
|
||||
{
|
||||
auto mut_column = IColumn::mutate(std::move(captured_columns[i].column));
|
||||
mut_column->insertFrom(*src_func.captured_columns[i].column, n);
|
||||
captured_columns[i].column = std::move(mut_column);
|
||||
}
|
||||
|
||||
++size_;
|
||||
}
|
||||
|
||||
void ColumnFunction::insertRangeFrom(const IColumn & src, size_t start, size_t length)
|
||||
{
|
||||
const ColumnFunction & src_func = assert_cast<const ColumnFunction &>(src);
|
||||
|
||||
size_t num_captured_columns = captured_columns.size();
|
||||
assert(num_captured_columns == src_func.captured_columns.size());
|
||||
|
||||
for (size_t i = 0; i < num_captured_columns; ++i)
|
||||
{
|
||||
auto mut_column = IColumn::mutate(std::move(captured_columns[i].column));
|
||||
mut_column->insertRangeFrom(*src_func.captured_columns[i].column, start, length);
|
||||
captured_columns[i].column = std::move(mut_column);
|
||||
}
|
||||
|
||||
size_ += length;
|
||||
}
|
||||
|
||||
ColumnPtr ColumnFunction::filter(const Filter & filt, ssize_t result_size_hint) const
|
||||
{
|
||||
if (size_ != filt.size())
|
||||
|
@ -88,10 +88,8 @@ public:
|
||||
throw Exception("Cannot insert into " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
void insertRangeFrom(const IColumn &, size_t, size_t) override
|
||||
{
|
||||
throw Exception("Cannot insert into " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
void insertFrom(const IColumn & src, size_t n) override;
|
||||
void insertRangeFrom(const IColumn &, size_t start, size_t length) override;
|
||||
|
||||
void insertData(const char *, size_t) override
|
||||
{
|
||||
|
@ -8,7 +8,6 @@ set (SRCS
|
||||
)
|
||||
|
||||
add_library(clickhouse_common_config ${SRCS})
|
||||
|
||||
target_link_libraries(clickhouse_common_config
|
||||
PUBLIC
|
||||
clickhouse_common_zookeeper
|
||||
@ -18,9 +17,17 @@ target_link_libraries(clickhouse_common_config
|
||||
string_utils
|
||||
)
|
||||
|
||||
if (USE_YAML_CPP)
|
||||
target_link_libraries(clickhouse_common_config
|
||||
add_library(clickhouse_common_config_no_zookeeper_log ${SRCS})
|
||||
target_link_libraries(clickhouse_common_config_no_zookeeper_log
|
||||
PUBLIC
|
||||
clickhouse_common_zookeeper_no_log
|
||||
common
|
||||
Poco::XML
|
||||
PRIVATE
|
||||
yaml-cpp
|
||||
string_utils
|
||||
)
|
||||
|
||||
if (USE_YAML_CPP)
|
||||
target_link_libraries(clickhouse_common_config PRIVATE yaml-cpp)
|
||||
target_link_libraries(clickhouse_common_config_no_zookeeper_log PRIVATE yaml-cpp)
|
||||
endif()
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace Util
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <Common/formatReadable.h>
|
||||
#include <Common/filesystemHelpers.h>
|
||||
#include <Common/ErrorCodes.h>
|
||||
#include <Common/LockMemoryExceptionInThread.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include <Common/config_version.h>
|
||||
@ -175,7 +176,7 @@ void tryLogCurrentException(const char * log_name, const std::string & start_of_
|
||||
///
|
||||
/// And in this case the exception will not be logged, so let's block the
|
||||
/// MemoryTracker until the exception will be logged.
|
||||
MemoryTracker::LockExceptionInThread lock_memory_tracker(VariableContext::Global);
|
||||
LockMemoryExceptionInThread lock_memory_tracker(VariableContext::Global);
|
||||
|
||||
/// Poco::Logger::get can allocate memory too
|
||||
tryLogCurrentExceptionImpl(&Poco::Logger::get(log_name), start_of_message);
|
||||
@ -188,7 +189,7 @@ void tryLogCurrentException(Poco::Logger * logger, const std::string & start_of_
|
||||
///
|
||||
/// And in this case the exception will not be logged, so let's block the
|
||||
/// MemoryTracker until the exception will be logged.
|
||||
MemoryTracker::LockExceptionInThread lock_memory_tracker(VariableContext::Global);
|
||||
LockMemoryExceptionInThread lock_memory_tracker(VariableContext::Global);
|
||||
|
||||
tryLogCurrentExceptionImpl(logger, start_of_message);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
/// Conversion of infinite values to integer is undefined.
|
||||
throw Exception("Cannot convert infinite value to integer type", ErrorCodes::CANNOT_CONVERT_TYPE);
|
||||
}
|
||||
else if (x > std::numeric_limits<T>::max() || x < std::numeric_limits<T>::lowest())
|
||||
else if (x > Float64(std::numeric_limits<T>::max()) || x < Float64(std::numeric_limits<T>::lowest()))
|
||||
{
|
||||
throw Exception("Cannot convert out of range floating point value to integer type", ErrorCodes::CANNOT_CONVERT_TYPE);
|
||||
}
|
||||
|
683
src/Common/IntervalTree.h
Normal file
683
src/Common/IntervalTree.h
Normal file
@ -0,0 +1,683 @@
|
||||
#pragma once
|
||||
|
||||
#include <base/defines.h>
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Structure that holds closed interval with left and right.
|
||||
* Example: [1, 1] is valid interval, that contain point 1.
|
||||
*/
|
||||
template <typename TIntervalStorageType>
|
||||
struct Interval
|
||||
{
|
||||
using IntervalStorageType = TIntervalStorageType;
|
||||
IntervalStorageType left;
|
||||
IntervalStorageType right;
|
||||
|
||||
Interval(IntervalStorageType left_, IntervalStorageType right_) : left(left_), right(right_) { }
|
||||
|
||||
inline bool contains(IntervalStorageType point) const { return left <= point && point <= right; }
|
||||
};
|
||||
|
||||
template <typename IntervalStorageType>
|
||||
bool operator<(const Interval<IntervalStorageType> & lhs, const Interval<IntervalStorageType> & rhs)
|
||||
{
|
||||
return std::tie(lhs.left, lhs.right) < std::tie(rhs.left, rhs.right);
|
||||
}
|
||||
|
||||
template <typename IntervalStorageType>
|
||||
bool operator<=(const Interval<IntervalStorageType> & lhs, const Interval<IntervalStorageType> & rhs)
|
||||
{
|
||||
return std::tie(lhs.left, lhs.right) <= std::tie(rhs.left, rhs.right);
|
||||
}
|
||||
|
||||
template <typename IntervalStorageType>
|
||||
bool operator==(const Interval<IntervalStorageType> & lhs, const Interval<IntervalStorageType> & rhs)
|
||||
{
|
||||
return std::tie(lhs.left, lhs.right) == std::tie(rhs.left, rhs.right);
|
||||
}
|
||||
|
||||
template <typename IntervalStorageType>
|
||||
bool operator!=(const Interval<IntervalStorageType> & lhs, const Interval<IntervalStorageType> & rhs)
|
||||
{
|
||||
return std::tie(lhs.left, lhs.right) != std::tie(rhs.left, rhs.right);
|
||||
}
|
||||
|
||||
template <typename IntervalStorageType>
|
||||
bool operator>(const Interval<IntervalStorageType> & lhs, const Interval<IntervalStorageType> & rhs)
|
||||
{
|
||||
return std::tie(lhs.left, lhs.right) > std::tie(rhs.left, rhs.right);
|
||||
}
|
||||
|
||||
template <typename IntervalStorageType>
|
||||
bool operator>=(const Interval<IntervalStorageType> & lhs, const Interval<IntervalStorageType> & rhs)
|
||||
{
|
||||
return std::tie(lhs.left, lhs.right) >= std::tie(rhs.left, rhs.right);
|
||||
}
|
||||
|
||||
struct IntervalTreeVoidValue
|
||||
{
|
||||
};
|
||||
|
||||
/** Tree structure that allow to efficiently retrieve all intervals that intersect specific point.
|
||||
* https://en.wikipedia.org/wiki/Interval_tree
|
||||
*
|
||||
* Search for all intervals intersecting point has complexity O(log(n) + k), k is count of intervals that intersect point.
|
||||
* If we need to only check if there are some interval intersecting point such operation has complexity O(log(n)).
|
||||
*
|
||||
* Explanation:
|
||||
*
|
||||
* IntervalTree structure is balanced tree. Each node contains:
|
||||
* 1. Point
|
||||
* 2. Intervals sorted by left ascending that intersect that point.
|
||||
* 3. Intervals sorted by right descending that intersect that point.
|
||||
*
|
||||
* Build:
|
||||
*
|
||||
* To keep tree relatively balanced we can use median of all segment points.
|
||||
* On each step build tree node with intervals. For root node input intervals are all intervals.
|
||||
* First split intervals in 4 groups.
|
||||
* 1. Intervals that lie that are less than median point. Interval right is less than median point.
|
||||
* 2. Intervals that lie that are greater than median point. Interval right is less than median point.
|
||||
* 3. Intervals that intersect node sorted by left ascending.
|
||||
* 4. Intervals that intersect node sorted by right descending.
|
||||
*
|
||||
* If intervals in 1 group are not empty. Continue build left child recursively with intervals from 1 group.
|
||||
* If intervals in 2 group are not empty. Continue build right child recursively with intervals from 2 group.
|
||||
*
|
||||
* Search:
|
||||
*
|
||||
* Search for intervals intersecting point is started from root node.
|
||||
* If search point is less than point in node, then we check intervals sorted by left ascending
|
||||
* until left is greater than search point.
|
||||
* If there is left child, continue search recursively in left child.
|
||||
*
|
||||
* If search point is greater than point in node, then we check intervals sorted by right descending
|
||||
* until right is less than search point.
|
||||
* If there is right child, continue search recursively in right child.
|
||||
*
|
||||
* If search point is equal to point in node, then we can emit all intervals that intersect current tree node
|
||||
* and stop searching.
|
||||
*
|
||||
* Additional details:
|
||||
* 1. To improve cache locality tree is stored implicitly in array, after build method is called
|
||||
* other intervals cannot be added to the tree.
|
||||
* 2. Additionally to improve cache locality in tree node we store sorted intervals for all nodes in separate
|
||||
* array. In node we store only start of its sorted intervals, and also size of intersecting intervals.
|
||||
* If we need to retrieve intervals sorted by left ascending they will be stored in indexes
|
||||
* [sorted_intervals_start_index, sorted_intervals_start_index + intersecting_intervals_size).
|
||||
* If we need to retrieve intervals sorted by right descending they will be store in indexes
|
||||
* [sorted_intervals_start_index + intersecting_intervals_size, sorted_intervals_start_index + intersecting_intervals_size * 2).
|
||||
*/
|
||||
template <typename Interval, typename Value>
|
||||
class IntervalTree
|
||||
{
|
||||
public:
|
||||
using IntervalStorageType = typename Interval::IntervalStorageType;
|
||||
|
||||
static constexpr bool is_empty_value = std::is_same_v<Value, IntervalTreeVoidValue>;
|
||||
|
||||
IntervalTree() { nodes.resize(1); }
|
||||
|
||||
template <typename TValue = Value, std::enable_if_t<std::is_same_v<TValue, IntervalTreeVoidValue>, bool> = true>
|
||||
void emplace(Interval interval)
|
||||
{
|
||||
assert(!tree_is_built);
|
||||
sorted_intervals.emplace_back(interval);
|
||||
increaseIntervalsSize();
|
||||
}
|
||||
|
||||
template <typename TValue = Value, std::enable_if_t<!std::is_same_v<TValue, IntervalTreeVoidValue>, bool> = true, typename... Args>
|
||||
void emplace(Interval interval, Args &&... args)
|
||||
{
|
||||
assert(!tree_is_built);
|
||||
sorted_intervals.emplace_back(
|
||||
std::piecewise_construct, std::forward_as_tuple(interval), std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
increaseIntervalsSize();
|
||||
}
|
||||
|
||||
template <typename TValue = Value, std::enable_if_t<std::is_same_v<TValue, IntervalTreeVoidValue>, bool> = true>
|
||||
void insert(Interval interval)
|
||||
{
|
||||
assert(!tree_is_built);
|
||||
sorted_intervals.emplace_back(interval);
|
||||
increaseIntervalsSize();
|
||||
}
|
||||
|
||||
template <typename TValue = Value, std::enable_if_t<!std::is_same_v<TValue, IntervalTreeVoidValue>, bool> = true>
|
||||
void insert(Interval interval, const Value & value)
|
||||
{
|
||||
assert(!tree_is_built);
|
||||
sorted_intervals.emplace_back(interval, value);
|
||||
increaseIntervalsSize();
|
||||
}
|
||||
|
||||
template <typename TValue = Value, std::enable_if_t<!std::is_same_v<TValue, IntervalTreeVoidValue>, bool> = true>
|
||||
void insert(Interval interval, Value && value)
|
||||
{
|
||||
assert(!tree_is_built);
|
||||
sorted_intervals.emplace_back(interval, std::move(value));
|
||||
increaseIntervalsSize();
|
||||
}
|
||||
|
||||
/// Build tree, after that intervals cannot be inserted, and only search or iteration can be performed.
|
||||
void build()
|
||||
{
|
||||
assert(!tree_is_built);
|
||||
nodes.clear();
|
||||
nodes.reserve(sorted_intervals.size());
|
||||
buildTree();
|
||||
tree_is_built = true;
|
||||
}
|
||||
|
||||
/** Find all intervals intersecting point.
|
||||
*
|
||||
* Callback interface for IntervalSet:
|
||||
*
|
||||
* template <typename IntervalType>
|
||||
* struct IntervalSetCallback
|
||||
* {
|
||||
* bool operator()(const IntervalType & interval)
|
||||
* {
|
||||
* bool should_continue_interval_iteration = false;
|
||||
* return should_continue_interval_iteration;
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* Callback interface for IntervalMap:
|
||||
*
|
||||
* template <typename IntervalType, typename Value>
|
||||
* struct IntervalMapCallback
|
||||
* {
|
||||
* bool operator()(const IntervalType & interval, const Value & value)
|
||||
* {
|
||||
* bool should_continue_interval_iteration = false;
|
||||
* return should_continue_interval_iteration;
|
||||
* }
|
||||
* };
|
||||
*/
|
||||
|
||||
template <typename IntervalCallback>
|
||||
void find(IntervalStorageType point, IntervalCallback && callback) const
|
||||
{
|
||||
if (unlikely(!tree_is_built))
|
||||
{
|
||||
findIntervalsNonConstructedImpl(point, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
findIntervalsImpl(point, callback);
|
||||
}
|
||||
|
||||
/// Check if there is an interval intersecting point
|
||||
bool has(IntervalStorageType point) const
|
||||
{
|
||||
bool has_intervals = false;
|
||||
|
||||
if constexpr (is_empty_value)
|
||||
{
|
||||
find(point, [&](auto &)
|
||||
{
|
||||
has_intervals = true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
find(point, [&](auto &, auto &)
|
||||
{
|
||||
has_intervals = true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
return has_intervals;
|
||||
}
|
||||
|
||||
class Iterator;
|
||||
using iterator = Iterator;
|
||||
using const_iterator = Iterator;
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
size_t start_index = findFirstIteratorNodeIndex();
|
||||
return Iterator(start_index, 0, this);
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
size_t end_index = findLastIteratorNodeIndex();
|
||||
size_t last_interval_index = 0;
|
||||
|
||||
if (likely(end_index < nodes.size()))
|
||||
last_interval_index = nodes[end_index].sorted_intervals_range_size;
|
||||
|
||||
return Iterator(end_index, last_interval_index, this);
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
size_t start_index = findFirstIteratorNodeIndex();
|
||||
return Iterator(start_index, 0, this);
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
size_t end_index = findLastIteratorNodeIndex();
|
||||
size_t last_interval_index = 0;
|
||||
|
||||
if (likely(end_index < nodes.size()))
|
||||
last_interval_index = nodes[end_index].sorted_intervals_range_size;
|
||||
|
||||
return Iterator(end_index, last_interval_index, this);
|
||||
}
|
||||
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
|
||||
const_iterator cend() const { return end(); }
|
||||
|
||||
size_t getIntervalsSize() const { return intervals_size; }
|
||||
|
||||
private:
|
||||
struct Node
|
||||
{
|
||||
size_t sorted_intervals_range_start_index;
|
||||
size_t sorted_intervals_range_size;
|
||||
|
||||
IntervalStorageType middle_element;
|
||||
|
||||
inline bool hasValue() const { return sorted_intervals_range_size != 0; }
|
||||
};
|
||||
|
||||
using IntervalWithEmptyValue = Interval;
|
||||
using IntervalWithNonEmptyValue = std::pair<Interval, Value>;
|
||||
|
||||
using IntervalWithValue = std::conditional_t<is_empty_value, IntervalWithEmptyValue, IntervalWithNonEmptyValue>;
|
||||
|
||||
public:
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
bool operator==(const Iterator & rhs) const
|
||||
{
|
||||
return node_index == rhs.node_index && current_interval_index == rhs.current_interval_index && tree == rhs.tree;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator & rhs) const { return !(*this == rhs); }
|
||||
|
||||
const IntervalWithValue & operator*() { return getCurrentValue(); }
|
||||
|
||||
const IntervalWithValue & operator*() const { return getCurrentValue(); }
|
||||
|
||||
const IntervalWithValue * operator->() { return &getCurrentValue(); }
|
||||
|
||||
const IntervalWithValue * operator->() const { return &getCurrentValue(); }
|
||||
|
||||
Iterator & operator++()
|
||||
{
|
||||
iterateToNext();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator++(int) // NOLINT
|
||||
{
|
||||
Iterator copy(*this);
|
||||
iterateToNext();
|
||||
return copy;
|
||||
}
|
||||
|
||||
Iterator & operator--()
|
||||
{
|
||||
iterateToPrevious();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator--(int) // NOLINT
|
||||
{
|
||||
Iterator copy(*this);
|
||||
iterateToPrevious();
|
||||
return copy;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class IntervalTree;
|
||||
|
||||
Iterator(size_t node_index_, size_t current_interval_index_, const IntervalTree * tree_)
|
||||
: node_index(node_index_), current_interval_index(current_interval_index_), tree(tree_)
|
||||
{
|
||||
}
|
||||
|
||||
size_t node_index;
|
||||
size_t current_interval_index;
|
||||
const IntervalTree * tree;
|
||||
|
||||
void iterateToNext()
|
||||
{
|
||||
size_t nodes_size = tree->nodes.size();
|
||||
auto & current_node = tree->nodes[node_index];
|
||||
|
||||
++current_interval_index;
|
||||
|
||||
if (current_interval_index < current_node.sorted_intervals_range_size)
|
||||
return;
|
||||
|
||||
size_t node_index_copy = node_index + 1;
|
||||
for (; node_index_copy < nodes_size; ++node_index_copy)
|
||||
{
|
||||
auto & node = tree->nodes[node_index_copy];
|
||||
|
||||
if (node.hasValue())
|
||||
{
|
||||
node_index = node_index_copy;
|
||||
current_interval_index = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iterateToPrevious()
|
||||
{
|
||||
if (current_interval_index > 0)
|
||||
{
|
||||
--current_interval_index;
|
||||
return;
|
||||
}
|
||||
|
||||
while (node_index > 0)
|
||||
{
|
||||
auto & node = tree->nodes[node_index - 1];
|
||||
if (node.hasValue())
|
||||
{
|
||||
current_interval_index = node.sorted_intervals_range_size - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
--node_index;
|
||||
}
|
||||
}
|
||||
|
||||
const IntervalWithValue & getCurrentValue() const
|
||||
{
|
||||
auto & current_node = tree->nodes[node_index];
|
||||
size_t interval_index = current_node.sorted_intervals_range_start_index + current_interval_index;
|
||||
return tree->sorted_intervals[interval_index];
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
void buildTree()
|
||||
{
|
||||
std::vector<IntervalStorageType> temporary_points_storage;
|
||||
temporary_points_storage.reserve(sorted_intervals.size() * 2);
|
||||
|
||||
std::vector<IntervalWithValue> left_intervals;
|
||||
std::vector<IntervalWithValue> right_intervals;
|
||||
std::vector<IntervalWithValue> intervals_sorted_by_left_asc;
|
||||
std::vector<IntervalWithValue> intervals_sorted_by_right_desc;
|
||||
|
||||
struct StackFrame
|
||||
{
|
||||
size_t index;
|
||||
std::vector<IntervalWithValue> intervals;
|
||||
};
|
||||
|
||||
std::vector<StackFrame> stack;
|
||||
stack.emplace_back(StackFrame{0, std::move(sorted_intervals)});
|
||||
sorted_intervals.clear();
|
||||
|
||||
while (!stack.empty())
|
||||
{
|
||||
auto frame = std::move(stack.back());
|
||||
stack.pop_back();
|
||||
|
||||
size_t current_index = frame.index;
|
||||
auto & current_intervals = frame.intervals;
|
||||
|
||||
if (current_intervals.empty())
|
||||
continue;
|
||||
|
||||
if (current_index >= nodes.size())
|
||||
nodes.resize(current_index + 1);
|
||||
|
||||
temporary_points_storage.clear();
|
||||
intervalsToPoints(current_intervals, temporary_points_storage);
|
||||
auto median = pointsMedian(temporary_points_storage);
|
||||
|
||||
left_intervals.clear();
|
||||
right_intervals.clear();
|
||||
intervals_sorted_by_left_asc.clear();
|
||||
intervals_sorted_by_right_desc.clear();
|
||||
|
||||
for (const auto & interval_with_value : current_intervals)
|
||||
{
|
||||
auto & interval = getInterval(interval_with_value);
|
||||
|
||||
if (interval.right < median)
|
||||
{
|
||||
left_intervals.emplace_back(interval_with_value);
|
||||
}
|
||||
else if (interval.left > median)
|
||||
{
|
||||
right_intervals.emplace_back(interval_with_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
intervals_sorted_by_left_asc.emplace_back(interval_with_value);
|
||||
intervals_sorted_by_right_desc.emplace_back(interval_with_value);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(intervals_sorted_by_left_asc.begin(), intervals_sorted_by_left_asc.end(), [](auto & lhs, auto & rhs)
|
||||
{
|
||||
auto & lhs_interval = getInterval(lhs);
|
||||
auto & rhs_interval = getInterval(rhs);
|
||||
return lhs_interval.left < rhs_interval.left;
|
||||
});
|
||||
|
||||
std::sort(intervals_sorted_by_right_desc.begin(), intervals_sorted_by_right_desc.end(), [](auto & lhs, auto & rhs)
|
||||
{
|
||||
auto & lhs_interval = getInterval(lhs);
|
||||
auto & rhs_interval = getInterval(rhs);
|
||||
return lhs_interval.right > rhs_interval.right;
|
||||
});
|
||||
|
||||
size_t sorted_intervals_range_start_index = sorted_intervals.size();
|
||||
|
||||
for (auto && interval_sorted_by_left_asc : intervals_sorted_by_left_asc)
|
||||
sorted_intervals.emplace_back(std::move(interval_sorted_by_left_asc));
|
||||
|
||||
for (auto && interval_sorted_by_right_desc : intervals_sorted_by_right_desc)
|
||||
sorted_intervals.emplace_back(std::move(interval_sorted_by_right_desc));
|
||||
|
||||
auto & node = nodes[current_index];
|
||||
node.middle_element = median;
|
||||
node.sorted_intervals_range_start_index = sorted_intervals_range_start_index;
|
||||
node.sorted_intervals_range_size = intervals_sorted_by_left_asc.size();
|
||||
|
||||
size_t left_child_index = current_index * 2 + 1;
|
||||
stack.emplace_back(StackFrame{left_child_index, std::move(left_intervals)});
|
||||
|
||||
size_t right_child_index = current_index * 2 + 2;
|
||||
stack.emplace_back(StackFrame{right_child_index, std::move(right_intervals)});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IntervalCallback>
|
||||
void findIntervalsImpl(IntervalStorageType point, IntervalCallback && callback) const
|
||||
{
|
||||
size_t current_index = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (current_index >= nodes.size())
|
||||
break;
|
||||
|
||||
auto & node = nodes[current_index];
|
||||
if (!node.hasValue())
|
||||
break;
|
||||
|
||||
auto middle_element = node.middle_element;
|
||||
|
||||
if (point < middle_element)
|
||||
{
|
||||
size_t start = node.sorted_intervals_range_start_index;
|
||||
size_t end = start + node.sorted_intervals_range_size;
|
||||
|
||||
for (; start != end; ++start)
|
||||
{
|
||||
auto & interval_with_value_left_sorted_asc = sorted_intervals[start];
|
||||
auto & interval_left_sorted_asc = getInterval(interval_with_value_left_sorted_asc);
|
||||
if (interval_left_sorted_asc.left > point)
|
||||
break;
|
||||
|
||||
bool should_continue = callCallback(interval_with_value_left_sorted_asc, callback);
|
||||
if (unlikely(!should_continue))
|
||||
return;
|
||||
}
|
||||
|
||||
size_t left_child_index = current_index * 2 + 1;
|
||||
current_index = left_child_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t start = node.sorted_intervals_range_start_index + node.sorted_intervals_range_size;
|
||||
size_t end = start + node.sorted_intervals_range_size;
|
||||
|
||||
for (; start != end; ++start)
|
||||
{
|
||||
auto & interval_with_value_right_sorted_desc = sorted_intervals[start];
|
||||
auto & interval_right_sorted_desc = getInterval(interval_with_value_right_sorted_desc);
|
||||
if (interval_right_sorted_desc.right < point)
|
||||
break;
|
||||
|
||||
bool should_continue = callCallback(interval_with_value_right_sorted_desc, callback);
|
||||
if (unlikely(!should_continue))
|
||||
return;
|
||||
}
|
||||
|
||||
if (likely(point > middle_element))
|
||||
{
|
||||
size_t right_child_index = current_index * 2 + 2;
|
||||
current_index = right_child_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
/// This is case when point == middle_element.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IntervalCallback>
|
||||
void findIntervalsNonConstructedImpl(IntervalStorageType point, IntervalCallback && callback) const
|
||||
{
|
||||
for (auto & interval_with_value : sorted_intervals)
|
||||
{
|
||||
auto & interval = getInterval(interval_with_value);
|
||||
|
||||
if (interval.contains(point))
|
||||
callCallback(interval_with_value, callback);
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t findFirstIteratorNodeIndex() const
|
||||
{
|
||||
size_t nodes_size = nodes.size();
|
||||
size_t result_index = 0;
|
||||
|
||||
for (; result_index < nodes_size; ++result_index)
|
||||
{
|
||||
if (nodes[result_index].hasValue())
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(result_index == nodes_size))
|
||||
result_index = 0;
|
||||
|
||||
return result_index;
|
||||
}
|
||||
|
||||
inline size_t findLastIteratorNodeIndex() const
|
||||
{
|
||||
if (unlikely(nodes.empty()))
|
||||
return 0;
|
||||
|
||||
size_t nodes_size = nodes.size();
|
||||
size_t result_index = nodes_size - 1;
|
||||
for (; result_index != 0; --result_index)
|
||||
{
|
||||
if (nodes[result_index].hasValue())
|
||||
break;
|
||||
}
|
||||
|
||||
return result_index;
|
||||
}
|
||||
|
||||
inline void increaseIntervalsSize()
|
||||
{
|
||||
/// Before tree is build we store all intervals size in our first node to allow tree iteration.
|
||||
++intervals_size;
|
||||
nodes[0].sorted_intervals_range_size = intervals_size;
|
||||
}
|
||||
|
||||
std::vector<Node> nodes;
|
||||
std::vector<IntervalWithValue> sorted_intervals;
|
||||
size_t intervals_size = 0;
|
||||
bool tree_is_built = false;
|
||||
|
||||
static inline const Interval & getInterval(const IntervalWithValue & interval_with_value)
|
||||
{
|
||||
if constexpr (is_empty_value)
|
||||
return interval_with_value;
|
||||
else
|
||||
return interval_with_value.first;
|
||||
}
|
||||
|
||||
template <typename IntervalCallback>
|
||||
static inline bool callCallback(const IntervalWithValue & interval, IntervalCallback && callback)
|
||||
{
|
||||
if constexpr (is_empty_value)
|
||||
return callback(interval);
|
||||
else
|
||||
return callback(interval.first, interval.second);
|
||||
}
|
||||
|
||||
static inline void
|
||||
intervalsToPoints(const std::vector<IntervalWithValue> & intervals, std::vector<IntervalStorageType> & temporary_points_storage)
|
||||
{
|
||||
for (const auto & interval_with_value : intervals)
|
||||
{
|
||||
auto & interval = getInterval(interval_with_value);
|
||||
temporary_points_storage.emplace_back(interval.left);
|
||||
temporary_points_storage.emplace_back(interval.right);
|
||||
}
|
||||
}
|
||||
|
||||
static inline IntervalStorageType pointsMedian(std::vector<IntervalStorageType> & points)
|
||||
{
|
||||
size_t size = points.size();
|
||||
size_t middle_element_index = size / 2;
|
||||
|
||||
std::nth_element(points.begin(), points.begin() + middle_element_index, points.end());
|
||||
|
||||
/** We should not get median as average of middle_element_index and middle_element_index - 1
|
||||
* because we want point in node to intersect some interval.
|
||||
* Example: Intervals [1, 1], [3, 3]. If we choose 2 as average point, it does not intersect any interval.
|
||||
*/
|
||||
return points[middle_element_index];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename IntervalType>
|
||||
using IntervalSet = IntervalTree<IntervalType, IntervalTreeVoidValue>;
|
||||
|
||||
template <typename IntervalType, typename Value>
|
||||
using IntervalMap = IntervalTree<IntervalType, Value>;
|
||||
|
||||
}
|
20
src/Common/LockMemoryExceptionInThread.cpp
Normal file
20
src/Common/LockMemoryExceptionInThread.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include <Common/LockMemoryExceptionInThread.h>
|
||||
|
||||
/// LockMemoryExceptionInThread
|
||||
thread_local uint64_t LockMemoryExceptionInThread::counter = 0;
|
||||
thread_local VariableContext LockMemoryExceptionInThread::level = VariableContext::Global;
|
||||
thread_local bool LockMemoryExceptionInThread::block_fault_injections = false;
|
||||
LockMemoryExceptionInThread::LockMemoryExceptionInThread(VariableContext level_, bool block_fault_injections_)
|
||||
: previous_level(level)
|
||||
, previous_block_fault_injections(block_fault_injections)
|
||||
{
|
||||
++counter;
|
||||
level = level_;
|
||||
block_fault_injections = block_fault_injections_;
|
||||
}
|
||||
LockMemoryExceptionInThread::~LockMemoryExceptionInThread()
|
||||
{
|
||||
--counter;
|
||||
level = previous_level;
|
||||
block_fault_injections = previous_block_fault_injections;
|
||||
}
|
39
src/Common/LockMemoryExceptionInThread.h
Normal file
39
src/Common/LockMemoryExceptionInThread.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <Common/VariableContext.h>
|
||||
|
||||
/// To be able to avoid MEMORY_LIMIT_EXCEEDED Exception in destructors:
|
||||
/// - either configured memory limit reached
|
||||
/// - or fault injected
|
||||
///
|
||||
/// So this will simply ignore the configured memory limit (and avoid fault injection).
|
||||
///
|
||||
/// NOTE: exception will be silently ignored, no message in log
|
||||
/// (since logging from MemoryTracker::alloc() is tricky)
|
||||
///
|
||||
/// NOTE: MEMORY_LIMIT_EXCEEDED Exception implicitly blocked if
|
||||
/// stack unwinding is currently in progress in this thread (to avoid
|
||||
/// std::terminate()), so you don't need to use it in this case explicitly.
|
||||
struct LockMemoryExceptionInThread
|
||||
{
|
||||
private:
|
||||
static thread_local uint64_t counter;
|
||||
static thread_local VariableContext level;
|
||||
static thread_local bool block_fault_injections;
|
||||
|
||||
VariableContext previous_level;
|
||||
bool previous_block_fault_injections;
|
||||
public:
|
||||
/// level_ - block in level and above
|
||||
/// block_fault_injections_ - block in fault injection too
|
||||
explicit LockMemoryExceptionInThread(VariableContext level_ = VariableContext::User, bool block_fault_injections_ = true);
|
||||
~LockMemoryExceptionInThread();
|
||||
|
||||
LockMemoryExceptionInThread(const LockMemoryExceptionInThread &) = delete;
|
||||
LockMemoryExceptionInThread & operator=(const LockMemoryExceptionInThread &) = delete;
|
||||
|
||||
static bool isBlocked(VariableContext current_level, bool fault_injection)
|
||||
{
|
||||
return counter > 0 && current_level >= level && (!fault_injection || block_fault_injections);
|
||||
}
|
||||
};
|
@ -1,12 +1,14 @@
|
||||
#include "MemoryTracker.h"
|
||||
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include "Common/TraceCollector.h"
|
||||
#include <Interpreters/TraceCollector.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/LockMemoryExceptionInThread.h>
|
||||
#include <Common/MemoryTrackerBlockerInThread.h>
|
||||
#include <Common/formatReadable.h>
|
||||
#include <base/logger_useful.h>
|
||||
#include <Common/ProfileEvents.h>
|
||||
#include <Common/thread_local_rng.h>
|
||||
#include <base/logger_useful.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
@ -34,7 +36,7 @@ namespace
|
||||
/// noexcept(false)) will cause std::terminate()
|
||||
bool inline memoryTrackerCanThrow(VariableContext level, bool fault_injection)
|
||||
{
|
||||
return !MemoryTracker::LockExceptionInThread::isBlocked(level, fault_injection) && !std::uncaught_exceptions();
|
||||
return !LockMemoryExceptionInThread::isBlocked(level, fault_injection) && !std::uncaught_exceptions();
|
||||
}
|
||||
|
||||
}
|
||||
@ -55,41 +57,6 @@ namespace ProfileEvents
|
||||
|
||||
static constexpr size_t log_peak_memory_usage_every = 1ULL << 30;
|
||||
|
||||
// BlockerInThread
|
||||
thread_local uint64_t MemoryTracker::BlockerInThread::counter = 0;
|
||||
thread_local VariableContext MemoryTracker::BlockerInThread::level = VariableContext::Global;
|
||||
MemoryTracker::BlockerInThread::BlockerInThread(VariableContext level_)
|
||||
: previous_level(level)
|
||||
{
|
||||
++counter;
|
||||
level = level_;
|
||||
}
|
||||
MemoryTracker::BlockerInThread::~BlockerInThread()
|
||||
{
|
||||
--counter;
|
||||
level = previous_level;
|
||||
}
|
||||
|
||||
/// LockExceptionInThread
|
||||
thread_local uint64_t MemoryTracker::LockExceptionInThread::counter = 0;
|
||||
thread_local VariableContext MemoryTracker::LockExceptionInThread::level = VariableContext::Global;
|
||||
thread_local bool MemoryTracker::LockExceptionInThread::block_fault_injections = false;
|
||||
MemoryTracker::LockExceptionInThread::LockExceptionInThread(VariableContext level_, bool block_fault_injections_)
|
||||
: previous_level(level)
|
||||
, previous_block_fault_injections(block_fault_injections)
|
||||
{
|
||||
++counter;
|
||||
level = level_;
|
||||
block_fault_injections = block_fault_injections_;
|
||||
}
|
||||
MemoryTracker::LockExceptionInThread::~LockExceptionInThread()
|
||||
{
|
||||
--counter;
|
||||
level = previous_level;
|
||||
block_fault_injections = previous_block_fault_injections;
|
||||
}
|
||||
|
||||
|
||||
MemoryTracker total_memory_tracker(nullptr, VariableContext::Global);
|
||||
|
||||
|
||||
@ -133,9 +100,9 @@ void MemoryTracker::allocImpl(Int64 size, bool throw_if_memory_exceeded)
|
||||
if (size < 0)
|
||||
throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Negative size ({}) is passed to MemoryTracker. It is a bug.", size);
|
||||
|
||||
if (BlockerInThread::isBlocked(level))
|
||||
if (MemoryTrackerBlockerInThread::isBlocked(level))
|
||||
{
|
||||
/// Since the BlockerInThread should respect the level, we should go to the next parent.
|
||||
/// Since the MemoryTrackerBlockerInThread should respect the level, we should go to the next parent.
|
||||
if (auto * loaded_next = parent.load(std::memory_order_relaxed))
|
||||
loaded_next->allocImpl(size, throw_if_memory_exceeded);
|
||||
return;
|
||||
@ -184,7 +151,7 @@ void MemoryTracker::allocImpl(Int64 size, bool throw_if_memory_exceeded)
|
||||
if (unlikely(fault_probability && fault(thread_local_rng)) && memoryTrackerCanThrow(level, true) && throw_if_memory_exceeded)
|
||||
{
|
||||
/// Prevent recursion. Exception::ctor -> std::string -> new[] -> MemoryTracker::alloc
|
||||
BlockerInThread untrack_lock(VariableContext::Global);
|
||||
MemoryTrackerBlockerInThread untrack_lock(VariableContext::Global);
|
||||
|
||||
ProfileEvents::increment(ProfileEvents::QueryMemoryLimitExceeded);
|
||||
const auto * description = description_ptr.load(std::memory_order_relaxed);
|
||||
@ -203,7 +170,7 @@ void MemoryTracker::allocImpl(Int64 size, bool throw_if_memory_exceeded)
|
||||
bool allocation_traced = false;
|
||||
if (unlikely(current_profiler_limit && will_be > current_profiler_limit))
|
||||
{
|
||||
BlockerInThread untrack_lock(VariableContext::Global);
|
||||
MemoryTrackerBlockerInThread untrack_lock(VariableContext::Global);
|
||||
DB::TraceCollector::collect(DB::TraceType::Memory, StackTrace(), size);
|
||||
setOrRaiseProfilerLimit((will_be + profiler_step - 1) / profiler_step * profiler_step);
|
||||
allocation_traced = true;
|
||||
@ -212,7 +179,7 @@ void MemoryTracker::allocImpl(Int64 size, bool throw_if_memory_exceeded)
|
||||
std::bernoulli_distribution sample(sample_probability);
|
||||
if (unlikely(sample_probability && sample(thread_local_rng)))
|
||||
{
|
||||
BlockerInThread untrack_lock(VariableContext::Global);
|
||||
MemoryTrackerBlockerInThread untrack_lock(VariableContext::Global);
|
||||
DB::TraceCollector::collect(DB::TraceType::MemorySample, StackTrace(), size);
|
||||
allocation_traced = true;
|
||||
}
|
||||
@ -220,7 +187,7 @@ void MemoryTracker::allocImpl(Int64 size, bool throw_if_memory_exceeded)
|
||||
if (unlikely(current_hard_limit && will_be > current_hard_limit) && memoryTrackerCanThrow(level, false) && throw_if_memory_exceeded)
|
||||
{
|
||||
/// Prevent recursion. Exception::ctor -> std::string -> new[] -> MemoryTracker::alloc
|
||||
BlockerInThread untrack_lock(VariableContext::Global);
|
||||
MemoryTrackerBlockerInThread untrack_lock(VariableContext::Global);
|
||||
ProfileEvents::increment(ProfileEvents::QueryMemoryLimitExceeded);
|
||||
const auto * description = description_ptr.load(std::memory_order_relaxed);
|
||||
throw DB::Exception(
|
||||
@ -237,7 +204,7 @@ void MemoryTracker::allocImpl(Int64 size, bool throw_if_memory_exceeded)
|
||||
if (throw_if_memory_exceeded)
|
||||
{
|
||||
/// Prevent recursion. Exception::ctor -> std::string -> new[] -> MemoryTracker::alloc
|
||||
BlockerInThread untrack_lock(VariableContext::Global);
|
||||
MemoryTrackerBlockerInThread untrack_lock(VariableContext::Global);
|
||||
bool log_memory_usage = true;
|
||||
peak_updated = updatePeak(will_be, log_memory_usage);
|
||||
}
|
||||
@ -249,7 +216,7 @@ void MemoryTracker::allocImpl(Int64 size, bool throw_if_memory_exceeded)
|
||||
|
||||
if (peak_updated && allocation_traced)
|
||||
{
|
||||
BlockerInThread untrack_lock(VariableContext::Global);
|
||||
MemoryTrackerBlockerInThread untrack_lock(VariableContext::Global);
|
||||
DB::TraceCollector::collect(DB::TraceType::MemoryPeak, StackTrace(), will_be);
|
||||
}
|
||||
|
||||
@ -288,9 +255,9 @@ bool MemoryTracker::updatePeak(Int64 will_be, bool log_memory_usage)
|
||||
|
||||
void MemoryTracker::free(Int64 size)
|
||||
{
|
||||
if (BlockerInThread::isBlocked(level))
|
||||
if (MemoryTrackerBlockerInThread::isBlocked(level))
|
||||
{
|
||||
/// Since the BlockerInThread should respect the level, we should go to the next parent.
|
||||
/// Since the MemoryTrackerBlockerInThread should respect the level, we should go to the next parent.
|
||||
if (auto * loaded_next = parent.load(std::memory_order_relaxed))
|
||||
loaded_next->free(size);
|
||||
return;
|
||||
@ -299,7 +266,7 @@ void MemoryTracker::free(Int64 size)
|
||||
std::bernoulli_distribution sample(sample_probability);
|
||||
if (unlikely(sample_probability && sample(thread_local_rng)))
|
||||
{
|
||||
BlockerInThread untrack_lock(VariableContext::Global);
|
||||
MemoryTrackerBlockerInThread untrack_lock(VariableContext::Global);
|
||||
DB::TraceCollector::collect(DB::TraceType::MemorySample, StackTrace(), -size);
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,9 @@ extern thread_local bool memory_tracker_always_throw_logical_error_on_allocation
|
||||
/** Tracks memory consumption.
|
||||
* It throws an exception if amount of consumed memory become greater than certain limit.
|
||||
* The same memory tracker could be simultaneously used in different threads.
|
||||
*
|
||||
* @see LockMemoryExceptionInThread
|
||||
* @see MemoryTrackerBlockerInThread
|
||||
*/
|
||||
class MemoryTracker
|
||||
{
|
||||
@ -167,64 +170,6 @@ public:
|
||||
|
||||
/// Prints info about peak memory consumption into log.
|
||||
void logPeakMemoryUsage() const;
|
||||
|
||||
/// To be able to temporarily stop memory tracking from current thread.
|
||||
struct BlockerInThread
|
||||
{
|
||||
private:
|
||||
static thread_local uint64_t counter;
|
||||
static thread_local VariableContext level;
|
||||
|
||||
VariableContext previous_level;
|
||||
public:
|
||||
/// level_ - block in level and above
|
||||
explicit BlockerInThread(VariableContext level_ = VariableContext::User);
|
||||
~BlockerInThread();
|
||||
|
||||
BlockerInThread(const BlockerInThread &) = delete;
|
||||
BlockerInThread & operator=(const BlockerInThread &) = delete;
|
||||
|
||||
static bool isBlocked(VariableContext current_level)
|
||||
{
|
||||
return counter > 0 && current_level >= level;
|
||||
}
|
||||
};
|
||||
|
||||
/// To be able to avoid MEMORY_LIMIT_EXCEEDED Exception in destructors:
|
||||
/// - either configured memory limit reached
|
||||
/// - or fault injected
|
||||
///
|
||||
/// So this will simply ignore the configured memory limit (and avoid fault injection).
|
||||
///
|
||||
/// NOTE: exception will be silently ignored, no message in log
|
||||
/// (since logging from MemoryTracker::alloc() is tricky)
|
||||
///
|
||||
/// NOTE: MEMORY_LIMIT_EXCEEDED Exception implicitly blocked if
|
||||
/// stack unwinding is currently in progress in this thread (to avoid
|
||||
/// std::terminate()), so you don't need to use it in this case explicitly.
|
||||
struct LockExceptionInThread
|
||||
{
|
||||
private:
|
||||
static thread_local uint64_t counter;
|
||||
static thread_local VariableContext level;
|
||||
static thread_local bool block_fault_injections;
|
||||
|
||||
VariableContext previous_level;
|
||||
bool previous_block_fault_injections;
|
||||
public:
|
||||
/// level_ - block in level and above
|
||||
/// block_fault_injections_ - block in fault injection too
|
||||
explicit LockExceptionInThread(VariableContext level_ = VariableContext::User, bool block_fault_injections_ = true);
|
||||
~LockExceptionInThread();
|
||||
|
||||
LockExceptionInThread(const LockExceptionInThread &) = delete;
|
||||
LockExceptionInThread & operator=(const LockExceptionInThread &) = delete;
|
||||
|
||||
static bool isBlocked(VariableContext current_level, bool fault_injection)
|
||||
{
|
||||
return counter > 0 && current_level >= level && (!fault_injection || block_fault_injections);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
extern MemoryTracker total_memory_tracker;
|
||||
|
16
src/Common/MemoryTrackerBlockerInThread.cpp
Normal file
16
src/Common/MemoryTrackerBlockerInThread.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include <Common/MemoryTrackerBlockerInThread.h>
|
||||
|
||||
// MemoryTrackerBlockerInThread
|
||||
thread_local uint64_t MemoryTrackerBlockerInThread::counter = 0;
|
||||
thread_local VariableContext MemoryTrackerBlockerInThread::level = VariableContext::Global;
|
||||
MemoryTrackerBlockerInThread::MemoryTrackerBlockerInThread(VariableContext level_)
|
||||
: previous_level(level)
|
||||
{
|
||||
++counter;
|
||||
level = level_;
|
||||
}
|
||||
MemoryTrackerBlockerInThread::~MemoryTrackerBlockerInThread()
|
||||
{
|
||||
--counter;
|
||||
level = previous_level;
|
||||
}
|
25
src/Common/MemoryTrackerBlockerInThread.h
Normal file
25
src/Common/MemoryTrackerBlockerInThread.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <Common/VariableContext.h>
|
||||
|
||||
/// To be able to temporarily stop memory tracking from current thread.
|
||||
struct MemoryTrackerBlockerInThread
|
||||
{
|
||||
private:
|
||||
static thread_local uint64_t counter;
|
||||
static thread_local VariableContext level;
|
||||
|
||||
VariableContext previous_level;
|
||||
public:
|
||||
/// level_ - block in level and above
|
||||
explicit MemoryTrackerBlockerInThread(VariableContext level_ = VariableContext::User);
|
||||
~MemoryTrackerBlockerInThread();
|
||||
|
||||
MemoryTrackerBlockerInThread(const MemoryTrackerBlockerInThread &) = delete;
|
||||
MemoryTrackerBlockerInThread & operator=(const MemoryTrackerBlockerInThread &) = delete;
|
||||
|
||||
static bool isBlocked(VariableContext current_level)
|
||||
{
|
||||
return counter > 0 && current_level >= level;
|
||||
}
|
||||
};
|
@ -1,9 +1,9 @@
|
||||
#include "QueryProfiler.h"
|
||||
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <Interpreters/TraceCollector.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/StackTrace.h>
|
||||
#include <Common/TraceCollector.h>
|
||||
#include <Common/thread_local_rng.h>
|
||||
#include <base/logger_useful.h>
|
||||
#include <base/phdr_cache.h>
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <Common/ThreadStatus.h>
|
||||
#include <base/errnoToString.h>
|
||||
#include <Interpreters/OpenTelemetrySpanLog.h>
|
||||
#include <Interpreters/Context.h>
|
||||
|
||||
#include <Poco/Logger.h>
|
||||
#include <base/getThreadId.h>
|
||||
@ -11,6 +12,7 @@
|
||||
|
||||
#include <csignal>
|
||||
#include <mutex>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -1,187 +0,0 @@
|
||||
#include "TraceCollector.h"
|
||||
|
||||
#include <Core/Field.h>
|
||||
#include <IO/ReadBufferFromFileDescriptor.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <IO/WriteBufferFromFileDescriptor.h>
|
||||
#include <IO/WriteBufferFromFileDescriptorDiscardOnFailure.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <Interpreters/TraceLog.h>
|
||||
#include <Poco/Logger.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/PipeFDs.h>
|
||||
#include <Common/StackTrace.h>
|
||||
#include <Common/setThreadName.h>
|
||||
#include <base/logger_useful.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
/// Normally query_id is a UUID (string with a fixed length) but user can provide custom query_id.
|
||||
/// Thus upper bound on query_id length should be introduced to avoid buffer overflow in signal handler.
|
||||
///
|
||||
/// And it cannot be large, since otherwise it will not fit into PIPE_BUF.
|
||||
/// The performance test query ids can be surprisingly long like
|
||||
/// `aggregating_merge_tree_simple_aggregate_function_string.query100.profile100`,
|
||||
/// so make some allowance for them as well.
|
||||
constexpr size_t QUERY_ID_MAX_LEN = 128;
|
||||
static_assert(QUERY_ID_MAX_LEN <= std::numeric_limits<uint8_t>::max());
|
||||
}
|
||||
|
||||
LazyPipeFDs pipe;
|
||||
|
||||
|
||||
TraceCollector::TraceCollector(std::shared_ptr<TraceLog> trace_log_)
|
||||
: trace_log(std::move(trace_log_))
|
||||
{
|
||||
pipe.open();
|
||||
|
||||
/** Turn write end of pipe to non-blocking mode to avoid deadlocks
|
||||
* when QueryProfiler is invoked under locks and TraceCollector cannot pull data from pipe.
|
||||
*/
|
||||
pipe.setNonBlockingWrite();
|
||||
pipe.tryIncreaseSize(1 << 20);
|
||||
|
||||
thread = ThreadFromGlobalPool(&TraceCollector::run, this);
|
||||
}
|
||||
|
||||
|
||||
TraceCollector::~TraceCollector()
|
||||
{
|
||||
if (!thread.joinable())
|
||||
LOG_ERROR(&Poco::Logger::get("TraceCollector"), "TraceCollector thread is malformed and cannot be joined");
|
||||
else
|
||||
stop();
|
||||
|
||||
pipe.close();
|
||||
}
|
||||
|
||||
|
||||
void TraceCollector::collect(TraceType trace_type, const StackTrace & stack_trace, Int64 size)
|
||||
{
|
||||
constexpr size_t buf_size = sizeof(char) /// TraceCollector stop flag
|
||||
+ sizeof(UInt8) /// String size
|
||||
+ QUERY_ID_MAX_LEN /// Maximum query_id length
|
||||
+ sizeof(UInt8) /// Number of stack frames
|
||||
+ sizeof(StackTrace::FramePointers) /// Collected stack trace, maximum capacity
|
||||
+ sizeof(TraceType) /// trace type
|
||||
+ sizeof(UInt64) /// thread_id
|
||||
+ sizeof(Int64); /// size
|
||||
|
||||
/// Write should be atomic to avoid overlaps
|
||||
/// (since recursive collect() is possible)
|
||||
static_assert(PIPE_BUF >= 512);
|
||||
static_assert(buf_size <= 512, "Only write of PIPE_BUF to pipe is atomic and the minimal known PIPE_BUF across supported platforms is 512");
|
||||
|
||||
char buffer[buf_size];
|
||||
WriteBufferFromFileDescriptorDiscardOnFailure out(pipe.fds_rw[1], buf_size, buffer);
|
||||
|
||||
StringRef query_id;
|
||||
UInt64 thread_id;
|
||||
|
||||
if (CurrentThread::isInitialized())
|
||||
{
|
||||
query_id = CurrentThread::getQueryId();
|
||||
query_id.size = std::min(query_id.size, QUERY_ID_MAX_LEN);
|
||||
|
||||
thread_id = CurrentThread::get().thread_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
thread_id = MainThreadStatus::get()->thread_id;
|
||||
}
|
||||
|
||||
writeChar(false, out); /// true if requested to stop the collecting thread.
|
||||
|
||||
writeBinary(static_cast<uint8_t>(query_id.size), out);
|
||||
out.write(query_id.data, query_id.size);
|
||||
|
||||
size_t stack_trace_size = stack_trace.getSize();
|
||||
size_t stack_trace_offset = stack_trace.getOffset();
|
||||
writeIntBinary(UInt8(stack_trace_size - stack_trace_offset), out);
|
||||
for (size_t i = stack_trace_offset; i < stack_trace_size; ++i)
|
||||
writePODBinary(stack_trace.getFramePointers()[i], out);
|
||||
|
||||
writePODBinary(trace_type, out);
|
||||
writePODBinary(thread_id, out);
|
||||
writePODBinary(size, out);
|
||||
|
||||
out.next();
|
||||
}
|
||||
|
||||
|
||||
/** Sends TraceCollector stop message
|
||||
*
|
||||
* Each sequence of data for TraceCollector thread starts with a boolean flag.
|
||||
* If this flag is true, TraceCollector must stop reading trace_pipe and exit.
|
||||
* This function sends flag with a true value to stop TraceCollector gracefully.
|
||||
*/
|
||||
void TraceCollector::stop()
|
||||
{
|
||||
WriteBufferFromFileDescriptor out(pipe.fds_rw[1]);
|
||||
writeChar(true, out);
|
||||
out.next();
|
||||
thread.join();
|
||||
}
|
||||
|
||||
|
||||
void TraceCollector::run()
|
||||
{
|
||||
setThreadName("TraceCollector");
|
||||
|
||||
ReadBufferFromFileDescriptor in(pipe.fds_rw[0]);
|
||||
|
||||
while (true)
|
||||
{
|
||||
char is_last;
|
||||
readChar(is_last, in);
|
||||
if (is_last)
|
||||
break;
|
||||
|
||||
std::string query_id;
|
||||
UInt8 query_id_size = 0;
|
||||
readBinary(query_id_size, in);
|
||||
query_id.resize(query_id_size);
|
||||
in.read(query_id.data(), query_id_size);
|
||||
|
||||
UInt8 trace_size = 0;
|
||||
readIntBinary(trace_size, in);
|
||||
|
||||
Array trace;
|
||||
trace.reserve(trace_size);
|
||||
|
||||
for (size_t i = 0; i < trace_size; ++i)
|
||||
{
|
||||
uintptr_t addr = 0;
|
||||
readPODBinary(addr, in);
|
||||
trace.emplace_back(UInt64(addr));
|
||||
}
|
||||
|
||||
TraceType trace_type;
|
||||
readPODBinary(trace_type, in);
|
||||
|
||||
UInt64 thread_id;
|
||||
readPODBinary(thread_id, in);
|
||||
|
||||
Int64 size;
|
||||
readPODBinary(size, in);
|
||||
|
||||
if (trace_log)
|
||||
{
|
||||
// time and time_in_microseconds are both being constructed from the same timespec so that the
|
||||
// times will be equal up to the precision of a second.
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
||||
UInt64 time = UInt64(ts.tv_sec * 1000000000LL + ts.tv_nsec);
|
||||
UInt64 time_in_microseconds = UInt64((ts.tv_sec * 1000000LL) + (ts.tv_nsec / 1000));
|
||||
TraceLogElement element{time_t(time / 1000000000), time_in_microseconds, time, trace_type, thread_id, query_id, trace, size};
|
||||
trace_log->add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/PipeFDs.h"
|
||||
#include <Common/ThreadPool.h>
|
||||
|
||||
class StackTrace;
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
class Logger;
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
class TraceLog;
|
||||
|
||||
enum class TraceType : uint8_t
|
||||
{
|
||||
Real,
|
||||
CPU,
|
||||
Memory,
|
||||
MemorySample,
|
||||
MemoryPeak,
|
||||
};
|
||||
|
||||
class TraceCollector
|
||||
{
|
||||
public:
|
||||
TraceCollector(std::shared_ptr<TraceLog> trace_log_);
|
||||
~TraceCollector();
|
||||
|
||||
/// Collect a stack trace. This method is signal safe.
|
||||
/// Precondition: the TraceCollector object must be created.
|
||||
/// size - for memory tracing is the amount of memory allocated; for other trace types it is 0.
|
||||
static void collect(TraceType trace_type, const StackTrace & stack_trace, Int64 size);
|
||||
|
||||
private:
|
||||
std::shared_ptr<TraceLog> trace_log;
|
||||
ThreadFromGlobalPool thread;
|
||||
|
||||
void run();
|
||||
void stop();
|
||||
};
|
||||
|
||||
}
|
78
src/Common/TraceSender.cpp
Normal file
78
src/Common/TraceSender.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#include <Common/TraceSender.h>
|
||||
|
||||
#include <IO/WriteBufferFromFileDescriptorDiscardOnFailure.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <Common/StackTrace.h>
|
||||
#include <Common/CurrentThread.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
/// Normally query_id is a UUID (string with a fixed length) but user can provide custom query_id.
|
||||
/// Thus upper bound on query_id length should be introduced to avoid buffer overflow in signal handler.
|
||||
///
|
||||
/// And it cannot be large, since otherwise it will not fit into PIPE_BUF.
|
||||
/// The performance test query ids can be surprisingly long like
|
||||
/// `aggregating_merge_tree_simple_aggregate_function_string.query100.profile100`,
|
||||
/// so make some allowance for them as well.
|
||||
constexpr size_t QUERY_ID_MAX_LEN = 128;
|
||||
static_assert(QUERY_ID_MAX_LEN <= std::numeric_limits<uint8_t>::max());
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
LazyPipeFDs TraceSender::pipe;
|
||||
|
||||
void TraceSender::send(TraceType trace_type, const StackTrace & stack_trace, Int64 size)
|
||||
{
|
||||
constexpr size_t buf_size = sizeof(char) /// TraceCollector stop flag
|
||||
+ sizeof(UInt8) /// String size
|
||||
+ QUERY_ID_MAX_LEN /// Maximum query_id length
|
||||
+ sizeof(UInt8) /// Number of stack frames
|
||||
+ sizeof(StackTrace::FramePointers) /// Collected stack trace, maximum capacity
|
||||
+ sizeof(TraceType) /// trace type
|
||||
+ sizeof(UInt64) /// thread_id
|
||||
+ sizeof(Int64); /// size
|
||||
|
||||
/// Write should be atomic to avoid overlaps
|
||||
/// (since recursive collect() is possible)
|
||||
static_assert(PIPE_BUF >= 512);
|
||||
static_assert(buf_size <= 512, "Only write of PIPE_BUF to pipe is atomic and the minimal known PIPE_BUF across supported platforms is 512");
|
||||
|
||||
char buffer[buf_size];
|
||||
WriteBufferFromFileDescriptorDiscardOnFailure out(pipe.fds_rw[1], buf_size, buffer);
|
||||
|
||||
StringRef query_id;
|
||||
UInt64 thread_id;
|
||||
|
||||
if (CurrentThread::isInitialized())
|
||||
{
|
||||
query_id = CurrentThread::getQueryId();
|
||||
query_id.size = std::min(query_id.size, QUERY_ID_MAX_LEN);
|
||||
|
||||
thread_id = CurrentThread::get().thread_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
thread_id = MainThreadStatus::get()->thread_id;
|
||||
}
|
||||
|
||||
writeChar(false, out); /// true if requested to stop the collecting thread.
|
||||
|
||||
writeBinary(static_cast<uint8_t>(query_id.size), out);
|
||||
out.write(query_id.data, query_id.size);
|
||||
|
||||
size_t stack_trace_size = stack_trace.getSize();
|
||||
size_t stack_trace_offset = stack_trace.getOffset();
|
||||
writeIntBinary(UInt8(stack_trace_size - stack_trace_offset), out);
|
||||
for (size_t i = stack_trace_offset; i < stack_trace_size; ++i)
|
||||
writePODBinary(stack_trace.getFramePointers()[i], out);
|
||||
|
||||
writePODBinary(trace_type, out);
|
||||
writePODBinary(thread_id, out);
|
||||
writePODBinary(size, out);
|
||||
|
||||
out.next();
|
||||
}
|
||||
|
||||
}
|
36
src/Common/TraceSender.h
Normal file
36
src/Common/TraceSender.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <Common/PipeFDs.h>
|
||||
#include <base/types.h>
|
||||
|
||||
class StackTrace;
|
||||
class TraceCollector;
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
enum class TraceType : uint8_t
|
||||
{
|
||||
Real,
|
||||
CPU,
|
||||
Memory,
|
||||
MemorySample,
|
||||
MemoryPeak,
|
||||
};
|
||||
|
||||
/// This is the second part of TraceCollector, that sends stacktrace to the pipe.
|
||||
/// It has been split out to avoid dependency from interpreters part.
|
||||
class TraceSender
|
||||
{
|
||||
public:
|
||||
/// Collect a stack trace. This method is signal safe.
|
||||
/// Precondition: the TraceCollector object must be created.
|
||||
/// size - for memory tracing is the amount of memory allocated; for other trace types it is 0.
|
||||
static void send(TraceType trace_type, const StackTrace & stack_trace, Int64 size);
|
||||
|
||||
private:
|
||||
friend class TraceCollector;
|
||||
static LazyPipeFDs pipe;
|
||||
};
|
||||
|
||||
}
|
@ -2,9 +2,32 @@ include("${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake")
|
||||
|
||||
add_headers_and_sources(clickhouse_common_zookeeper .)
|
||||
|
||||
# for clickhouse server
|
||||
add_library(clickhouse_common_zookeeper ${clickhouse_common_zookeeper_headers} ${clickhouse_common_zookeeper_sources})
|
||||
target_compile_definitions (clickhouse_common_zookeeper PRIVATE -DZOOKEEPER_LOG)
|
||||
target_link_libraries (clickhouse_common_zookeeper
|
||||
PUBLIC
|
||||
clickhouse_common_io
|
||||
common
|
||||
PRIVATE
|
||||
string_utils
|
||||
)
|
||||
# To avoid circular dependency from interpreters.
|
||||
if (OS_DARWIN)
|
||||
target_link_libraries (clickhouse_common_zookeeper PRIVATE -Wl,-undefined,dynamic_lookup)
|
||||
else()
|
||||
target_link_libraries (clickhouse_common_zookeeper PRIVATE -Wl,--unresolved-symbols=ignore-all)
|
||||
endif()
|
||||
|
||||
target_link_libraries (clickhouse_common_zookeeper PUBLIC clickhouse_common_io common PRIVATE string_utils)
|
||||
# for examples -- no logging (to avoid extra dependencies)
|
||||
add_library(clickhouse_common_zookeeper_no_log ${clickhouse_common_zookeeper_headers} ${clickhouse_common_zookeeper_sources})
|
||||
target_link_libraries (clickhouse_common_zookeeper_no_log
|
||||
PUBLIC
|
||||
clickhouse_common_io
|
||||
common
|
||||
PRIVATE
|
||||
string_utils
|
||||
)
|
||||
|
||||
if (ENABLE_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <Common/ZooKeeper/ZooKeeperCommon.h>
|
||||
#include <Common/ZooKeeper/ZooKeeperIO.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <IO/WriteBufferFromString.h>
|
||||
#include <IO/Operators.h>
|
||||
|
@ -49,6 +49,8 @@ static constexpr int32_t PASSWORD_LENGTH = 16;
|
||||
/// but it can be raised up, so we have a slightly larger limit on our side.
|
||||
static constexpr int32_t MAX_STRING_OR_ARRAY_SIZE = 1 << 28; /// 256 MiB
|
||||
static constexpr int32_t DEFAULT_SESSION_TIMEOUT_MS = 30000;
|
||||
static constexpr int32_t DEFAULT_MIN_SESSION_TIMEOUT_MS = 10000;
|
||||
static constexpr int32_t DEFAULT_MAX_SESSION_TIMEOUT_MS = 100000;
|
||||
static constexpr int32_t DEFAULT_OPERATION_TIMEOUT_MS = 10000;
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user