This commit is contained in:
Clément Rodriguez 2020-02-19 15:23:17 +01:00
commit cdd99d7f23
3774 changed files with 102711 additions and 71800 deletions

View File

@ -52,12 +52,12 @@ IncludeCategories:
ReflowComments: false
AlignEscapedNewlinesLeft: false
AlignEscapedNewlines: DontAlign
AlignTrailingComments: true
# Not changed:
AccessModifierOffset: -4
AlignConsecutiveAssignments: false
AlignOperands: false
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false

2
.github/CODEOWNERS vendored
View File

@ -1,4 +1,2 @@
dbms/* @ClickHouse/core-assigner
utils/* @ClickHouse/core-assigner
docs/* @ClickHouse/docs
docs/zh/* @ClickHouse/docs-zh

View File

@ -7,16 +7,20 @@ Changelog category (leave one):
- Performance Improvement
- Backward Incompatible Change
- Build/Testing/Packaging Improvement
- Documentation
- Documentation (changelog entry is not required)
- Other
- Non-significant (changelog entry is not needed)
- Non-significant (changelog entry is not required)
Changelog entry (up to few sentences, not needed for non-significant PRs):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
...
Detailed description (optional):
Detailed description / Documentation draft:
...
By adding documentation, you'll allow users to try your new feature immediately, not when someone else will have time to document it later. Documentation is necessary for all features that affect user experience in any way. You can add brief documentation draft above, or add documentation right into your patch as Markdown files in [docs](https://github.com/ClickHouse/ClickHouse/tree/master/docs) folder.
If you are doing this for the first time, it's recommended to read the lightweight [Contributing to ClickHouse Documentation](https://github.com/ClickHouse/ClickHouse/tree/master/docs/README.md) guide first.

10
.gitignore vendored
View File

@ -13,12 +13,15 @@
/build_*
/build-*
/docs/build
/docs/publish
/docs/edit
/docs/website
/docs/tools/venv/
/docs/en/development/build/
/docs/ru/development/build/
/docs/en/single.md
/docs/ru/single.md
/docs/zh/single.md
/docs/ja/single.md
/docs/fa/single.md
# callgrind files
callgrind.out.*
@ -244,6 +247,9 @@ website/package-lock.json
# ccls cache
/.ccls-cache
# clangd cache
/.clangd
/compile_commands.json
# Toolchains

54
.gitmodules vendored
View File

@ -1,6 +1,7 @@
[submodule "contrib/poco"]
path = contrib/poco
url = https://github.com/ClickHouse-Extras/poco
branch = clickhouse
[submodule "contrib/zstd"]
path = contrib/zstd
url = https://github.com/facebook/zstd.git
@ -28,9 +29,6 @@
[submodule "contrib/re2"]
path = contrib/re2
url = https://github.com/google/re2.git
[submodule "contrib/ssl"]
path = contrib/ssl
url = https://github.com/ClickHouse-Extras/ssl.git
[submodule "contrib/llvm"]
path = contrib/llvm
url = https://github.com/ClickHouse-Extras/llvm
@ -51,7 +49,7 @@
url = https://github.com/ClickHouse-Extras/boost.git
[submodule "contrib/base64"]
path = contrib/base64
url = https://github.com/aklomp/base64.git
url = https://github.com/powturbo/Turbo-Base64.git
[submodule "contrib/arrow"]
path = contrib/arrow
url = https://github.com/apache/arrow
@ -69,10 +67,10 @@
url = https://github.com/ClickHouse-Extras/libgsasl.git
[submodule "contrib/libcxx"]
path = contrib/libcxx
url = https://github.com/llvm-mirror/libcxx.git
url = https://github.com/ClickHouse-Extras/libcxx.git
[submodule "contrib/libcxxabi"]
path = contrib/libcxxabi
url = https://github.com/llvm-mirror/libcxxabi.git
url = https://github.com/ClickHouse-Extras/libcxxabi.git
[submodule "contrib/snappy"]
path = contrib/snappy
url = https://github.com/google/snappy
@ -106,3 +104,47 @@
[submodule "contrib/sparsehash-c11"]
path = contrib/sparsehash-c11
url = https://github.com/sparsehash/sparsehash-c11.git
[submodule "contrib/grpc"]
path = contrib/grpc
url = https://github.com/ClickHouse-Extras/grpc.git
branch = v1.25.0
[submodule "contrib/aws"]
path = contrib/aws
url = https://github.com/aws/aws-sdk-cpp.git
[submodule "aws-c-event-stream"]
path = contrib/aws-c-event-stream
url = https://github.com/awslabs/aws-c-event-stream.git
[submodule "aws-c-common"]
path = contrib/aws-c-common
url = https://github.com/awslabs/aws-c-common.git
[submodule "aws-checksums"]
path = contrib/aws-checksums
url = https://github.com/awslabs/aws-checksums.git
[submodule "contrib/curl"]
path = contrib/curl
url = https://github.com/curl/curl.git
[submodule "contrib/openssl"]
path = contrib/openssl
url = https://github.com/ClickHouse-Extras/openssl.git
[submodule "contrib/icudata"]
path = contrib/icudata
url = https://github.com/ClickHouse-Extras/icudata.git
[submodule "contrib/icu"]
path = contrib/icu
url = https://github.com/unicode-org/icu.git
[submodule "contrib/flatbuffers"]
path = contrib/flatbuffers
url = https://github.com/google/flatbuffers.git
[submodule "contrib/libc-headers"]
path = contrib/libc-headers
url = https://github.com/ClickHouse-Extras/libc-headers.git
[submodule "contrib/replxx"]
path = contrib/replxx
url = https://github.com/AmokHuginnsson/replxx.git
[submodule "contrib/ryu"]
path = contrib/ryu
url = https://github.com/ClickHouse-Extras/ryu.git
[submodule "contrib/avro"]
path = contrib/avro
url = https://github.com/ClickHouse-Extras/avro.git
ignore = untracked

45
AUTHORS
View File

@ -1,43 +1,2 @@
The following authors have created the source code of "ClickHouse"
published and distributed by YANDEX LLC as the owner:
Alexander Makarov <asealback@yandex-team.ru>
Alexander Prudaev <aprudaev@yandex-team.ru>
Alexey Arno <af-arno@yandex-team.ru>
Alexey Milovidov <milovidov@yandex-team.ru>
Alexey Tronov <vkusny@yandex-team.ru>
Alexey Vasiliev <loudhorr@yandex-team.ru>
Alexey Zatelepin <ztlpn@yandex-team.ru>
Amy Krishnevsky <krishnevsky@yandex-team.ru>
Andrey M <hertz@yandex-team.ru>
Andrey Mironov <hertz@yandex-team.ru>
Andrey Urusov <drobus@yandex-team.ru>
Anton Tikhonov <rokerjoker@yandex-team.ru>
Dmitry Bilunov <kmeaw@yandex-team.ru>
Dmitry Galuza <galuza@yandex-team.ru>
Eugene Konkov <konkov@yandex-team.ru>
Evgeniy Gatov <egatov@yandex-team.ru>
Ilya Khomutov <robert@yandex-team.ru>
Ilya Korolev <breeze@yandex-team.ru>
Ivan Blinkov <blinkov@yandex-team.ru>
Maxim Nikulin <mnikulin@yandex-team.ru>
Michael Kolupaev <mkolupaev@yandex-team.ru>
Michael Razuvaev <razuvaev@yandex-team.ru>
Nikolai Kochetov <nik-kochetov@yandex-team.ru>
Nikolay Vasiliev <lonlylocly@yandex-team.ru>
Nikolay Volosatov <bamx23@yandex-team.ru>
Pavel Artemkin <stanly@yandex-team.ru>
Pavel Kartaviy <kartavyy@yandex-team.ru>
Roman Nozdrin <drrtuy@yandex-team.ru>
Roman Peshkurov <peshkurov@yandex-team.ru>
Sergey Fedorov <fets@yandex-team.ru>
Sergey Lazarev <hamilkar@yandex-team.ru>
Sergey Magidovich <mgsergio@yandex-team.ru>
Sergey Serebryanik <serebrserg@yandex-team.ru>
Sergey Veletskiy <velom@yandex-team.ru>
Vasily Okunev <okunev@yandex-team.ru>
Vitaliy Lyudvichenko <vludv@yandex-team.ru>
Vladimir Chebotarev <chebotarev@yandex-team.ru>
Vsevolod Orlov <vorloff@yandex-team.ru>
Vyacheslav Alipov <alipov@yandex-team.ru>
Yuriy Galitskiy <orantius@yandex-team.ru>
To see the list of authors who created the source code of ClickHouse, published and distributed by YANDEX LLC as the owner,
run "SELECT * FROM system.contributors;" query on any ClickHouse server.

File diff suppressed because it is too large Load Diff

View File

@ -95,6 +95,8 @@ if (CMAKE_GENERATOR STREQUAL "Ninja")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always")
endif ()
include (cmake/add_warning.cmake)
if (NOT MSVC)
set (COMMON_WARNING_FLAGS "${COMMON_WARNING_FLAGS} -Wall") # -Werror is also added inside directories with our own code.
endif ()
@ -176,7 +178,9 @@ if (ARCH_NATIVE)
set (COMPILER_FLAGS "${COMPILER_FLAGS} -march=native")
endif ()
set (CMAKE_CXX_STANDARD 17)
# cmake < 3.12 doesn't supoprt 20. We'll set CMAKE_CXX_FLAGS for now
# set (CMAKE_CXX_STANDARD 20)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2a")
set (CMAKE_CXX_EXTENSIONS 0) # https://cmake.org/cmake/help/latest/prop_tgt/CXX_EXTENSIONS.html#prop_tgt:CXX_EXTENSIONS
set (CMAKE_CXX_STANDARD_REQUIRED ON)
@ -198,14 +202,21 @@ if(WITH_COVERAGE AND COMPILER_GCC)
endif()
set (CMAKE_BUILD_COLOR_MAKEFILE ON)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS} ${PLATFORM_EXTRA_CXX_FLAG} -fno-omit-frame-pointer ${COMMON_WARNING_FLAGS} ${CXX_WARNING_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS} ${PLATFORM_EXTRA_CXX_FLAG} ${COMMON_WARNING_FLAGS} ${CXX_WARNING_FLAGS}")
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 ${CMAKE_CXX_FLAGS_ADD}")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g3 -ggdb3 -fno-inline ${CMAKE_CXX_FLAGS_ADD}")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILER_FLAGS} -fno-omit-frame-pointer ${COMMON_WARNING_FLAGS} ${CMAKE_C_FLAGS_ADD}")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILER_FLAGS} ${COMMON_WARNING_FLAGS} ${CMAKE_C_FLAGS_ADD}")
set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 ${CMAKE_C_FLAGS_ADD}")
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g3 -ggdb3 -fno-inline ${CMAKE_C_FLAGS_ADD}")
if (COMPILER_CLANG)
# Exception unwinding doesn't work in clang release build without this option
# TODO investigate that
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer")
endif ()
option (ENABLE_LIBRARIES "Enable all libraries (Global default switch)" ON)
option (UNBUNDLED "Try find all libraries in system. We recommend to avoid this mode for production builds, because we cannot guarantee exact versions and variants of libraries your system has installed. This mode exists for enthusiastic developers who search for trouble. Also it is useful for maintainers of OS packages." OFF)
@ -215,9 +226,13 @@ else ()
set(NOT_UNBUNDLED 1)
endif ()
# Using system libs can cause lot of warnings in includes.
if (UNBUNDLED OR NOT (OS_LINUX OR APPLE) OR ARCH_32)
# Using system libs can cause a lot of warnings in includes (on macro expansion).
if (UNBUNDLED OR NOT (OS_LINUX OR OS_DARWIN) OR ARCH_32)
option (NO_WERROR "Disable -Werror compiler option" ON)
if (NOT NO_WERROR)
add_warning(error)
endif ()
endif ()
# Make this extra-checks for correct library dependencies.
@ -241,8 +256,16 @@ endif ()
string (TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC)
set (CMAKE_POSTFIX_VARIABLE "CMAKE_${CMAKE_BUILD_TYPE_UC}_POSTFIX")
if (NOT MAKE_STATIC_LIBRARIES)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (MAKE_STATIC_LIBRARIES)
set (CMAKE_POSITION_INDEPENDENT_CODE OFF)
if (OS_LINUX)
# Slightly more efficient code can be generated
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-pie")
set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fno-pie")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no-pie")
endif ()
else ()
set (CMAKE_POSITION_INDEPENDENT_CODE ON)
endif ()
# Using "include-what-you-use" tool.
@ -307,9 +330,7 @@ include (cmake/find/poco.cmake)
include (cmake/find/lz4.cmake)
include (cmake/find/xxhash.cmake)
include (cmake/find/sparsehash.cmake)
include (cmake/find/rt.cmake)
include (cmake/find/execinfo.cmake)
include (cmake/find/readline_edit.cmake)
include (cmake/find/re2.cmake)
include (cmake/find/libgsasl.cmake)
include (cmake/find/rdkafka.cmake)
@ -323,8 +344,10 @@ endif()
include (cmake/find/libxml2.cmake)
include (cmake/find/brotli.cmake)
include (cmake/find/protobuf.cmake)
include (cmake/find/grpc.cmake)
include (cmake/find/pdqsort.cmake)
include (cmake/find/hdfs3.cmake) # uses protobuf
include (cmake/find/s3.cmake)
include (cmake/find/consistent-hashing.cmake)
include (cmake/find/base64.cmake)
include (cmake/find/parquet.cmake)
@ -333,6 +356,7 @@ include (cmake/find/simdjson.cmake)
include (cmake/find/rapidjson.cmake)
include (cmake/find/fastops.cmake)
include (cmake/find/orc.cmake)
include (cmake/find/avro.cmake)
find_contrib_lib(cityhash)
find_contrib_lib(farmhash)
@ -344,28 +368,15 @@ if (ENABLE_TESTS)
endif ()
# Need to process before "contrib" dir:
include (libs/libcommon/cmake/find_gperftools.cmake)
include (libs/libcommon/cmake/find_jemalloc.cmake)
include (libs/libcommon/cmake/find_cctz.cmake)
include (libs/libmysqlxx/cmake/find_mysqlclient.cmake)
include (cmake/find/jemalloc.cmake)
include (cmake/find/cctz.cmake)
include (cmake/find/mysqlclient.cmake)
# When testing for memory leaks with Valgrind, don't link tcmalloc or jemalloc.
if (USE_JEMALLOC)
message (STATUS "Link jemalloc: ${JEMALLOC_LIBRARIES}")
set (MALLOC_LIBRARIES ${JEMALLOC_LIBRARIES})
elseif (USE_TCMALLOC)
if (DEBUG_TCMALLOC AND NOT GPERFTOOLS_TCMALLOC_MINIMAL_DEBUG)
message (FATAL_ERROR "Requested DEBUG_TCMALLOC but debug library is not found. You should install Google Perftools. Example: sudo apt-get install libgoogle-perftools-dev")
endif ()
if (DEBUG_TCMALLOC AND GPERFTOOLS_TCMALLOC_MINIMAL_DEBUG)
message (STATUS "Link libtcmalloc_minimal_debug for testing: ${GPERFTOOLS_TCMALLOC_MINIMAL_DEBUG}")
set (MALLOC_LIBRARIES ${GPERFTOOLS_TCMALLOC_MINIMAL_DEBUG})
else ()
message (STATUS "Link libtcmalloc_minimal: ${GPERFTOOLS_TCMALLOC_MINIMAL}")
set (MALLOC_LIBRARIES ${GPERFTOOLS_TCMALLOC_MINIMAL})
endif ()
elseif (SANITIZE)
message (STATUS "Will use ${SANITIZE} sanitizer.")
elseif (OS_LINUX)
@ -382,20 +393,16 @@ add_subdirectory (contrib EXCLUDE_FROM_ALL)
macro (add_executable target)
# invoke built-in add_executable
_add_executable (${ARGV})
# explicitly acquire and interpose malloc symbols by clickhouse_malloc
_add_executable (${ARGV} $<TARGET_OBJECTS:clickhouse_malloc>)
get_target_property (type ${target} TYPE)
if (${type} STREQUAL EXECUTABLE)
file (RELATIVE_PATH dir ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
if (${dir} MATCHES "^dbms")
# Only interpose operator::new/delete for dbms executables (MemoryTracker stuff)
target_link_libraries (${target} PRIVATE clickhouse_new_delete ${MALLOC_LIBRARIES})
else ()
target_link_libraries (${target} PRIVATE ${MALLOC_LIBRARIES})
endif ()
# operator::new/delete for executables (MemoryTracker stuff)
target_link_libraries (${target} PRIVATE clickhouse_new_delete ${MALLOC_LIBRARIES})
endif()
endmacro()
add_subdirectory (libs)
add_subdirectory (base)
add_subdirectory (utils)
add_subdirectory (dbms)

View File

@ -1,24 +1,30 @@
# Contributing to ClickHouse
## Technical info
Developer guide for writing code for ClickHouse is published on official website alongside the usage and operations documentation:
https://clickhouse.yandex/docs/en/development/architecture/
ClickHouse is an open project, and you can contribute to it in many ways. You can help with ideas, code, or documentation. We appreciate any efforts that help us to make the project better.
## Legal info
Thank you.
In order for us (YANDEX LLC) to accept patches and other contributions from you, you will have to adopt our Yandex Contributor License Agreement (the "**CLA**"). The current version of the CLA you may find here:
## Technical Info
We have a [developer's guide](https://clickhouse.yandex/docs/en/development/developer_instruction/) for writing code for ClickHouse. Besides this guide, you can find [Overview of ClickHouse Architecture](https://clickhouse.yandex/docs/en/development/architecture/) and instructions on how to build ClickHouse in different environments.
If you want to contribute to documentation, read the [Contributing to ClickHouse Documentation](docs/README.md) guide.
## Legal Info
In order for us (YANDEX LLC) to accept patches and other contributions from you, you may adopt our Yandex Contributor License Agreement (the "**CLA**"). The current version of the CLA you may find here:
1) https://yandex.ru/legal/cla/?lang=en (in English) and
2) https://yandex.ru/legal/cla/?lang=ru (in Russian).
By adopting the CLA, you state the following:
* You obviously wish and are willingly licensing your contributions to us for our open source projects under the terms of the CLA,
* You has read the terms and conditions of the CLA and agree with them in full,
* You have read the terms and conditions of the CLA and agree with them in full,
* You are legally able to provide and license your contributions as stated,
* We may use your contributions for our open source projects and for any other our project too,
* We rely on your assurances concerning the rights of third parties in relation to your contributes.
* We rely on your assurances concerning the rights of third parties in relation to your contributions.
If you agree with these principles, please read and adopt our CLA. By providing us your contributions, you hereby declare that you has already read and adopt our CLA, and we may freely merge your contributions with our corresponding open source project and use it in further in accordance with terms and conditions of the CLA.
If you agree with these principles, please read and adopt our CLA. By providing us your contributions, you hereby declare that you have already read and adopt our CLA, and we may freely merge your contributions with our corresponding open source project and use it in further in accordance with terms and conditions of the CLA.
If you have already adopted terms and conditions of the CLA, you are able to provide your contributes. When you submit your pull request, please add the following information into it:
@ -31,4 +37,7 @@ Replace the bracketed text as follows:
It is enough to provide us such notification once.
If you don't agree with the CLA, you still can open a pull request to provide your contributions.
As an alternative, you can provide DCO instead of CLA. You can find the text of DCO here: https://developercertificate.org/
It is enough to read and copy it verbatim to your pull request.
If you don't agree with the CLA and don't want to provide DCO, you still can open a pull request to provide your contributions.

View File

@ -1,4 +1,4 @@
Copyright 2016-2019 Yandex LLC
Copyright 2016-2020 Yandex LLC
Apache License
Version 2.0, January 2004
@ -188,7 +188,7 @@ Copyright 2016-2019 Yandex LLC
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016-2019 Yandex LLC
Copyright 2016-2020 Yandex LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,21 +1,17 @@
[![ClickHouse — open source distributed column-oriented DBMS](https://github.com/ClickHouse/ClickHouse/raw/master/website/images/logo-400x240.png)](https://clickhouse.yandex)
[![ClickHouse — open source distributed column-oriented DBMS](https://github.com/ClickHouse/ClickHouse/raw/master/website/images/logo-400x240.png)](https://clickhouse.tech)
ClickHouse is an open-source column-oriented database management system that allows generating analytical data reports in real time.
## Useful Links
* [Official website](https://clickhouse.yandex/) has quick high-level overview of ClickHouse on main page.
* [Tutorial](https://clickhouse.yandex/tutorial.html) shows how to set up and query small ClickHouse cluster.
* [Documentation](https://clickhouse.yandex/docs/en/) provides more in-depth information.
* [Official website](https://clickhouse.tech/) has quick high-level overview of ClickHouse on main page.
* [Tutorial](https://clickhouse.tech/docs/en/getting_started/tutorial/) shows how to set up and query small ClickHouse cluster.
* [Documentation](https://clickhouse.tech/docs/en/) provides more in-depth information.
* [YouTube channel](https://www.youtube.com/c/ClickHouseDB) has a lot of content about ClickHouse in video format.
* [Blog](https://clickhouse.yandex/blog/en/) contains various ClickHouse-related articles, as well as announces and reports about events.
* [Contacts](https://clickhouse.yandex/#contacts) can help to get your questions answered if there are any.
* [Contacts](https://clickhouse.tech/#contacts) can help to get your questions answered if there are any.
* You can also [fill this form](https://forms.yandex.com/surveys/meet-yandex-clickhouse-team/) to meet Yandex ClickHouse team in person.
## Upcoming Events
* [ClickHouse Meetup in Tokyo](https://clickhouse.connpass.com/event/147001/) on November 14.
* [ClickHouse Meetup in Istanbul](https://www.eventbrite.com/e/clickhouse-meetup-istanbul-create-blazing-fast-experiences-w-clickhouse-tickets-73101120419) on November 19.
* [ClickHouse Meetup in Ankara](https://www.eventbrite.com/e/clickhouse-meetup-ankara-create-blazing-fast-experiences-w-clickhouse-tickets-73100530655) on November 21.
* [ClickHouse Meetup in Singapore](https://www.meetup.com/Singapore-Clickhouse-Meetup-Group/events/265085331/) on November 23.
* [ClickHouse Meetup in San Francisco](https://www.eventbrite.com/e/clickhouse-december-meetup-registration-78642047481) on December 3.
## Upcoming Events
* [ClickHouse Meetup in Athens](https://www.meetup.com/Athens-Big-Data/events/268379195/) on March 5.

17
base/CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
add_subdirectory (common)
add_subdirectory (loggers)
add_subdirectory (daemon)
if (USE_INTERNAL_MEMCPY)
add_subdirectory (memcpy)
endif()
if (USE_MYSQL)
add_subdirectory (mysqlxx)
endif ()
if (USE_INTERNAL_CONSISTENT_HASHING_LIBRARY)
add_subdirectory (consistent-hashing)
endif ()
add_subdirectory (consistent-hashing-sumbur)
add_subdirectory (widechar_width)

View File

@ -0,0 +1,64 @@
configure_file (config_common.h.in config_common.h)
set (SRCS
argsToConfig.cpp
coverage.cpp
DateLUT.cpp
DateLUTImpl.cpp
demangle.cpp
getMemoryAmount.cpp
getThreadId.cpp
JSON.cpp
LineReader.cpp
mremap.cpp
phdr_cache.cpp
preciseExp10.c
setTerminalEcho.cpp
shift10.cpp
sleep.cpp
)
if (ENABLE_REPLXX)
set (SRCS ${SRCS}
ReplxxLineReader.cpp
ReplxxLineReader.h
)
endif ()
add_library (common ${SRCS})
target_include_directories(common PUBLIC .. ${CMAKE_CURRENT_BINARY_DIR}/..)
if (USE_INTERNAL_MEMCPY)
target_link_libraries (common PRIVATE memcpy)
endif ()
if(CCTZ_INCLUDE_DIR)
target_include_directories(common BEFORE PRIVATE ${CCTZ_INCLUDE_DIR})
endif()
if (NOT USE_INTERNAL_BOOST_LIBRARY)
target_include_directories (common SYSTEM BEFORE PUBLIC ${Boost_INCLUDE_DIRS})
endif ()
if(NOT USE_INTERNAL_POCO_LIBRARY)
target_include_directories (common SYSTEM BEFORE PUBLIC ${Poco_Foundation_INCLUDE_DIR})
endif()
if(CCTZ_LIBRARY)
target_link_libraries(common PRIVATE ${CCTZ_LIBRARY})
endif()
target_link_libraries(common PUBLIC replxx)
target_link_libraries (common
PUBLIC
${Poco_Util_LIBRARY}
${Poco_Foundation_LIBRARY}
${CITYHASH_LIBRARIES}
${Boost_SYSTEM_LIBRARY}
)
if (ENABLE_TESTS)
add_subdirectory (tests)
endif ()

View File

@ -391,9 +391,9 @@ public:
/*
The bits in week_mode has the following meaning:
WeekModeFlag::MONDAY_FIRST (0) If not set Sunday is first day of week
If set Monday is first day of week
WeekModeFlag::YEAR (1) If not set Week is in range 0-53
WeekModeFlag::MONDAY_FIRST (0) If not set Sunday is first day of week
If set Monday is first day of week
WeekModeFlag::YEAR (1) If not set Week is in range 0-53
Week 0 is returned for the the last week of the previous year (for
a date at start of january) In this case one can get 53 for the
@ -401,19 +401,19 @@ public:
relevant for the given year. Note that this flag is only
releveant if WeekModeFlag::JANUARY is not set.
If set Week is in range 1-53.
If set Week is in range 1-53.
In this case one may get week 53 for a date in January (when
the week is that last week of previous year) and week 1 for a
date in December.
WeekModeFlag::FIRST_WEEKDAY (2) If not set Weeks are numbered according
WeekModeFlag::FIRST_WEEKDAY (2) If not set Weeks are numbered according
to ISO 8601:1988
If set The week that contains the first
If set The week that contains the first
'first-day-of-week' is week 1.
WeekModeFlag::NEWYEAR_DAY (3) If not set no meaning
If set The week that contains the January 1 is week 1.
WeekModeFlag::NEWYEAR_DAY (3) If not set no meaning
If set The week that contains the January 1 is week 1.
Week is in range 1-53.
And ignore WeekModeFlag::YEAR, WeekModeFlag::FIRST_WEEKDAY
@ -666,7 +666,7 @@ public:
inline DayNum makeDayNum(UInt16 year, UInt8 month, UInt8 day_of_month) const
{
if (unlikely(year < DATE_LUT_MIN_YEAR || year > DATE_LUT_MAX_YEAR || month < 1 || month > 12 || day_of_month < 1 || day_of_month > 31))
return DayNum(0);
return DayNum(0); // TODO (nemkov, DateTime64 phase 2): implement creating real date for year outside of LUT range.
return DayNum(years_months_lut[(year - DATE_LUT_MIN_YEAR) * 12 + month - 1] + day_of_month - 1);
}

View File

@ -12,9 +12,9 @@
class KillingErrorHandler : public Poco::ErrorHandler
{
public:
void exception(const Poco::Exception &) { std::terminate(); }
void exception(const std::exception &) { std::terminate(); }
void exception() { std::terminate(); }
void exception(const Poco::Exception &) override { std::terminate(); }
void exception(const std::exception &) override { std::terminate(); }
void exception() override { std::terminate(); }
};
@ -23,9 +23,9 @@ public:
class ServerErrorHandler : public Poco::ErrorHandler
{
public:
void exception(const Poco::Exception &) { logException(); }
void exception(const std::exception &) { logException(); }
void exception() { logException(); }
void exception(const Poco::Exception &) override { logException(); }
void exception(const std::exception &) override { logException(); }
void exception() override { logException(); }
private:
Logger * log = &Logger::get("ServerErrorHandler");

View File

@ -399,7 +399,7 @@ JSON::Pos JSON::skipElement() const
ElementType type = getType();
switch(type)
switch (type)
{
case TYPE_NULL:
return skipNull();
@ -587,7 +587,7 @@ std::string JSON::getString() const
++s;
checkPos(s);
switch(*s)
switch (*s)
{
case '"':
buf += '"';
@ -665,7 +665,7 @@ StringRef JSON::getRawString() const
if (*s != '"')
throw JSONException(std::string("JSON: expected \", got ") + *s);
while (++s != ptr_end && *s != '"');
if (s != ptr_end )
if (s != ptr_end)
return StringRef(ptr_begin + 1, s - ptr_begin - 1);
throw JSONException("JSON: incorrect syntax (expected end of string, found end of JSON).");
}

156
base/common/LineReader.cpp Normal file
View File

@ -0,0 +1,156 @@
#include <common/LineReader.h>
#include <iostream>
#include <string_view>
#include <string.h>
#include <unistd.h>
#ifdef OS_LINUX
/// We can detect if code is linked with one or another readline variants or open the library dynamically.
# include <dlfcn.h>
extern "C"
{
char * readline(const char *) __attribute__((__weak__));
char * (*readline_ptr)(const char *) = readline;
}
#endif
namespace
{
/// Trim ending whitespace inplace
void trim(String & s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), s.end());
}
/// Check if multi-line query is inserted from the paste buffer.
/// Allows delaying the start of query execution until the entirety of query is inserted.
bool hasInputData()
{
timeval timeout = {0, 0};
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
return select(1, &fds, nullptr, nullptr, &timeout) == 1;
}
}
LineReader::Suggest::WordsRange LineReader::Suggest::getCompletions(const String & prefix, size_t prefix_length) const
{
if (!ready)
return std::make_pair(words.end(), words.end());
std::string_view last_word;
auto last_word_pos = prefix.find_last_of(word_break_characters);
if (std::string::npos == last_word_pos)
last_word = prefix;
else
last_word = std::string_view(prefix).substr(last_word_pos + 1, std::string::npos);
/// last_word can be empty.
return std::equal_range(
words.begin(), words.end(), last_word, [prefix_length](std::string_view s, std::string_view prefix_searched)
{
return strncmp(s.data(), prefix_searched.data(), prefix_length) < 0;
});
}
LineReader::LineReader(const String & history_file_path_, char extender_, char delimiter_)
: history_file_path(history_file_path_), extender(extender_), delimiter(delimiter_)
{
/// FIXME: check extender != delimiter
}
String LineReader::readLine(const String & first_prompt, const String & second_prompt)
{
String line;
bool is_multiline = false;
while (auto status = readOneLine(is_multiline ? second_prompt : first_prompt))
{
if (status == RESET_LINE)
{
line.clear();
is_multiline = false;
continue;
}
if (input.empty())
{
if (!line.empty() && !delimiter && !hasInputData())
break;
else
continue;
}
is_multiline = (input.back() == extender) || (delimiter && input.back() != delimiter) || hasInputData();
if (input.back() == extender)
{
input = input.substr(0, input.size() - 1);
trim(input);
if (input.empty())
continue;
}
line += (line.empty() ? "" : " ") + input;
if (!is_multiline)
break;
}
if (!line.empty() && line != prev_line)
{
addToHistory(line);
prev_line = line;
}
return line;
}
LineReader::InputStatus LineReader::readOneLine(const String & prompt)
{
input.clear();
#ifdef OS_LINUX
if (!readline_ptr)
{
for (auto name : {"libreadline.so", "libreadline.so.0", "libeditline.so", "libeditline.so.0"})
{
void * dl_handle = dlopen(name, RTLD_LAZY);
if (dl_handle)
{
readline_ptr = reinterpret_cast<char * (*)(const char *)>(dlsym(dl_handle, "readline"));
if (readline_ptr)
{
break;
}
}
}
}
/// Minimal support for readline
if (readline_ptr)
{
char * line_read = (*readline_ptr)(prompt.c_str());
if (!line_read)
return ABORT;
input = line_read;
}
else
#endif
{
std::cout << prompt;
std::getline(std::cin, input);
if (!std::cin.good())
return ABORT;
}
trim(input);
return INPUT_LINE;
}

55
base/common/LineReader.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
#include <common/Types.h>
#include <atomic>
#include <vector>
class LineReader
{
public:
class Suggest
{
protected:
using Words = std::vector<std::string>;
using WordsRange = std::pair<Words::const_iterator, Words::const_iterator>;
Words words;
std::atomic<bool> ready{false};
public:
/// Get iterators for the matched range of words if any.
WordsRange getCompletions(const String & prefix, size_t prefix_length) const;
};
LineReader(const String & history_file_path, char extender, char delimiter = 0); /// if delimiter != 0, then it's multiline mode
virtual ~LineReader() {}
/// Reads the whole line until delimiter (in multiline mode) or until the last line without extender.
/// If resulting line is empty, it means the user interrupted the input.
/// Non-empty line is appended to history - without duplication.
/// Typical delimiter is ';' (semicolon) and typical extender is '\' (backslash).
String readLine(const String & first_prompt, const String & second_prompt);
protected:
enum InputStatus
{
ABORT = 0,
RESET_LINE,
INPUT_LINE,
};
const String history_file_path;
static constexpr char word_break_characters[] = " \t\n\r\"\\'`@$><=;|&{(.";
String input;
private:
const char extender;
const char delimiter;
String prev_line;
virtual InputStatus readOneLine(const String & prompt);
virtual void addToHistory(const String &) {}
};

View File

@ -0,0 +1,57 @@
#include <common/ReplxxLineReader.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
namespace
{
/// Trim ending whitespace inplace
void trim(String & s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), s.end());
}
}
ReplxxLineReader::ReplxxLineReader(const Suggest & suggest, const String & history_file_path_, char extender_, char delimiter_)
: LineReader(history_file_path_, extender_, delimiter_)
{
if (!history_file_path.empty())
rx.history_load(history_file_path);
auto callback = [&suggest] (const String & context, size_t context_size)
{
auto range = suggest.getCompletions(context, context_size);
return replxx::Replxx::completions_t(range.first, range.second);
};
rx.set_completion_callback(callback);
rx.set_complete_on_empty(false);
rx.set_word_break_characters(word_break_characters);
}
ReplxxLineReader::~ReplxxLineReader()
{
if (!history_file_path.empty())
rx.history_save(history_file_path);
}
LineReader::InputStatus ReplxxLineReader::readOneLine(const String & prompt)
{
input.clear();
const char* cinput = rx.input(prompt);
if (cinput == nullptr)
return (errno != EAGAIN) ? ABORT : RESET_LINE;
input = cinput;
trim(input);
return INPUT_LINE;
}
void ReplxxLineReader::addToHistory(const String & line)
{
rx.history_add(line);
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "LineReader.h"
#include <replxx.hxx>
class ReplxxLineReader : public LineReader
{
public:
ReplxxLineReader(const Suggest & suggest, const String & history_file_path, char extender, char delimiter = 0);
~ReplxxLineReader() override;
private:
InputStatus readOneLine(const String & prompt) override;
void addToHistory(const String & line) override;
replxx::Replxx rx;
};

View File

@ -29,11 +29,14 @@ struct StringRef
StringRef(const char * data_, size_t size_) : data(data_), size(size_) {}
StringRef(const unsigned char * data_, size_t size_) : data(reinterpret_cast<const char *>(data_)), size(size_) {}
StringRef(const std::string & s) : data(s.data()), size(s.size()) {}
StringRef(const std::string_view & s) : data(s.data()), size(s.size()) {}
explicit StringRef(const char * data_) : data(data_), size(strlen(data_)) {}
StringRef() = default;
std::string toString() const { return std::string(data, size); }
explicit operator std::string() const { return toString(); }
explicit operator std::string_view() const { return {data, size}; }
};
using StringRefs = std::vector<StringRef>;

View File

@ -1,8 +1,10 @@
#pragma once
#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <type_traits>
#include <algorithm>
using Int8 = int8_t;
using Int16 = int16_t;
@ -14,6 +16,8 @@ using UInt16 = uint16_t;
using UInt32 = uint32_t;
using UInt64 = uint64_t;
using String = std::string;
/// The standard library type traits, such as std::is_arithmetic, with one exception
/// (std::common_type), are "set in stone". Attempting to specialize them causes undefined behavior.
/// So instead of using the std type_traits, we use our own version which allows extension.
@ -52,4 +56,3 @@ struct is_arithmetic
template <typename T>
inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;

View File

@ -2,10 +2,6 @@
// .h autogenerated by cmake !
#cmakedefine01 USE_TCMALLOC
#cmakedefine01 USE_JEMALLOC
#cmakedefine01 USE_READLINE
#cmakedefine01 USE_LIBEDIT
#cmakedefine01 HAVE_READLINE_HISTORY
#cmakedefine01 UNBUNDLED
#cmakedefine01 WITH_COVERAGE

31
base/common/coverage.cpp Normal file
View File

@ -0,0 +1,31 @@
#include <common/coverage.h>
#include <common/config_common.h>
#if WITH_COVERAGE
#include <unistd.h>
#include <mutex>
#if defined(__clang__)
extern "C" void __llvm_profile_dump();
#elif defined(__GNUC__) || defined(__GNUG__)
extern "C" void __gcov_exit();
#endif
#endif
void dumpCoverageReportIfPossible()
{
#if WITH_COVERAGE
static std::mutex mutex;
std::lock_guard lock(mutex);
#if defined(__clang__)
__llvm_profile_dump();
#elif defined(__GNUC__) || defined(__GNUG__)
__gcov_exit();
#endif
#endif
}

9
base/common/coverage.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
/// Flush coverage report to file, depending on coverage system
/// proposed by compiler (llvm for clang and gcov for gcc).
///
/// Noop if build without coverage (WITH_COVERAGE=0).
/// Thread safe (use exclusive lock).
/// Idempotent, may be called multiple times.
void dumpCoverageReportIfPossible();

View File

@ -10,6 +10,11 @@
#if _MSC_VER || MEMORY_SANITIZER
DemangleResult tryDemangle(const char * name)
{
return DemangleResult{};
}
std::string demangle(const char * name, int & status)
{
status = 0;
@ -21,28 +26,27 @@ std::string demangle(const char * name, int & status)
#include <stdlib.h>
#include <cxxabi.h>
std::string demangle(const char * name, int & status)
static DemangleResult tryDemangle(const char * name, int & status)
{
std::string res;
char * demangled_str = abi::__cxa_demangle(name, 0, 0, &status);
if (demangled_str)
{
try
{
res = demangled_str;
}
catch (...)
{
free(demangled_str);
throw;
}
free(demangled_str);
}
else
res = name;
return res;
return DemangleResult(abi::__cxa_demangle(name, nullptr, nullptr, &status));
}
DemangleResult tryDemangle(const char * name)
{
int status = 0;
return tryDemangle(name, status);
}
std::string demangle(const char * name, int & status)
{
auto result = tryDemangle(name, status);
if (result)
{
return std::string(result.get());
}
return name;
}
#endif

View File

@ -1,5 +1,6 @@
#pragma once
#include <memory>
#include <string>
@ -14,3 +15,18 @@ inline std::string demangle(const char * name)
int status = 0;
return demangle(name, status);
}
// abi::__cxa_demangle returns a C string of known size that should be deleted
// with free().
struct FreeingDeleter
{
template <typename PointerType>
void operator() (PointerType ptr)
{
std::free(ptr);
}
};
typedef std::unique_ptr<char, FreeingDeleter> DemangleResult;
DemangleResult tryDemangle(const char * name);

View File

@ -33,7 +33,7 @@ uint64_t getMemoryAmountOrZero()
/* New 64-bit MEMORYSTATUSEX isn't available. Use old 32.bit */
MEMORYSTATUS status;
status.dwLength = sizeof(status);
GlobalMemoryStatus( &status );
GlobalMemoryStatus(&status);
return status.dwTotalPhys;
#elif defined(WIN32) || defined(_WIN32)
@ -41,7 +41,7 @@ uint64_t getMemoryAmountOrZero()
/* Use new 64-bit MEMORYSTATUSEX, not old 32-bit MEMORYSTATUS */
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx( &status );
GlobalMemoryStatusEx(&status);
return status.ullTotalPhys;
#else
@ -58,24 +58,24 @@ uint64_t getMemoryAmountOrZero()
#endif
uint64_t size = 0; /* 64-bit */
size_t len = sizeof(size);
if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) {
if (sysctl(mib, 2, &size, &len, NULL, 0) == 0)
return size;
}
return 0; /* Failed? */
#elif defined(_SC_AIX_REALMEM)
/* AIX. ----------------------------------------------------- */
return sysconf( _SC_AIX_REALMEM ) * 1024;
return sysconf(_SC_AIX_REALMEM) * 1024;
#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
/* FreeBSD, Linux, OpenBSD, and Solaris. -------------------- */
return (uint64_t)sysconf( _SC_PHYS_PAGES )
* (uint64_t)sysconf( _SC_PAGESIZE );
return (uint64_t)sysconf(_SC_PHYS_PAGES)
* (uint64_t)sysconf(_SC_PAGESIZE);
#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE)
/* Legacy. -------------------------------------------------- */
return (uint64_t)sysconf( _SC_PHYS_PAGES )
* (uint64_t)sysconf( _SC_PAGE_SIZE );
return (uint64_t)sysconf(_SC_PHYS_PAGES)
* (uint64_t)sysconf(_SC_PAGE_SIZE);
#elif defined(CTL_HW) && (defined(HW_PHYSMEM) || defined(HW_REALMEM))
/* DragonFly BSD, FreeBSD, NetBSD, OpenBSD, and OSX. -------- */
@ -87,10 +87,10 @@ uint64_t getMemoryAmountOrZero()
mib[1] = HW_PHYSMEM; /* Others. ------------------ */
#endif
unsigned int size = 0; /* 32-bit */
size_t len = sizeof( size );
if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) {
size_t len = sizeof(size);
if (sysctl(mib, 2, &size, &len, NULL, 0) == 0)
return size;
}
return 0; /* Failed? */
#endif /* sysctl and sysconf variants */

View File

@ -0,0 +1,26 @@
#include <common/getThreadId.h>
#if OS_LINUX
#include <unistd.h>
#include <syscall.h>
#else
#include <pthread.h>
#include <stdexcept>
#endif
static thread_local uint64_t current_tid = 0;
uint64_t getThreadId()
{
if (!current_tid)
{
#if OS_LINUX
current_tid = syscall(SYS_gettid); /// This call is always successful. - man gettid
#else
if (0 != pthread_threadid_np(nullptr, &current_tid))
throw std::logic_error("pthread_threadid_np returned error");
#endif
}
return current_tid;
}

View File

@ -0,0 +1,5 @@
#pragma once
#include <cstdint>
/// Obtain thread id from OS. The value is cached in thread local variable.
uint64_t getThreadId();

View File

@ -1,7 +1,7 @@
#pragma once
#include "demangle.h"
#include "getThreadNumber.h"
#include "getThreadId.h"
#include <type_traits>
#include <tuple>
#include <iomanip>
@ -140,8 +140,8 @@ Out & dump(Out & out, const char * name, T && x)
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif
#define DUMPVAR(VAR) dump(std::cerr, #VAR, (VAR)); std::cerr << "; ";
#define DUMPHEAD std::cerr << __FILE__ << ':' << __LINE__ << " [ " << getThreadNumber() << " ] ";
#define DUMPVAR(VAR) ::dump(std::cerr, #VAR, (VAR)); std::cerr << "; ";
#define DUMPHEAD std::cerr << __FILE__ << ':' << __LINE__ << " [ " << getThreadId() << " ] ";
#define DUMPTAIL std::cerr << '\n';
#define DUMP1(V1) do { DUMPHEAD DUMPVAR(V1) DUMPTAIL } while(0)

View File

@ -6,7 +6,6 @@
#include <Poco/Logger.h>
#include <Poco/Message.h>
#include <Poco/Version.h>
#include <Core/SettingsCommon.h>
#include <Common/CurrentThread.h>
#ifndef QUERY_PREVIEW_LENGTH

View File

@ -1,7 +1,8 @@
#include <common/shift10.h>
#include <common/likely.h>
#include <limits>
#include <port/ssize_t.h>
template <typename T>

7
base/common/time.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <time.h>
#if defined (OS_DARWIN)
# define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
#endif

View File

@ -26,7 +26,7 @@ inline uint32_t HI_32(uint64_t x) { return static_cast<uint32_t>(x >> 32); }
return std::numeric_limits<unsigned long long>::digits - __builtin_clzll(value);
}
#else
/// Stupid realization for non GCC-like compilers. Can use BSR from x86 instructions set.
/// Stupid implementation for non GCC-like compilers. Can use BSR from x86 instructions set.
template <typename T>
inline unsigned GetValueBitCountImpl(T value) noexcept {
unsigned result = 1; // result == 0 - impossible value, since value cannot be zero

View File

@ -1,7 +1,7 @@
#pragma once
#include <sys/types.h>
#include <port/unistd.h>
#include <unistd.h>
#include <iostream>
#include <memory>
#include <functional>
@ -19,10 +19,12 @@
#include <Poco/Version.h>
#include <common/Types.h>
#include <common/logger_useful.h>
#include <common/getThreadId.h>
#include <daemon/GraphiteWriter.h>
#include <Common/Config/ConfigProcessor.h>
#include <loggers/Loggers.h>
namespace Poco { class TaskManager; }
@ -166,22 +168,11 @@ protected:
{
std::string file;
/// Создать объект, не создавая PID файл
PID() {}
/// Создать объект, создать PID файл
PID(const std::string & file_) { seed(file_); }
/// Создать PID файл
void seed(const std::string & file_);
/// Удалить PID файл
void clear();
~PID() { clear(); }
PID(const std::string & file_);
~PID();
};
PID pid;
std::optional<PID> pid;
std::atomic_bool is_cancelled{false};

View File

@ -1,5 +1,5 @@
#include <daemon/BaseDaemon.h>
#include <Common/Config/ConfigProcessor.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
@ -12,19 +12,16 @@
#include <unistd.h>
#include <typeinfo>
#include <common/logger_useful.h>
#include <common/ErrorHandlers.h>
#include <common/Pipe.h>
#include <Common/StackTrace.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <memory>
#include <ext/scope_guard.h>
#include <Poco/Observer.h>
#include <Poco/AutoPtr.h>
#include <common/getThreadNumber.h>
#include <Poco/PatternFormatter.h>
#include <Poco/TaskManager.h>
#include <Poco/File.h>
@ -36,16 +33,25 @@
#include <Poco/Condition.h>
#include <Poco/SyslogChannel.h>
#include <Poco/DirectoryIterator.h>
#include <Common/Exception.h>
#include <common/logger_useful.h>
#include <common/ErrorHandlers.h>
#include <common/argsToConfig.h>
#include <common/getThreadId.h>
#include <common/coverage.h>
#include <IO/WriteBufferFromFile.h>
#include <IO/WriteBufferFromFileDescriptorDiscardOnFailure.h>
#include <IO/ReadBufferFromFileDescriptor.h>
#include <IO/ReadHelpers.h>
#include <IO/WriteHelpers.h>
#include <Common/Exception.h>
#include <Common/PipeFDs.h>
#include <Common/StackTrace.h>
#include <Common/getMultipleKeysFromConfig.h>
#include <Common/ClickHouseRevision.h>
#include <Common/Config/ConfigProcessor.h>
#include <Common/config_version.h>
#include <common/argsToConfig.h>
#ifdef __APPLE__
// ucontext is not available without _XOPEN_SOURCE
@ -54,7 +60,7 @@
#include <ucontext.h>
Pipe signal_pipe;
DB::PipeFDs signal_pipe;
/** Reset signal handler to the default and send signal to itself.
@ -67,8 +73,16 @@ static void call_default_signal_handler(int sig)
}
using ThreadNumber = decltype(getThreadNumber());
static const size_t buf_size = sizeof(int) + sizeof(siginfo_t) + sizeof(ucontext_t) + sizeof(StackTrace) + sizeof(ThreadNumber);
static constexpr size_t max_query_id_size = 127;
static const size_t buf_size =
sizeof(int)
+ sizeof(siginfo_t)
+ sizeof(ucontext_t)
+ sizeof(StackTrace)
+ sizeof(UInt32)
+ max_query_id_size + 1; /// query_id + varint encoded length
using signal_function = void(int, siginfo_t*, void*);
@ -92,9 +106,9 @@ static void terminateRequestedSignalHandler(int sig, siginfo_t * info, void * co
}
/** Handler for "fault" signals. Send data about fault to separate thread to write into log.
/** Handler for "fault" or diagnostic signals. Send data about fault to separate thread to write into log.
*/
static void faultSignalHandler(int sig, siginfo_t * info, void * context)
static void signalHandler(int sig, siginfo_t * info, void * context)
{
char buf[buf_size];
DB::WriteBufferFromFileDescriptorDiscardOnFailure out(signal_pipe.fds_rw[1], buf_size, buf);
@ -102,15 +116,19 @@ static void faultSignalHandler(int sig, siginfo_t * info, void * context)
const ucontext_t signal_context = *reinterpret_cast<ucontext_t *>(context);
const StackTrace stack_trace(signal_context);
StringRef query_id = CurrentThread::getQueryId(); /// This is signal safe.
query_id.size = std::min(query_id.size, max_query_id_size);
DB::writeBinary(sig, out);
DB::writePODBinary(*info, out);
DB::writePODBinary(signal_context, out);
DB::writePODBinary(stack_trace, out);
DB::writeBinary(getThreadNumber(), out);
DB::writeBinary(UInt32(getThreadId()), out);
DB::writeStringBinary(query_id, out);
out.next();
if (sig != SIGPROF) /// This signal is used for debugging.
if (sig != SIGTSTP) /// This signal is used for debugging.
{
/// The time that is usually enough for separate thread to print info into log.
::sleep(10);
@ -162,7 +180,7 @@ public:
}
else if (sig == Signals::StdTerminate)
{
ThreadNumber thread_num;
UInt32 thread_num;
std::string message;
DB::readBinary(thread_num, in);
@ -181,16 +199,18 @@ public:
siginfo_t info;
ucontext_t context;
StackTrace stack_trace(NoCapture{});
ThreadNumber thread_num;
UInt32 thread_num;
std::string query_id;
DB::readPODBinary(info, in);
DB::readPODBinary(context, in);
DB::readPODBinary(stack_trace, in);
DB::readBinary(thread_num, in);
DB::readBinary(query_id, in);
/// This allows to receive more signals if failure happens inside onFault function.
/// Example: segfault while symbolizing stack trace.
std::thread([=] { onFault(sig, info, context, stack_trace, thread_num); }).detach();
std::thread([=, this] { onFault(sig, info, context, stack_trace, thread_num, query_id); }).detach();
}
}
}
@ -200,16 +220,33 @@ private:
BaseDaemon & daemon;
private:
void onTerminate(const std::string & message, ThreadNumber thread_num) const
void onTerminate(const std::string & message, UInt32 thread_num) const
{
LOG_FATAL(log, "(version " << VERSION_STRING << VERSION_OFFICIAL << ") (from thread " << thread_num << ") " << message);
}
void onFault(int sig, const siginfo_t & info, const ucontext_t & context, const StackTrace & stack_trace, ThreadNumber thread_num) const
void onFault(
int sig,
const siginfo_t & info,
const ucontext_t & context,
const StackTrace & stack_trace,
UInt32 thread_num,
const std::string & query_id) const
{
LOG_FATAL(log, "########################################");
LOG_FATAL(log, "(version " << VERSION_STRING << VERSION_OFFICIAL << ") (from thread " << thread_num << ") "
<< "Received signal " << strsignal(sig) << " (" << sig << ")" << ".");
{
std::stringstream message;
message << "(version " << VERSION_STRING << VERSION_OFFICIAL << ")";
message << " (from thread " << thread_num << ")";
if (query_id.empty())
message << " (no query)";
else
message << " (query_id: " << query_id << ")";
message << " Received signal " << strsignal(sig) << " (" << sig << ")" << ".";
LOG_FATAL(log, message.rdbuf());
}
LOG_FATAL(log, signalToErrorMessage(sig, info, context));
@ -264,7 +301,7 @@ static void terminate_handler()
DB::WriteBufferFromFileDescriptor out(signal_pipe.fds_rw[1], buf_size, buf);
DB::writeBinary(static_cast<int>(SignalListener::StdTerminate), out);
DB::writeBinary(getThreadNumber(), out);
DB::writeBinary(UInt32(getThreadId()), out);
DB::writeBinary(log_message, out);
out.next();
@ -345,7 +382,7 @@ enum class InstructionFail
static std::string instructionFailToString(InstructionFail fail)
{
switch(fail)
switch (fail)
{
case InstructionFail::NONE:
return "NONE";
@ -461,7 +498,8 @@ void BaseDaemon::terminate()
void BaseDaemon::kill()
{
pid.clear();
dumpCoverageReportIfPossible();
pid.reset();
if (::raise(SIGKILL) != 0)
throw Poco::SystemException("cannot kill process");
}
@ -631,7 +669,7 @@ void BaseDaemon::initialize(Application & self)
/// Create pid file.
if (config().has("pid"))
pid.seed(config().getString("pid"));
pid.emplace(config().getString("pid"));
/// Change path for logging.
if (!log_path.empty())
@ -649,7 +687,7 @@ void BaseDaemon::initialize(Application & self)
}
// sensitive data masking rules are not used here
buildLoggers(config(), logger());
buildLoggers(config(), logger(), self.commandName());
if (is_daemon)
{
@ -719,9 +757,9 @@ void BaseDaemon::initializeTerminationAndSignalProcessing()
}
};
/// SIGPROF is added for debugging purposes. To output a stack trace of any running thread at anytime.
/// SIGTSTP is added for debugging purposes. To output a stack trace of any running thread at anytime.
add_signal_handler({SIGABRT, SIGSEGV, SIGILL, SIGBUS, SIGSYS, SIGFPE, SIGPIPE, SIGPROF}, faultSignalHandler);
add_signal_handler({SIGABRT, SIGSEGV, SIGILL, SIGBUS, SIGSYS, SIGFPE, SIGPIPE, SIGTSTP}, signalHandler);
add_signal_handler({SIGHUP, SIGUSR1}, closeLogsSignalHandler);
add_signal_handler({SIGINT, SIGQUIT, SIGTERM}, terminateRequestedSignalHandler);
@ -729,9 +767,11 @@ void BaseDaemon::initializeTerminationAndSignalProcessing()
static KillingErrorHandler killing_error_handler;
Poco::ErrorHandler::set(&killing_error_handler);
signal_pipe.setNonBlocking();
signal_pipe.tryIncreaseSize(1 << 20);
signal_listener.reset(new SignalListener(*this));
signal_listener_thread.start(*signal_listener);
}
void BaseDaemon::logRevision() const
@ -796,7 +836,7 @@ bool isPidRunning(pid_t pid)
return 0;
}
void BaseDaemon::PID::seed(const std::string & file_)
BaseDaemon::PID::PID(const std::string & file_)
{
file = Poco::Path(file_).absolute().toString();
Poco::File poco_file(file);
@ -823,34 +863,28 @@ void BaseDaemon::PID::seed(const std::string & file_)
if (-1 == fd)
{
file.clear();
if (EEXIST == errno)
throw Poco::Exception("Pid file exists, should not start daemon.");
throw Poco::CreateFileException("Cannot create pid file.");
}
SCOPE_EXIT({ close(fd); });
std::stringstream s;
s << getpid();
if (static_cast<ssize_t>(s.str().size()) != write(fd, s.str().c_str(), s.str().size()))
throw Poco::Exception("Cannot write to pid file.");
}
BaseDaemon::PID::~PID()
{
try
{
std::stringstream s;
s << getpid();
if (static_cast<ssize_t>(s.str().size()) != write(fd, s.str().c_str(), s.str().size()))
throw Poco::Exception("Cannot write to pid file.");
Poco::File(file).remove();
}
catch (...)
{
close(fd);
throw;
}
close(fd);
}
void BaseDaemon::PID::clear()
{
if (!file.empty())
{
Poco::File(file).remove();
file.clear();
DB::tryLogCurrentException(__PRETTY_FUNCTION__);
}
}
@ -891,4 +925,3 @@ void BaseDaemon::waitForTerminationRequest()
std::unique_lock<std::mutex> lock(signal_handler_mutex);
signal_event.wait(lock, [this](){ return terminate_signals_counter > 0; });
}

37
base/ext/chrono_io.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include <chrono>
#include <string>
#include <common/DateLUT.h>
namespace ext
{
template <typename Clock, typename Duration = typename Clock::duration>
std::string to_string(const std::chrono::time_point<Clock, Duration> & tp)
{
return DateLUT::instance().timeToString(std::chrono::system_clock::to_time_t(tp));
}
template <typename Rep, typename Period = std::ratio<1>>
std::string to_string(const std::chrono::duration<Rep, Period> & dur)
{
auto seconds_as_int = std::chrono::duration_cast<std::chrono::seconds>(dur);
if (seconds_as_int == dur)
return std::to_string(seconds_as_int.count()) + "s";
auto seconds_as_double = std::chrono::duration_cast<std::chrono::duration<double>>(dur);
return std::to_string(seconds_as_double.count()) + "s";
}
template <typename Clock, typename Duration = typename Clock::duration>
std::ostream & operator<<(std::ostream & o, const std::chrono::time_point<Clock, Duration> & tp)
{
return o << to_string(tp);
}
template <typename Rep, typename Period = std::ratio<1>>
std::ostream & operator<<(std::ostream & o, const std::chrono::duration<Rep, Period> & dur)
{
return o << to_string(dur);
}
}

25
base/ext/push_back.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include <vector>
namespace ext
{
/// Moves all arguments starting from the second to the end of the vector.
/// For example, `push_back(vec, a1, a2, a3)` is a more compact way to write
/// `vec.push_back(a1); vec.push_back(a2); vec.push_back(a3);`
/// This function is like boost::range::push_back() but works for noncopyable types too.
template <typename T>
void push_back(std::vector<T> &)
{
}
template <typename T, typename FirstArg, typename... OtherArgs>
void push_back(std::vector<T> & vec, FirstArg && first, OtherArgs &&... other)
{
vec.reserve(vec.size() + sizeof...(other) + 1);
vec.emplace_back(std::move(first));
push_back(vec, std::move(other)...);
}
}

42
base/ext/range.h Normal file
View File

@ -0,0 +1,42 @@
#pragma once
#include <type_traits>
#include <boost/range/counting_range.hpp>
#include <boost/range/adaptor/transformed.hpp>
namespace ext
{
/// For loop adaptor which is used to iterate through a half-closed interval [begin, end).
template <typename BeginType, typename EndType>
inline auto range(BeginType begin, EndType end)
{
using CommonType = typename std::common_type<BeginType, EndType>::type;
return boost::counting_range<CommonType>(begin, end);
}
template <typename Type>
inline auto range(Type end)
{
return range<Type, Type>(static_cast<Type>(0), end);
}
/// The same as range(), but every value is casted statically to a specified `ValueType`.
/// This is useful to iterate through all constants of a enum.
template <typename ValueType, typename BeginType, typename EndType>
inline auto range_with_static_cast(BeginType begin, EndType end)
{
using CommonType = typename std::common_type<BeginType, EndType>::type;
if constexpr (std::is_same_v<ValueType, CommonType>)
return boost::counting_range<CommonType>(begin, end);
else
return boost::counting_range<CommonType>(begin, end)
| boost::adaptors::transformed([](CommonType x) -> ValueType { return static_cast<ValueType>(x); });
}
template <typename ValueType, typename EndType>
inline auto range_with_static_cast(EndType end)
{
return range_with_static_cast<ValueType, EndType, EndType>(static_cast<EndType>(0), end);
}
}

Some files were not shown because too many files have changed in this diff Show More