mirror of
https://github.com/XRPLF/clio.git
synced 2026-03-12 07:32:36 +00:00
Compare commits
6 Commits
nightly-20
...
2.6.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d053a1f8c8 | ||
|
|
c12601c0f5 | ||
|
|
381009807f | ||
|
|
f530216688 | ||
|
|
0cccb1a2c0 | ||
|
|
1803990aa8 |
@@ -22,7 +22,7 @@ BreakBeforeBinaryOperators: false
|
||||
BreakBeforeBraces: WebKit
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
ColumnLimit: 100
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
@@ -49,7 +49,6 @@ IndentFunctionDeclarationAfterType: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
IndentRequiresClause: true
|
||||
InsertNewlineAtEOF: true
|
||||
RequiresClausePosition: OwnLine
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
|
||||
245
.cmake-format.yaml
Normal file
245
.cmake-format.yaml
Normal file
@@ -0,0 +1,245 @@
|
||||
_help_parse: Options affecting listfile parsing
|
||||
parse:
|
||||
_help_additional_commands:
|
||||
- Specify structure for custom cmake functions
|
||||
additional_commands:
|
||||
foo:
|
||||
flags:
|
||||
- BAR
|
||||
- BAZ
|
||||
kwargs:
|
||||
HEADERS: "*"
|
||||
SOURCES: "*"
|
||||
DEPENDS: "*"
|
||||
_help_override_spec:
|
||||
- Override configurations per-command where available
|
||||
override_spec: {}
|
||||
_help_vartags:
|
||||
- Specify variable tags.
|
||||
vartags: []
|
||||
_help_proptags:
|
||||
- Specify property tags.
|
||||
proptags: []
|
||||
_help_format: Options affecting formatting.
|
||||
format:
|
||||
_help_disable:
|
||||
- Disable formatting entirely, making cmake-format a no-op
|
||||
disable: false
|
||||
_help_line_width:
|
||||
- How wide to allow formatted cmake files
|
||||
line_width: 120
|
||||
_help_tab_size:
|
||||
- How many spaces to tab for indent
|
||||
tab_size: 2
|
||||
_help_use_tabchars:
|
||||
- If true, lines are indented using tab characters (utf-8
|
||||
- 0x09) instead of <tab_size> space characters (utf-8 0x20).
|
||||
- In cases where the layout would require a fractional tab
|
||||
- character, the behavior of the fractional indentation is
|
||||
- governed by <fractional_tab_policy>
|
||||
use_tabchars: false
|
||||
_help_fractional_tab_policy:
|
||||
- If <use_tabchars> is True, then the value of this variable
|
||||
- indicates how fractional indentions are handled during
|
||||
- whitespace replacement. If set to 'use-space', fractional
|
||||
- indentation is left as spaces (utf-8 0x20). If set to
|
||||
- "`round-up` fractional indentation is replaced with a single"
|
||||
- tab character (utf-8 0x09) effectively shifting the column
|
||||
- to the next tabstop
|
||||
fractional_tab_policy: use-space
|
||||
_help_max_subgroups_hwrap:
|
||||
- If an argument group contains more than this many sub-groups
|
||||
- (parg or kwarg groups) then force it to a vertical layout.
|
||||
max_subgroups_hwrap: 4
|
||||
_help_max_pargs_hwrap:
|
||||
- If a positional argument group contains more than this many
|
||||
- arguments, then force it to a vertical layout.
|
||||
max_pargs_hwrap: 6
|
||||
_help_max_rows_cmdline:
|
||||
- If a cmdline positional group consumes more than this many
|
||||
- lines without nesting, then invalidate the layout (and nest)
|
||||
max_rows_cmdline: 2
|
||||
_help_separate_ctrl_name_with_space:
|
||||
- If true, separate flow control names from their parentheses
|
||||
- with a space
|
||||
separate_ctrl_name_with_space: true
|
||||
_help_separate_fn_name_with_space:
|
||||
- If true, separate function names from parentheses with a
|
||||
- space
|
||||
separate_fn_name_with_space: false
|
||||
_help_dangle_parens:
|
||||
- If a statement is wrapped to more than one line, than dangle
|
||||
- the closing parenthesis on its own line.
|
||||
dangle_parens: true
|
||||
_help_dangle_align:
|
||||
- If the trailing parenthesis must be 'dangled' on its on
|
||||
- "line, then align it to this reference: `prefix`: the start"
|
||||
- "of the statement, `prefix-indent`: the start of the"
|
||||
- "statement, plus one indentation level, `child`: align to"
|
||||
- the column of the arguments
|
||||
dangle_align: prefix
|
||||
_help_min_prefix_chars:
|
||||
- If the statement spelling length (including space and
|
||||
- parenthesis) is smaller than this amount, then force reject
|
||||
- nested layouts.
|
||||
min_prefix_chars: 4
|
||||
_help_max_prefix_chars:
|
||||
- If the statement spelling length (including space and
|
||||
- parenthesis) is larger than the tab width by more than this
|
||||
- amount, then force reject un-nested layouts.
|
||||
max_prefix_chars: 10
|
||||
_help_max_lines_hwrap:
|
||||
- If a candidate layout is wrapped horizontally but it exceeds
|
||||
- this many lines, then reject the layout.
|
||||
max_lines_hwrap: 2
|
||||
_help_line_ending:
|
||||
- What style line endings to use in the output.
|
||||
line_ending: unix
|
||||
_help_command_case:
|
||||
- Format command names consistently as 'lower' or 'upper' case
|
||||
command_case: canonical
|
||||
_help_keyword_case:
|
||||
- Format keywords consistently as 'lower' or 'upper' case
|
||||
keyword_case: unchanged
|
||||
_help_always_wrap:
|
||||
- A list of command names which should always be wrapped
|
||||
always_wrap: []
|
||||
_help_enable_sort:
|
||||
- If true, the argument lists which are known to be sortable
|
||||
- will be sorted lexicographicall
|
||||
enable_sort: true
|
||||
_help_autosort:
|
||||
- If true, the parsers may infer whether or not an argument
|
||||
- list is sortable (without annotation).
|
||||
autosort: true
|
||||
_help_require_valid_layout:
|
||||
- By default, if cmake-format cannot successfully fit
|
||||
- everything into the desired linewidth it will apply the
|
||||
- last, most aggressive attempt that it made. If this flag is
|
||||
- True, however, cmake-format will print error, exit with non-
|
||||
- zero status code, and write-out nothing
|
||||
require_valid_layout: false
|
||||
_help_layout_passes:
|
||||
- A dictionary mapping layout nodes to a list of wrap
|
||||
- decisions. See the documentation for more information.
|
||||
layout_passes: {}
|
||||
_help_markup: Options affecting comment reflow and formatting.
|
||||
markup:
|
||||
_help_bullet_char:
|
||||
- What character to use for bulleted lists
|
||||
bullet_char: "*"
|
||||
_help_enum_char:
|
||||
- What character to use as punctuation after numerals in an
|
||||
- enumerated list
|
||||
enum_char: .
|
||||
_help_first_comment_is_literal:
|
||||
- If comment markup is enabled, don't reflow the first comment
|
||||
- block in each listfile. Use this to preserve formatting of
|
||||
- your copyright/license statements.
|
||||
first_comment_is_literal: false
|
||||
_help_literal_comment_pattern:
|
||||
- If comment markup is enabled, don't reflow any comment block
|
||||
- which matches this (regex) pattern. Default is `None`
|
||||
- (disabled).
|
||||
literal_comment_pattern: null
|
||||
_help_fence_pattern:
|
||||
- Regular expression to match preformat fences in comments
|
||||
- default= ``r'^\s*([`~]{3}[`~]*)(.*)$'``
|
||||
fence_pattern: ^\s*([`~]{3}[`~]*)(.*)$
|
||||
_help_ruler_pattern:
|
||||
- Regular expression to match rulers in comments default=
|
||||
- '``r''^\s*[^\w\s]{3}.*[^\w\s]{3}$''``'
|
||||
ruler_pattern: ^\s*[^\w\s]{3}.*[^\w\s]{3}$
|
||||
_help_explicit_trailing_pattern:
|
||||
- If a comment line matches starts with this pattern then it
|
||||
- is explicitly a trailing comment for the preceding
|
||||
- argument. Default is '#<'
|
||||
explicit_trailing_pattern: "#<"
|
||||
_help_hashruler_min_length:
|
||||
- If a comment line starts with at least this many consecutive
|
||||
- hash characters, then don't lstrip() them off. This allows
|
||||
- for lazy hash rulers where the first hash char is not
|
||||
- separated by space
|
||||
hashruler_min_length: 10
|
||||
_help_canonicalize_hashrulers:
|
||||
- If true, then insert a space between the first hash char and
|
||||
- remaining hash chars in a hash ruler, and normalize its
|
||||
- length to fill the column
|
||||
canonicalize_hashrulers: true
|
||||
_help_enable_markup:
|
||||
- enable comment markup parsing and reflow
|
||||
enable_markup: true
|
||||
_help_lint: Options affecting the linter
|
||||
lint:
|
||||
_help_disabled_codes:
|
||||
- a list of lint codes to disable
|
||||
disabled_codes: []
|
||||
_help_function_pattern:
|
||||
- regular expression pattern describing valid function names
|
||||
function_pattern: "[0-9a-z_]+"
|
||||
_help_macro_pattern:
|
||||
- regular expression pattern describing valid macro names
|
||||
macro_pattern: "[0-9A-Z_]+"
|
||||
_help_global_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- variables with global (cache) scope
|
||||
global_var_pattern: "[A-Z][0-9A-Z_]+"
|
||||
_help_internal_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- variables with global scope (but internal semantic)
|
||||
internal_var_pattern: _[A-Z][0-9A-Z_]+
|
||||
_help_local_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- variables with local scope
|
||||
local_var_pattern: "[a-z][a-z0-9_]+"
|
||||
_help_private_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- privatedirectory variables
|
||||
private_var_pattern: _[0-9a-z_]+
|
||||
_help_public_var_pattern:
|
||||
- regular expression pattern describing valid names for public
|
||||
- directory variables
|
||||
public_var_pattern: "[A-Z][0-9A-Z_]+"
|
||||
_help_argument_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- function/macro arguments and loop variables.
|
||||
argument_var_pattern: "[a-z][a-z0-9_]+"
|
||||
_help_keyword_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- keywords used in functions or macros
|
||||
keyword_pattern: "[A-Z][0-9A-Z_]+"
|
||||
_help_max_conditionals_custom_parser:
|
||||
- In the heuristic for C0201, how many conditionals to match
|
||||
- within a loop in before considering the loop a parser.
|
||||
max_conditionals_custom_parser: 2
|
||||
_help_min_statement_spacing:
|
||||
- Require at least this many newlines between statements
|
||||
min_statement_spacing: 1
|
||||
_help_max_statement_spacing:
|
||||
- Require no more than this many newlines between statements
|
||||
max_statement_spacing: 2
|
||||
max_returns: 6
|
||||
max_branches: 12
|
||||
max_arguments: 5
|
||||
max_localvars: 15
|
||||
max_statements: 50
|
||||
_help_encode: Options affecting file encoding
|
||||
encode:
|
||||
_help_emit_byteorder_mark:
|
||||
- If true, emit the unicode byte-order mark (BOM) at the start
|
||||
- of the file
|
||||
emit_byteorder_mark: false
|
||||
_help_input_encoding:
|
||||
- Specify the encoding of the input file. Defaults to utf-8
|
||||
input_encoding: utf-8
|
||||
_help_output_encoding:
|
||||
- Specify the encoding of the output file. Defaults to utf-8.
|
||||
- Note that cmake only claims to support utf-8 so be careful
|
||||
- when using anything else
|
||||
output_encoding: utf-8
|
||||
_help_misc: Miscellaneous configurations options.
|
||||
misc:
|
||||
_help_per_command:
|
||||
- A dictionary containing any per-command configuration
|
||||
- overrides. Currently only `command_case` is supported.
|
||||
per_command: {}
|
||||
@@ -1,19 +0,0 @@
|
||||
# Custom CMake command definitions for gersemi formatting.
|
||||
# These stubs teach gersemi the signatures of project-specific commands
|
||||
# so it can format their invocations correctly.
|
||||
|
||||
function(setup_target_for_coverage_gcovr)
|
||||
set(options NONE)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME FORMAT)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(
|
||||
THIS_FUNCTION_PREFIX
|
||||
"${options}"
|
||||
"${oneValueArgs}"
|
||||
"${multiValueArgs}"
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(append_coverage_compiler_flags_to_target name mode)
|
||||
endfunction()
|
||||
@@ -1 +0,0 @@
|
||||
definitions: [.gersemi]
|
||||
18
.github/actions/build-clio/action.yml
vendored
18
.github/actions/build-clio/action.yml
vendored
@@ -5,27 +5,25 @@ inputs:
|
||||
targets:
|
||||
description: Space-separated build target names
|
||||
default: all
|
||||
nproc_subtract:
|
||||
description: The number of processors to subtract when calculating parallelism.
|
||||
subtract_threads:
|
||||
description: An option for the action get-threads-number.
|
||||
required: true
|
||||
default: "0"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
|
||||
id: nproc
|
||||
- name: Get number of threads
|
||||
uses: ./.github/actions/get-threads-number
|
||||
id: number_of_threads
|
||||
with:
|
||||
subtract: ${{ inputs.nproc_subtract }}
|
||||
subtract_threads: ${{ inputs.subtract_threads }}
|
||||
|
||||
- name: Build targets
|
||||
shell: bash
|
||||
env:
|
||||
CMAKE_TARGETS: ${{ inputs.targets }}
|
||||
run: |
|
||||
cd build
|
||||
cmake \
|
||||
--build . \
|
||||
--parallel "${{ steps.nproc.outputs.nproc }}" \
|
||||
--target ${CMAKE_TARGETS}
|
||||
--parallel "${{ steps.number_of_threads.outputs.threads_number }}" \
|
||||
--target ${{ inputs.targets }}
|
||||
|
||||
12
.github/actions/build-docker-image/action.yml
vendored
12
.github/actions/build-docker-image/action.yml
vendored
@@ -34,32 +34,32 @@ runs:
|
||||
steps:
|
||||
- name: Login to DockerHub
|
||||
if: ${{ inputs.push_image == 'true' && inputs.dockerhub_repo != '' }}
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
username: ${{ env.DOCKERHUB_USER }}
|
||||
password: ${{ env.DOCKERHUB_PW }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: ${{ inputs.push_image == 'true' }}
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ env.GITHUB_TOKEN }}
|
||||
|
||||
- uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||
- uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
|
||||
with:
|
||||
cache-image: false
|
||||
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
- uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||
|
||||
- uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
|
||||
- uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
|
||||
id: meta
|
||||
with:
|
||||
images: ${{ inputs.images }}
|
||||
tags: ${{ inputs.tags }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||
with:
|
||||
context: ${{ inputs.directory }}
|
||||
platforms: ${{ inputs.platforms }}
|
||||
|
||||
41
.github/actions/cache-key/action.yml
vendored
41
.github/actions/cache-key/action.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Cache key
|
||||
description: Generate cache key for ccache
|
||||
|
||||
inputs:
|
||||
conan_profile:
|
||||
description: Conan profile name
|
||||
required: true
|
||||
build_type:
|
||||
description: Current build type (e.g. Release, Debug)
|
||||
required: true
|
||||
default: Release
|
||||
code_coverage:
|
||||
description: Whether code coverage is on
|
||||
required: true
|
||||
default: "false"
|
||||
|
||||
outputs:
|
||||
key:
|
||||
description: Generated cache key for ccache
|
||||
value: ${{ steps.key_without_commit.outputs.key }}-${{ steps.git_common_ancestor.outputs.commit }}
|
||||
restore_keys:
|
||||
description: Cache restore keys for fallback
|
||||
value: ${{ steps.key_without_commit.outputs.key }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Find common commit
|
||||
id: git_common_ancestor
|
||||
uses: ./.github/actions/git-common-ancestor
|
||||
|
||||
- name: Set cache key without commit
|
||||
id: key_without_commit
|
||||
shell: bash
|
||||
env:
|
||||
RUNNER_OS: ${{ runner.os }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CODE_COVERAGE: ${{ inputs.code_coverage == 'true' && '-code_coverage' || '' }}
|
||||
CONAN_PROFILE: ${{ inputs.conan_profile }}
|
||||
run: |
|
||||
echo "key=clio-ccache-${RUNNER_OS}-${BUILD_TYPE}${CODE_COVERAGE}-${CONAN_PROFILE}-develop" >> "${GITHUB_OUTPUT}"
|
||||
20
.github/actions/cmake/action.yml
vendored
20
.github/actions/cmake/action.yml
vendored
@@ -37,10 +37,6 @@ inputs:
|
||||
description: Whether to generate Debian package
|
||||
required: true
|
||||
default: "false"
|
||||
version:
|
||||
description: Version of the clio_server binary
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
@@ -48,7 +44,6 @@ runs:
|
||||
- name: Run cmake
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_DIR: "${{ inputs.build_dir }}"
|
||||
BUILD_TYPE: "${{ inputs.build_type }}"
|
||||
SANITIZER_OPTION: |-
|
||||
${{ endsWith(inputs.conan_profile, '.asan') && '-Dsan=address' ||
|
||||
@@ -61,22 +56,9 @@ runs:
|
||||
STATIC: "${{ inputs.static == 'true' && 'ON' || 'OFF' }}"
|
||||
TIME_TRACE: "${{ inputs.time_trace == 'true' && 'ON' || 'OFF' }}"
|
||||
PACKAGE: "${{ inputs.package == 'true' && 'ON' || 'OFF' }}"
|
||||
# GitHub creates a merge commit for a PR
|
||||
# https://www.kenmuse.com/blog/the-many-shas-of-a-github-pull-request/
|
||||
#
|
||||
# We:
|
||||
# - explicitly provide branch name
|
||||
# - use `github.head_ref` to get the SHA of last commit in the PR branch
|
||||
#
|
||||
# This way it works both for PRs and pushes to branches.
|
||||
GITHUB_BRANCH_NAME: "${{ github.head_ref || github.ref_name }}"
|
||||
GITHUB_HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
|
||||
#
|
||||
# If tag is being pushed, or it's a nightly release, we use that version.
|
||||
FORCE_CLIO_VERSION: ${{ inputs.version }}
|
||||
run: |
|
||||
cmake \
|
||||
-B "${BUILD_DIR}" \
|
||||
-B ${{inputs.build_dir}} \
|
||||
-S . \
|
||||
-G Ninja \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
|
||||
2
.github/actions/code-coverage/action.yml
vendored
2
.github/actions/code-coverage/action.yml
vendored
@@ -24,7 +24,7 @@ runs:
|
||||
-j8 --exclude-throw-branches
|
||||
|
||||
- name: Archive coverage report
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-report.xml
|
||||
path: build/coverage_report.xml
|
||||
|
||||
15
.github/actions/conan/action.yml
vendored
15
.github/actions/conan/action.yml
vendored
@@ -21,17 +21,18 @@ inputs:
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Create build directory
|
||||
shell: bash
|
||||
run: mkdir -p "${{ inputs.build_dir }}"
|
||||
|
||||
- name: Run conan
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_DIR: "${{ inputs.build_dir }}"
|
||||
CONAN_BUILD_OPTION: "${{ inputs.force_conan_source_build == 'true' && '*' || 'missing' }}"
|
||||
BUILD_TYPE: "${{ inputs.build_type }}"
|
||||
CONAN_PROFILE: "${{ inputs.conan_profile }}"
|
||||
run: |
|
||||
conan \
|
||||
install . \
|
||||
-of "${BUILD_DIR}" \
|
||||
-b "${CONAN_BUILD_OPTION}" \
|
||||
-s "build_type=${BUILD_TYPE}" \
|
||||
--profile:all "${CONAN_PROFILE}"
|
||||
-of build \
|
||||
-b "$CONAN_BUILD_OPTION" \
|
||||
-s "build_type=${{ inputs.build_type }}" \
|
||||
--profile:all "${{ inputs.conan_profile }}"
|
||||
|
||||
13
.github/actions/create-issue/action.yml
vendored
13
.github/actions/create-issue/action.yml
vendored
@@ -28,17 +28,12 @@ runs:
|
||||
- name: Create an issue
|
||||
id: create_issue
|
||||
shell: bash
|
||||
env:
|
||||
ISSUE_BODY: ${{ inputs.body }}
|
||||
ISSUE_ASSIGNEES: ${{ inputs.assignees }}
|
||||
ISSUE_LABELS: ${{ inputs.labels }}
|
||||
ISSUE_TITLE: ${{ inputs.title }}
|
||||
run: |
|
||||
echo -e "${ISSUE_BODY}" > issue.md
|
||||
echo -e '${{ inputs.body }}' > issue.md
|
||||
gh issue create \
|
||||
--assignee "${ISSUE_ASSIGNEES}" \
|
||||
--label "${ISSUE_LABELS}" \
|
||||
--title "${ISSUE_TITLE}" \
|
||||
--assignee '${{ inputs.assignees }}' \
|
||||
--label '${{ inputs.labels }}' \
|
||||
--title '${{ inputs.title }}' \
|
||||
--body-file ./issue.md \
|
||||
> create_issue.log
|
||||
created_issue="$(sed 's|.*/||' create_issue.log)"
|
||||
|
||||
36
.github/actions/get-threads-number/action.yml
vendored
Normal file
36
.github/actions/get-threads-number/action.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Get number of threads
|
||||
description: Determines number of threads to use on macOS and Linux
|
||||
|
||||
inputs:
|
||||
subtract_threads:
|
||||
description: How many threads to subtract from the calculated number
|
||||
required: true
|
||||
default: "0"
|
||||
outputs:
|
||||
threads_number:
|
||||
description: Number of threads to use
|
||||
value: ${{ steps.number_of_threads_export.outputs.num }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Get number of threads on mac
|
||||
id: mac_threads
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
shell: bash
|
||||
run: echo "num=$(($(sysctl -n hw.logicalcpu) - 2))" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get number of threads on Linux
|
||||
id: linux_threads
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
run: echo "num=$(($(nproc) - 2))" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Shift and export number of threads
|
||||
id: number_of_threads_export
|
||||
shell: bash
|
||||
run: |
|
||||
num_of_threads="${{ steps.mac_threads.outputs.num || steps.linux_threads.outputs.num }}"
|
||||
shift_by="${{ inputs.subtract_threads }}"
|
||||
shifted="$((num_of_threads - shift_by))"
|
||||
echo "num=$(( shifted > 1 ? shifted : 1 ))" >> $GITHUB_OUTPUT
|
||||
38
.github/actions/restore-cache/action.yml
vendored
Normal file
38
.github/actions/restore-cache/action.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Restore cache
|
||||
description: Find and restores ccache cache
|
||||
|
||||
inputs:
|
||||
conan_profile:
|
||||
description: Conan profile name
|
||||
required: true
|
||||
ccache_dir:
|
||||
description: Path to .ccache directory
|
||||
required: true
|
||||
build_type:
|
||||
description: Current build type (e.g. Release, Debug)
|
||||
required: true
|
||||
default: Release
|
||||
code_coverage:
|
||||
description: Whether code coverage is on
|
||||
required: true
|
||||
default: "false"
|
||||
|
||||
outputs:
|
||||
ccache_cache_hit:
|
||||
description: True if ccache cache has been downloaded
|
||||
value: ${{ steps.ccache_cache.outputs.cache-hit }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Find common commit
|
||||
id: git_common_ancestor
|
||||
uses: ./.github/actions/git-common-ancestor
|
||||
|
||||
- name: Restore ccache cache
|
||||
uses: actions/cache/restore@v4
|
||||
id: ccache_cache
|
||||
if: ${{ env.CCACHE_DISABLE != '1' }}
|
||||
with:
|
||||
path: ${{ inputs.ccache_dir }}
|
||||
key: clio-ccache-${{ runner.os }}-${{ inputs.build_type }}${{ inputs.code_coverage == 'true' && '-code_coverage' || '' }}-${{ inputs.conan_profile }}-develop-${{ steps.git_common_ancestor.outputs.commit }}
|
||||
38
.github/actions/save-cache/action.yml
vendored
Normal file
38
.github/actions/save-cache/action.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Save cache
|
||||
description: Save ccache cache for develop branch
|
||||
|
||||
inputs:
|
||||
conan_profile:
|
||||
description: Conan profile name
|
||||
required: true
|
||||
ccache_dir:
|
||||
description: Path to .ccache directory
|
||||
required: true
|
||||
build_type:
|
||||
description: Current build type (e.g. Release, Debug)
|
||||
required: true
|
||||
default: Release
|
||||
code_coverage:
|
||||
description: Whether code coverage is on
|
||||
required: true
|
||||
default: "false"
|
||||
|
||||
ccache_cache_hit:
|
||||
description: Whether ccache cache has been downloaded
|
||||
required: true
|
||||
ccache_cache_miss_rate:
|
||||
description: How many ccache cache misses happened
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Find common commit
|
||||
id: git_common_ancestor
|
||||
uses: ./.github/actions/git-common-ancestor
|
||||
|
||||
- name: Save ccache cache
|
||||
if: ${{ inputs.ccache_cache_hit != 'true' || inputs.ccache_cache_miss_rate == '100.0' }}
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ${{ inputs.ccache_dir }}
|
||||
key: clio-ccache-${{ runner.os }}-${{ inputs.build_type }}${{ inputs.code_coverage == 'true' && '-code_coverage' || '' }}-${{ inputs.conan_profile }}-develop-${{ steps.git_common_ancestor.outputs.commit }}
|
||||
28
.github/dependabot.yml
vendored
28
.github/dependabot.yml
vendored
@@ -91,6 +91,19 @@ updates:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/get-threads-number/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
reviewers:
|
||||
- XRPLF/clio-dev-team
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/git-common-ancestor/
|
||||
schedule:
|
||||
@@ -105,7 +118,20 @@ updates:
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/cache-key/
|
||||
directory: .github/actions/restore-cache/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
reviewers:
|
||||
- XRPLF/clio-dev-team
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/save-cache/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
|
||||
2
.github/scripts/conan/apple-clang-17.profile
vendored
2
.github/scripts/conan/apple-clang-17.profile
vendored
@@ -4,7 +4,7 @@ build_type=Release
|
||||
compiler=apple-clang
|
||||
compiler.cppstd=20
|
||||
compiler.libcxx=libc++
|
||||
compiler.version=17.0
|
||||
compiler.version=17
|
||||
os=Macos
|
||||
|
||||
[conf]
|
||||
|
||||
2
.github/scripts/conan/generate_matrix.py
vendored
2
.github/scripts/conan/generate_matrix.py
vendored
@@ -4,7 +4,7 @@ import json
|
||||
|
||||
LINUX_OS = ["heavy", "heavy-arm64"]
|
||||
LINUX_CONTAINERS = [
|
||||
'{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
'{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
]
|
||||
LINUX_COMPILERS = ["gcc", "clang"]
|
||||
|
||||
|
||||
4
.github/scripts/conan/init.sh
vendored
4
.github/scripts/conan/init.sh
vendored
@@ -40,9 +40,9 @@ mkdir -p "$PROFILES_DIR"
|
||||
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
create_profile_with_sanitizers "apple-clang" "$APPLE_CLANG_PROFILE"
|
||||
echo "include(apple-clang)" >"$PROFILES_DIR/default"
|
||||
echo "include(apple-clang)" > "$PROFILES_DIR/default"
|
||||
else
|
||||
create_profile_with_sanitizers "clang" "$CLANG_PROFILE"
|
||||
create_profile_with_sanitizers "gcc" "$GCC_PROFILE"
|
||||
echo "include(gcc)" >"$PROFILES_DIR/default"
|
||||
echo "include(gcc)" > "$PROFILES_DIR/default"
|
||||
fi
|
||||
|
||||
25
.github/scripts/conan/regenerate_lockfile.sh
vendored
25
.github/scripts/conan/regenerate_lockfile.sh
vendored
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ex
|
||||
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
trap "rm -rf $TEMP_DIR" EXIT
|
||||
|
||||
echo "Using temporary CONAN_HOME: $TEMP_DIR"
|
||||
|
||||
# We use a temporary Conan home to avoid polluting the user's existing Conan
|
||||
# configuration and to not use local cache (which leads to non-reproducible lockfiles).
|
||||
export CONAN_HOME="$TEMP_DIR"
|
||||
|
||||
# Ensure that the xrplf remote is the first to be consulted, so any recipes we
|
||||
# patched are used. We also add it there to not created huge diff when the
|
||||
# official Conan Center Index is updated.
|
||||
conan remote add --force --index 0 xrplf https://conan.ripplex.io
|
||||
|
||||
# Delete any existing lockfile.
|
||||
rm -f conan.lock
|
||||
|
||||
# Create a new lockfile that is compatible with macOS.
|
||||
# It should also work on Linux.
|
||||
conan lock create . \
|
||||
--profile:all=.github/scripts/conan/apple-clang-17.profile
|
||||
45
.github/scripts/execute-tests-under-sanitizer
vendored
Executable file
45
.github/scripts/execute-tests-under-sanitizer
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -o pipefail
|
||||
|
||||
# Note: This script is intended to be run from the root of the repository.
|
||||
#
|
||||
# This script runs each unit-test separately and generates reports from the currently active sanitizer.
|
||||
# Output is saved in ./.sanitizer-report in the root of the repository
|
||||
|
||||
if [[ -z "$1" ]]; then
|
||||
cat <<EOF
|
||||
|
||||
ERROR
|
||||
-----------------------------------------------------------------------------
|
||||
Path to clio_tests should be passed as first argument to the script.
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEST_BINARY=$1
|
||||
|
||||
if [[ ! -f "$TEST_BINARY" ]]; then
|
||||
echo "Test binary not found: $TEST_BINARY"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TESTS=$($TEST_BINARY --gtest_list_tests | awk '/^ / {print suite $1} !/^ / {suite=$1}')
|
||||
|
||||
OUTPUT_DIR="./.sanitizer-report"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
for TEST in $TESTS; do
|
||||
OUTPUT_FILE="$OUTPUT_DIR/${TEST//\//_}"
|
||||
export TSAN_OPTIONS="log_path=\"$OUTPUT_FILE\" die_after_fork=0"
|
||||
export ASAN_OPTIONS="log_path=\"$OUTPUT_FILE\""
|
||||
export UBSAN_OPTIONS="log_path=\"$OUTPUT_FILE\""
|
||||
export MallocNanoZone='0' # for MacOSX
|
||||
$TEST_BINARY --gtest_filter="$TEST" > /dev/null 2>&1
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "'$TEST' failed a sanitizer check."
|
||||
fi
|
||||
done
|
||||
2
.github/scripts/prepare-release-artifacts.sh
vendored
2
.github/scripts/prepare-release-artifacts.sh
vendored
@@ -20,5 +20,5 @@ for artifact_name in $(ls); do
|
||||
rm "${artifact_name}/${BINARY_NAME}"
|
||||
rm -r "${artifact_name}"
|
||||
|
||||
sha256sum "./${artifact_name}.zip" >"./${artifact_name}.zip.sha256sum"
|
||||
sha256sum "./${artifact_name}.zip" > "./${artifact_name}.zip.sha256sum"
|
||||
done
|
||||
|
||||
18
.github/workflows/build-clio-docker-image.yml
vendored
18
.github/workflows/build-clio-docker-image.yml
vendored
@@ -38,37 +38,32 @@ on:
|
||||
description: Whether to strip clio binary
|
||||
default: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build_and_publish_image:
|
||||
name: Build and publish image
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download Clio binary from artifact
|
||||
if: ${{ inputs.artifact_name != null }}
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: ${{ inputs.artifact_name }}
|
||||
path: ./docker/clio/artifact/
|
||||
|
||||
- name: Download Clio binary from url
|
||||
if: ${{ inputs.clio_server_binary_url != null }}
|
||||
env:
|
||||
BINARY_URL: ${{ inputs.clio_server_binary_url }}
|
||||
BINARY_SHA256: ${{ inputs.binary_sha256 }}
|
||||
shell: bash
|
||||
run: |
|
||||
wget "${BINARY_URL}" -P ./docker/clio/artifact/
|
||||
if [ "$(sha256sum ./docker/clio/clio_server | awk '{print $1}')" != "${BINARY_SHA256}" ]; then
|
||||
wget "${{inputs.clio_server_binary_url}}" -P ./docker/clio/artifact/
|
||||
if [ "$(sha256sum ./docker/clio/clio_server | awk '{print $1}')" != "${{inputs.binary_sha256}}" ]; then
|
||||
echo "Binary sha256 sum doesn't match"
|
||||
exit 1
|
||||
fi
|
||||
- name: Unpack binary
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt update && sudo apt install -y tar unzip
|
||||
cd docker/clio/artifact
|
||||
@@ -85,6 +80,7 @@ jobs:
|
||||
|
||||
- name: Strip binary
|
||||
if: ${{ inputs.strip_binary }}
|
||||
shell: bash
|
||||
run: strip ./docker/clio/clio_server
|
||||
|
||||
- name: Set GHCR_REPO
|
||||
|
||||
36
.github/workflows/build.yml
vendored
36
.github/workflows/build.yml
vendored
@@ -23,7 +23,6 @@ on:
|
||||
- "cmake/**"
|
||||
- "src/**"
|
||||
- "tests/**"
|
||||
- "benchmarks/**"
|
||||
|
||||
- docs/config-description.md
|
||||
workflow_dispatch:
|
||||
@@ -34,10 +33,6 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/develop' && github.run_number || 'branch' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
name: Build and Test
|
||||
@@ -50,7 +45,7 @@ jobs:
|
||||
build_type: [Release, Debug]
|
||||
container:
|
||||
[
|
||||
'{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }',
|
||||
'{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }',
|
||||
]
|
||||
static: [true]
|
||||
|
||||
@@ -80,11 +75,11 @@ jobs:
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
conan_profile: gcc
|
||||
build_type: Debug
|
||||
download_ccache: true
|
||||
upload_ccache: true
|
||||
upload_ccache: false
|
||||
code_coverage: true
|
||||
static: true
|
||||
upload_clio_server: false
|
||||
@@ -93,21 +88,40 @@ jobs:
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
package:
|
||||
name: Build packages
|
||||
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
conan_profile: gcc
|
||||
build_type: Release
|
||||
download_ccache: true
|
||||
upload_ccache: false
|
||||
code_coverage: false
|
||||
static: true
|
||||
upload_clio_server: false
|
||||
package: true
|
||||
targets: package
|
||||
analyze_build_time: false
|
||||
|
||||
check_config:
|
||||
name: Check Config Description
|
||||
needs: build-and-test
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: clio_server_Linux_Release_gcc
|
||||
|
||||
- name: Compare Config Description
|
||||
shell: bash
|
||||
run: |
|
||||
repoConfigFile=docs/config-description.md
|
||||
configDescriptionFile=config_description_new.md
|
||||
|
||||
22
.github/workflows/check-libxrpl.yml
vendored
22
.github/workflows/check-libxrpl.yml
vendored
@@ -12,33 +12,31 @@ concurrency:
|
||||
env:
|
||||
CONAN_PROFILE: gcc
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build Clio / `libXRPL ${{ github.event.client_payload.version }}`
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
|
||||
with:
|
||||
enable_ccache: false
|
||||
disable_ccache: true
|
||||
|
||||
- name: Update libXRPL version requirement
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i.bak -E "s|'xrpl/[a-zA-Z0-9\\.\\-]+'|'xrpl/${{ github.event.client_payload.conan_ref }}'|g" conanfile.py
|
||||
rm -f conanfile.py.bak
|
||||
|
||||
- name: Update conan lockfile
|
||||
shell: bash
|
||||
run: |
|
||||
conan lock create . --profile:all ${{ env.CONAN_PROFILE }}
|
||||
|
||||
@@ -59,7 +57,7 @@ jobs:
|
||||
run: strip build/clio_tests
|
||||
|
||||
- name: Upload clio_tests
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: clio_tests_check_libxrpl
|
||||
path: build/clio_tests
|
||||
@@ -69,10 +67,10 @@ jobs:
|
||||
needs: build
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: clio_tests_check_libxrpl
|
||||
|
||||
@@ -92,7 +90,7 @@ jobs:
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create an issue
|
||||
uses: ./.github/actions/create-issue
|
||||
|
||||
16
.github/workflows/check-pr-title.yml
vendored
16
.github/workflows/check-pr-title.yml
vendored
@@ -7,4 +7,18 @@ on:
|
||||
|
||||
jobs:
|
||||
check_title:
|
||||
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@943eb8277e8f4b010fde0c826ce4154c36c39509
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: ytanikin/pr-conventional-commits@b72758283dcbee706975950e96bc4bf323a8d8c0 # v1.4.2
|
||||
with:
|
||||
task_types: '["build","feat","fix","docs","test","ci","style","refactor","perf","chore"]'
|
||||
add_label: false
|
||||
custom_labels: '{"build":"build", "feat":"enhancement", "fix":"bug", "docs":"documentation", "test":"testability", "ci":"ci", "style":"refactoring", "refactor":"refactoring", "perf":"performance", "chore":"tooling"}'
|
||||
|
||||
- name: Check if message starts with upper-case letter
|
||||
run: |
|
||||
if [[ ! "${{ github.event.pull_request.title }}" =~ ^[a-z]+:\ [\[A-Z] ]]; then
|
||||
echo "Error: PR title must start with an upper-case letter."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
66
.github/workflows/clang-tidy.yml
vendored
66
.github/workflows/clang-tidy.yml
vendored
@@ -22,16 +22,12 @@ env:
|
||||
CONAN_PROFILE: clang
|
||||
LLVM_TOOLS_VERSION: 20
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
clang_tidy:
|
||||
if: github.event_name != 'push' || contains(github.event.head_commit.message, 'clang-tidy auto fixes')
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -39,14 +35,21 @@ jobs:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
|
||||
with:
|
||||
enable_ccache: false
|
||||
disable_ccache: true
|
||||
|
||||
- name: Restore cache
|
||||
uses: ./.github/actions/restore-cache
|
||||
id: restore_cache
|
||||
with:
|
||||
conan_profile: ${{ env.CONAN_PROFILE }}
|
||||
ccache_dir: ${{ env.CCACHE_DIR }}
|
||||
|
||||
- name: Run conan
|
||||
uses: ./.github/actions/conan
|
||||
@@ -58,34 +61,34 @@ jobs:
|
||||
with:
|
||||
conan_profile: ${{ env.CONAN_PROFILE }}
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
|
||||
id: nproc
|
||||
- name: Get number of threads
|
||||
uses: ./.github/actions/get-threads-number
|
||||
id: number_of_threads
|
||||
|
||||
- name: Run clang-tidy (several times)
|
||||
- name: Run clang-tidy
|
||||
continue-on-error: true
|
||||
id: clang_tidy
|
||||
shell: bash
|
||||
id: run_clang_tidy
|
||||
run: |
|
||||
# We run clang-tidy several times, because some fixes may enable new fixes in subsequent runs.
|
||||
CLANG_TIDY_COMMAND="run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j ${{ steps.nproc.outputs.nproc }} -fix -quiet"
|
||||
${CLANG_TIDY_COMMAND} ||
|
||||
${CLANG_TIDY_COMMAND} ||
|
||||
${CLANG_TIDY_COMMAND}
|
||||
|
||||
- name: Check for changes
|
||||
id: files_changed
|
||||
continue-on-error: true
|
||||
run: |
|
||||
git diff --exit-code
|
||||
run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j "${{ steps.number_of_threads.outputs.threads_number }}" -fix -quiet 1>output.txt
|
||||
|
||||
- name: Fix local includes and clang-format style
|
||||
if: ${{ steps.files_changed.outcome != 'success' }}
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
shell: bash
|
||||
run: |
|
||||
pre-commit run --all-files fix-local-includes || true
|
||||
pre-commit run --all-files clang-format || true
|
||||
|
||||
- name: Print issues found
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i '/error\||/!d' ./output.txt
|
||||
cat output.txt
|
||||
rm output.txt
|
||||
|
||||
- name: Create an issue
|
||||
if: ${{ (steps.clang_tidy.outcome != 'success' || steps.files_changed.outcome != 'success') && github.event_name != 'pull_request' }}
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
|
||||
id: create_issue
|
||||
uses: ./.github/actions/create-issue
|
||||
env:
|
||||
@@ -97,8 +100,8 @@ jobs:
|
||||
|
||||
List of the issues found: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
|
||||
|
||||
- uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd # v7.0.0
|
||||
if: ${{ steps.files_changed.outcome != 'success' && github.event_name != 'pull_request' }}
|
||||
- uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
|
||||
passphrase: ${{ secrets.ACTIONS_GPG_PASSPHRASE }}
|
||||
@@ -106,8 +109,8 @@ jobs:
|
||||
git_commit_gpgsign: true
|
||||
|
||||
- name: Create PR with fixes
|
||||
if: ${{ steps.files_changed.outcome != 'success' && github.event_name != 'pull_request' }}
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
env:
|
||||
GH_REPO: ${{ github.repository }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
@@ -122,5 +125,6 @@ jobs:
|
||||
reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
|
||||
|
||||
- name: Fail the job
|
||||
if: ${{ steps.clang_tidy.outcome != 'success' || steps.files_changed.outcome != 'success' }}
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
shell: bash
|
||||
run: exit 1
|
||||
|
||||
18
.github/workflows/docs.yml
vendored
18
.github/workflows/docs.yml
vendored
@@ -10,26 +10,22 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
|
||||
with:
|
||||
enable_ccache: false
|
||||
disable_ccache: true
|
||||
|
||||
- name: Create build directory
|
||||
run: mkdir build_docs
|
||||
@@ -43,10 +39,10 @@ jobs:
|
||||
run: cmake --build . --target docs
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
|
||||
uses: actions/configure-pages@v5
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
with:
|
||||
path: build_docs/html
|
||||
name: docs-develop
|
||||
@@ -66,6 +62,6 @@ jobs:
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
|
||||
uses: actions/deploy-pages@v4
|
||||
with:
|
||||
artifact_name: docs-develop
|
||||
|
||||
59
.github/workflows/nightly.yml
vendored
59
.github/workflows/nightly.yml
vendored
@@ -23,25 +23,9 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
get_date:
|
||||
name: Get Date
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
date: ${{ steps.get_date.outputs.date }}
|
||||
steps:
|
||||
- name: Get current date
|
||||
id: get_date
|
||||
run: |
|
||||
echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
|
||||
|
||||
build-and-test:
|
||||
name: Build and Test
|
||||
needs: get_date
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -55,17 +39,17 @@ jobs:
|
||||
conan_profile: gcc
|
||||
build_type: Release
|
||||
static: true
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
- os: heavy
|
||||
conan_profile: gcc
|
||||
build_type: Debug
|
||||
static: true
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
- os: heavy
|
||||
conan_profile: gcc.ubsan
|
||||
build_type: Release
|
||||
static: false
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
with:
|
||||
@@ -79,31 +63,9 @@ jobs:
|
||||
upload_clio_server: true
|
||||
download_ccache: false
|
||||
upload_ccache: false
|
||||
version: nightly-${{ needs.get_date.outputs.date }}
|
||||
|
||||
package:
|
||||
name: Build debian package
|
||||
needs: get_date
|
||||
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
conan_profile: gcc
|
||||
build_type: Release
|
||||
download_ccache: false
|
||||
upload_ccache: false
|
||||
code_coverage: false
|
||||
static: true
|
||||
upload_clio_server: false
|
||||
package: true
|
||||
version: nightly-${{ needs.get_date.outputs.date }}
|
||||
targets: package
|
||||
analyze_build_time: false
|
||||
|
||||
analyze_build_time:
|
||||
name: Analyze Build Time
|
||||
needs: get_date
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -111,7 +73,7 @@ jobs:
|
||||
include:
|
||||
- os: heavy
|
||||
conan_profile: clang
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
static: true
|
||||
- os: macos15
|
||||
conan_profile: apple-clang
|
||||
@@ -130,20 +92,19 @@ jobs:
|
||||
upload_clio_server: false
|
||||
targets: all
|
||||
analyze_build_time: true
|
||||
version: nightly-${{ needs.get_date.outputs.date }}
|
||||
|
||||
nightly_release:
|
||||
needs: [build-and-test, package, get_date]
|
||||
needs: build-and-test
|
||||
uses: ./.github/workflows/reusable-release.yml
|
||||
with:
|
||||
delete_pattern: "nightly-*"
|
||||
overwrite_release: true
|
||||
prerelease: true
|
||||
title: "Clio development build (nightly-${{ needs.get_date.outputs.date }})"
|
||||
version: nightly-${{ needs.get_date.outputs.date }}
|
||||
title: "Clio development (nightly) build"
|
||||
version: nightly
|
||||
header: >
|
||||
> **Note:** Please remember that this is a development release and it is not recommended for production use.
|
||||
|
||||
Changelog (including previous releases): <https://github.com/XRPLF/clio/commits/nightly-${{ needs.get_date.outputs.date }}>
|
||||
Changelog (including previous releases): <https://github.com/XRPLF/clio/commits/nightly>
|
||||
generate_changelog: false
|
||||
draft: false
|
||||
|
||||
@@ -169,7 +130,7 @@ jobs:
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create an issue
|
||||
uses: ./.github/actions/create-issue
|
||||
|
||||
4
.github/workflows/pre-commit-autoupdate.yml
vendored
4
.github/workflows/pre-commit-autoupdate.yml
vendored
@@ -1,8 +1,8 @@
|
||||
name: Pre-commit auto-update
|
||||
|
||||
on:
|
||||
# every first day of the month
|
||||
schedule:
|
||||
# every first day of the month
|
||||
- cron: "0 0 1 * *"
|
||||
pull_request:
|
||||
branches: [release/*, develop]
|
||||
@@ -12,7 +12,7 @@ on:
|
||||
|
||||
jobs:
|
||||
auto-update:
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@44856eb0d6ecb7d376370244324ab3dc8b863bad
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@afbcbdafbe0ce5439492fb87eda6441371086386
|
||||
with:
|
||||
sign_commit: true
|
||||
committer: "Clio CI <skuznetsov@ripple.com>"
|
||||
|
||||
4
.github/workflows/pre-commit.yml
vendored
4
.github/workflows/pre-commit.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
|
||||
jobs:
|
||||
run-hooks:
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@44856eb0d6ecb7d376370244324ab3dc8b863bad
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@a8d7472b450eb53a1e5228f64552e5974457a21a
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-pre-commit:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-pre-commit:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
|
||||
27
.github/workflows/release.yml
vendored
27
.github/workflows/release.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
conan_profile: gcc
|
||||
build_type: Release
|
||||
static: true
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
with:
|
||||
@@ -43,32 +43,13 @@ jobs:
|
||||
upload_clio_server: true
|
||||
download_ccache: false
|
||||
upload_ccache: false
|
||||
version: ${{ github.event_name == 'push' && github.ref_name || '' }}
|
||||
|
||||
package:
|
||||
name: Build debian package
|
||||
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
conan_profile: gcc
|
||||
build_type: Release
|
||||
download_ccache: false
|
||||
upload_ccache: false
|
||||
code_coverage: false
|
||||
static: true
|
||||
upload_clio_server: false
|
||||
package: true
|
||||
version: ${{ github.event_name == 'push' && github.ref_name || '' }}
|
||||
targets: package
|
||||
analyze_build_time: false
|
||||
expected_version: ${{ github.event_name == 'push' && github.ref_name || '' }}
|
||||
|
||||
release:
|
||||
needs: [build-and-test, package]
|
||||
needs: build-and-test
|
||||
uses: ./.github/workflows/reusable-release.yml
|
||||
with:
|
||||
delete_pattern: ""
|
||||
overwrite_release: false
|
||||
prerelease: ${{ contains(github.ref_name, '-') }}
|
||||
title: "${{ github.ref_name }}"
|
||||
version: "${{ github.ref_name }}"
|
||||
|
||||
14
.github/workflows/reusable-build-test.yml
vendored
14
.github/workflows/reusable-build-test.yml
vendored
@@ -63,18 +63,18 @@ on:
|
||||
type: string
|
||||
default: all
|
||||
|
||||
expected_version:
|
||||
description: Expected version of the clio_server binary
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
package:
|
||||
description: Whether to generate Debian package
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
version:
|
||||
description: Version of the clio_server binary
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
@@ -90,8 +90,8 @@ jobs:
|
||||
upload_clio_server: ${{ inputs.upload_clio_server }}
|
||||
targets: ${{ inputs.targets }}
|
||||
analyze_build_time: false
|
||||
expected_version: ${{ inputs.expected_version }}
|
||||
package: ${{ inputs.package }}
|
||||
version: ${{ inputs.version }}
|
||||
|
||||
test:
|
||||
needs: build
|
||||
|
||||
107
.github/workflows/reusable-build.yml
vendored
107
.github/workflows/reusable-build.yml
vendored
@@ -60,25 +60,21 @@ on:
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
expected_version:
|
||||
description: Expected version of the clio_server binary
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
package:
|
||||
description: Whether to generate Debian package
|
||||
required: false
|
||||
type: boolean
|
||||
|
||||
version:
|
||||
description: Version of the clio_server binary
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
secrets:
|
||||
CODECOV_TOKEN:
|
||||
required: false
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
@@ -88,38 +84,36 @@ jobs:
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
# We need to fetch tags to have correct version in the release
|
||||
# The workaround is based on https://github.com/actions/checkout/issues/1467
|
||||
fetch-tags: true
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
|
||||
with:
|
||||
enable_ccache: ${{ inputs.download_ccache }}
|
||||
disable_ccache: ${{ !inputs.download_ccache }}
|
||||
|
||||
- name: Setup conan on macOS
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
shell: bash
|
||||
run: ./.github/scripts/conan/init.sh
|
||||
|
||||
- name: Generate cache key
|
||||
uses: ./.github/actions/cache-key
|
||||
id: cache_key
|
||||
- name: Restore cache
|
||||
if: ${{ inputs.download_ccache }}
|
||||
uses: ./.github/actions/restore-cache
|
||||
id: restore_cache
|
||||
with:
|
||||
conan_profile: ${{ inputs.conan_profile }}
|
||||
ccache_dir: ${{ env.CCACHE_DIR }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
code_coverage: ${{ inputs.code_coverage }}
|
||||
|
||||
- name: Restore ccache cache
|
||||
if: ${{ inputs.download_ccache && github.ref != 'refs/heads/develop' }}
|
||||
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: ${{ steps.cache_key.outputs.key }}
|
||||
restore-keys: |
|
||||
${{ steps.cache_key.outputs.restore_keys }}
|
||||
|
||||
- name: Run conan
|
||||
uses: ./.github/actions/conan
|
||||
with:
|
||||
@@ -135,7 +129,6 @@ jobs:
|
||||
static: ${{ inputs.static }}
|
||||
time_trace: ${{ inputs.analyze_build_time }}
|
||||
package: ${{ inputs.package }}
|
||||
version: ${{ inputs.version }}
|
||||
|
||||
- name: Build Clio
|
||||
uses: ./.github/actions/build-clio
|
||||
@@ -148,26 +141,24 @@ jobs:
|
||||
ClangBuildAnalyzer --all build/ build_time_report.bin
|
||||
ClangBuildAnalyzer --analyze build_time_report.bin > build_time_report.txt
|
||||
cat build_time_report.txt
|
||||
shell: bash
|
||||
|
||||
- name: Upload build time analyze report
|
||||
if: ${{ inputs.analyze_build_time }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_time_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
path: build_time_report.txt
|
||||
|
||||
- name: Show ccache's statistics and zero it
|
||||
- name: Show ccache's statistics
|
||||
if: ${{ inputs.download_ccache }}
|
||||
shell: bash
|
||||
id: ccache_stats
|
||||
run: |
|
||||
ccache --show-stats -vv
|
||||
ccache --zero-stats
|
||||
|
||||
- name: Save ccache cache
|
||||
if: ${{ inputs.upload_ccache && github.ref == 'refs/heads/develop' }}
|
||||
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: ${{ steps.cache_key.outputs.key }}
|
||||
ccache -s > /tmp/ccache.stats
|
||||
miss_rate=$(cat /tmp/ccache.stats | grep 'Misses' | head -n1 | sed 's/.*(\(.*\)%).*/\1/')
|
||||
echo "miss_rate=${miss_rate}" >> $GITHUB_OUTPUT
|
||||
cat /tmp/ccache.stats
|
||||
|
||||
- name: Strip unit_tests
|
||||
if: ${{ !endsWith(inputs.conan_profile, 'san') && !inputs.code_coverage && !inputs.analyze_build_time }}
|
||||
@@ -179,32 +170,44 @@ jobs:
|
||||
|
||||
- name: Upload clio_server
|
||||
if: ${{ inputs.upload_clio_server && !inputs.code_coverage && !inputs.analyze_build_time }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: clio_server_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
path: build/clio_server
|
||||
|
||||
- name: Upload clio_tests
|
||||
if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
path: build/clio_tests
|
||||
|
||||
- name: Upload clio_integration_tests
|
||||
if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
path: build/clio_integration_tests
|
||||
|
||||
- name: Upload Clio Linux package
|
||||
if: ${{ inputs.package }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: clio_deb_package_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
path: build/*.deb
|
||||
|
||||
- name: Save cache
|
||||
if: ${{ inputs.upload_ccache && github.ref == 'refs/heads/develop' }}
|
||||
uses: ./.github/actions/save-cache
|
||||
with:
|
||||
conan_profile: ${{ inputs.conan_profile }}
|
||||
ccache_dir: ${{ env.CCACHE_DIR }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
code_coverage: ${{ inputs.code_coverage }}
|
||||
|
||||
ccache_cache_hit: ${{ steps.restore_cache.outputs.ccache_cache_hit }}
|
||||
ccache_cache_miss_rate: ${{ steps.ccache_stats.outputs.miss_rate }}
|
||||
|
||||
# This is run as part of the build job, because it requires the following:
|
||||
# - source code
|
||||
# - conan packages
|
||||
@@ -215,21 +218,15 @@ jobs:
|
||||
if: ${{ inputs.code_coverage }}
|
||||
uses: ./.github/actions/code-coverage
|
||||
|
||||
- name: Verify version is expected
|
||||
if: ${{ inputs.version != '' }}
|
||||
env:
|
||||
INPUT_VERSION: ${{ inputs.version }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
- name: Verify expected version
|
||||
if: ${{ inputs.expected_version != '' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
EXPECTED_VERSION="clio-${INPUT_VERSION}"
|
||||
if [[ "${BUILD_TYPE}" == "Debug" ]]; then
|
||||
EXPECTED_VERSION="${EXPECTED_VERSION}+DEBUG"
|
||||
fi
|
||||
|
||||
actual_version=$(./build/clio_server --version | head -n 1)
|
||||
if [[ "${actual_version}" != "${EXPECTED_VERSION}" ]]; then
|
||||
echo "Expected version '${EXPECTED_VERSION}', but got '${actual_version}'"
|
||||
EXPECTED_VERSION="clio-${{ inputs.expected_version }}"
|
||||
actual_version=$(./build/clio_server --version)
|
||||
if [[ "$actual_version" != "$EXPECTED_VERSION" ]]; then
|
||||
echo "Expected version '$EXPECTED_VERSION', but got '$actual_version'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
75
.github/workflows/reusable-release.yml
vendored
75
.github/workflows/reusable-release.yml
vendored
@@ -3,10 +3,10 @@ name: Make release
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
delete_pattern:
|
||||
description: "Pattern to delete previous releases"
|
||||
overwrite_release:
|
||||
description: "Overwrite the current release and tag"
|
||||
required: true
|
||||
type: string
|
||||
type: boolean
|
||||
|
||||
prerelease:
|
||||
description: "Create a prerelease"
|
||||
@@ -38,15 +38,11 @@ on:
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d
|
||||
env:
|
||||
GH_REPO: ${{ github.repository }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
@@ -55,75 +51,62 @@ jobs:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
|
||||
with:
|
||||
enable_ccache: false
|
||||
disable_ccache: true
|
||||
|
||||
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: release_artifacts
|
||||
pattern: clio_server_*
|
||||
|
||||
- name: Prepare release artifacts
|
||||
run: .github/scripts/prepare-release-artifacts.sh release_artifacts
|
||||
|
||||
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
with:
|
||||
path: release_artifacts
|
||||
pattern: clio_deb_package_*
|
||||
|
||||
- name: Create release notes
|
||||
env:
|
||||
RELEASE_HEADER: ${{ inputs.header }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "# Release notes" > "${RUNNER_TEMP}/release_notes.md"
|
||||
echo "" >> "${RUNNER_TEMP}/release_notes.md"
|
||||
printf '%s\n' "${RELEASE_HEADER}" >> "${RUNNER_TEMP}/release_notes.md"
|
||||
printf '%s\n' "${{ inputs.header }}" >> "${RUNNER_TEMP}/release_notes.md"
|
||||
|
||||
- name: Generate changelog
|
||||
shell: bash
|
||||
if: ${{ inputs.generate_changelog }}
|
||||
run: |
|
||||
LAST_TAG="$(gh release view --json tagName -q .tagName --repo XRPLF/clio)"
|
||||
LAST_TAG_COMMIT="$(git rev-parse $LAST_TAG)"
|
||||
BASE_COMMIT="$(git merge-base HEAD $LAST_TAG_COMMIT)"
|
||||
git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b|-rc" >> "${RUNNER_TEMP}/release_notes.md"
|
||||
git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b|-rc"
|
||||
cat CHANGELOG.md >> "${RUNNER_TEMP}/release_notes.md"
|
||||
|
||||
- name: Prepare release artifacts
|
||||
shell: bash
|
||||
run: .github/scripts/prepare-release-artifacts.sh release_artifacts
|
||||
|
||||
- name: Upload release notes
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release_notes_${{ inputs.version }}
|
||||
path: "${RUNNER_TEMP}/release_notes.md"
|
||||
|
||||
- name: Remove previous release with a pattern
|
||||
if: ${{ github.event_name != 'pull_request' && inputs.delete_pattern != '' }}
|
||||
env:
|
||||
DELETE_PATTERN: ${{ inputs.delete_pattern }}
|
||||
- name: Remove current release and tag
|
||||
if: ${{ github.event_name != 'pull_request' && inputs.overwrite_release }}
|
||||
shell: bash
|
||||
run: |
|
||||
RELEASES_TO_DELETE=$(gh release list --limit 50 --repo "${GH_REPO}" | grep -E "${DELETE_PATTERN}" | awk -F'\t' '{print $3}' || true)
|
||||
if [ -n "$RELEASES_TO_DELETE" ]; then
|
||||
for RELEASE in $RELEASES_TO_DELETE; do
|
||||
echo "Deleting release: $RELEASE"
|
||||
gh release delete "$RELEASE" --repo "${GH_REPO}" --yes --cleanup-tag
|
||||
done
|
||||
fi
|
||||
gh release delete ${{ inputs.version }} --yes || true
|
||||
git push origin :${{ inputs.version }} || true
|
||||
|
||||
- name: Publish release
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
env:
|
||||
RELEASE_VERSION: ${{ inputs.version }}
|
||||
PRERELEASE_OPTION: ${{ inputs.prerelease && '--prerelease' || '' }}
|
||||
RELEASE_TITLE: ${{ inputs.title }}
|
||||
DRAFT_OPTION: ${{ inputs.draft && '--draft' || '' }}
|
||||
shell: bash
|
||||
run: |
|
||||
gh release create "${RELEASE_VERSION}" \
|
||||
${PRERELEASE_OPTION} \
|
||||
--title "${RELEASE_TITLE}" \
|
||||
gh release create "${{ inputs.version }}" \
|
||||
${{ inputs.prerelease && '--prerelease' || '' }} \
|
||||
--title "${{ inputs.title }}" \
|
||||
--target "${GITHUB_SHA}" \
|
||||
${DRAFT_OPTION} \
|
||||
${{ inputs.draft && '--draft' || '' }} \
|
||||
--notes-file "${RUNNER_TEMP}/release_notes.md" \
|
||||
./release_artifacts/clio_*
|
||||
./release_artifacts/clio_server*
|
||||
|
||||
74
.github/workflows/reusable-test.yml
vendored
74
.github/workflows/reusable-test.yml
vendored
@@ -33,10 +33,6 @@ on:
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
unit_tests:
|
||||
name: Unit testing
|
||||
@@ -45,29 +41,56 @@ jobs:
|
||||
|
||||
if: ${{ inputs.run_unit_tests }}
|
||||
|
||||
env:
|
||||
# TODO: remove completely when we have fixed all currently existing issues with sanitizers
|
||||
SANITIZER_IGNORE_ERRORS: ${{ endsWith(inputs.conan_profile, '.tsan') || inputs.conan_profile == 'clang.asan' || (inputs.conan_profile == 'gcc.asan' && inputs.build_type == 'Release') }}
|
||||
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
|
||||
- name: Make clio_tests executable
|
||||
shell: bash
|
||||
run: chmod +x ./clio_tests
|
||||
|
||||
- name: Run clio_tests
|
||||
continue-on-error: true
|
||||
id: run_clio_tests
|
||||
- name: Run clio_tests (regular)
|
||||
if: ${{ env.SANITIZER_IGNORE_ERRORS == 'false' }}
|
||||
run: ./clio_tests
|
||||
|
||||
- name: Run clio_tests (sanitizer errors ignored)
|
||||
if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' }}
|
||||
run: ./.github/scripts/execute-tests-under-sanitizer ./clio_tests
|
||||
|
||||
- name: Check for sanitizer report
|
||||
if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' }}
|
||||
shell: bash
|
||||
id: check_report
|
||||
run: |
|
||||
if ls .sanitizer-report/* 1> /dev/null 2>&1; then
|
||||
echo "found_report=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "found_report=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Upload sanitizer report
|
||||
if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' && steps.check_report.outputs.found_report == 'true' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sanitizer_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
path: .sanitizer-report/*
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Create an issue
|
||||
if: ${{ steps.run_clio_tests.outcome == 'failure' && endsWith(inputs.conan_profile, 'san') }}
|
||||
if: ${{ false && env.SANITIZER_IGNORE_ERRORS == 'true' && steps.check_report.outputs.found_report == 'true' }}
|
||||
uses: ./.github/actions/create-issue
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
@@ -75,13 +98,10 @@ jobs:
|
||||
labels: "bug"
|
||||
title: "[${{ inputs.conan_profile }}] reported issues"
|
||||
body: >
|
||||
Clio tests failed one or more sanitizer checks when built with `${{ inputs.conan_profile }}`.
|
||||
Clio tests failed one or more sanitizer checks when built with ${{ inputs.conan_profile }}`.
|
||||
|
||||
Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
|
||||
|
||||
- name: Fail the job if clio_tests failed
|
||||
if: ${{ steps.run_clio_tests.outcome == 'failure' }}
|
||||
run: exit 1
|
||||
Reports are available as artifacts.
|
||||
|
||||
integration_tests:
|
||||
name: Integration testing
|
||||
@@ -102,19 +122,13 @@ jobs:
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
|
||||
|
||||
- name: Delete and start colima (macOS)
|
||||
# This is a temporary workaround for colima issues on macOS runners
|
||||
- name: Spin up scylladb
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
colima delete --force
|
||||
colima start
|
||||
|
||||
- name: Spin up scylladb (macOS)
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
timeout-minutes: 1
|
||||
run: |
|
||||
docker rm --force scylladb || true
|
||||
docker run \
|
||||
--detach \
|
||||
--name scylladb \
|
||||
@@ -126,15 +140,11 @@ jobs:
|
||||
--memory 16G \
|
||||
scylladb/scylla
|
||||
|
||||
- name: Wait for scylladb container to be healthy (macOS)
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
timeout-minutes: 1
|
||||
run: |
|
||||
until [ "$(docker inspect -f '{{.State.Health.Status}}' scylladb)" == "healthy" ]; do
|
||||
sleep 1
|
||||
sleep 5
|
||||
done
|
||||
|
||||
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
|
||||
|
||||
@@ -6,29 +6,25 @@ on:
|
||||
CODECOV_TOKEN:
|
||||
required: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
upload_report:
|
||||
name: Upload report
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download report artifact
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: coverage-report.xml
|
||||
path: build
|
||||
|
||||
- name: Upload coverage report
|
||||
if: ${{ hashFiles('build/coverage_report.xml') != '' }}
|
||||
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
|
||||
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
|
||||
with:
|
||||
files: build/coverage_report.xml
|
||||
fail_ci_if_error: true
|
||||
|
||||
6
.github/workflows/sanitizers.yml
vendored
6
.github/workflows/sanitizers.yml
vendored
@@ -15,6 +15,7 @@ on:
|
||||
- ".github/actions/**"
|
||||
- "!.github/actions/build-docker-image/**"
|
||||
- "!.github/actions/create-issue/**"
|
||||
- .github/scripts/execute-tests-under-sanitizer
|
||||
|
||||
- CMakeLists.txt
|
||||
- conanfile.py
|
||||
@@ -43,13 +44,14 @@ jobs:
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d" }'
|
||||
download_ccache: false
|
||||
upload_ccache: false
|
||||
conan_profile: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
|
||||
build_type: ${{ matrix.build_type }}
|
||||
static: false
|
||||
run_unit_tests: true
|
||||
# Currently, both gcc.tsan and clang.tsan unit tests hang
|
||||
run_unit_tests: ${{ matrix.sanitizer_ext != '.tsan' }}
|
||||
run_integration_tests: false
|
||||
upload_clio_server: false
|
||||
targets: clio_tests clio_integration_tests
|
||||
|
||||
46
.github/workflows/update-docker-ci.yml
vendored
46
.github/workflows/update-docker-ci.yml
vendored
@@ -33,10 +33,6 @@ env:
|
||||
GCC_MAJOR_VERSION: 15
|
||||
GCC_VERSION: 15.2.0
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
repo:
|
||||
name: Calculate repo name
|
||||
@@ -56,11 +52,11 @@ jobs:
|
||||
needs: repo
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
|
||||
with:
|
||||
files: "docker/compilers/gcc/**"
|
||||
|
||||
@@ -94,11 +90,11 @@ jobs:
|
||||
needs: repo
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
|
||||
with:
|
||||
files: "docker/compilers/gcc/**"
|
||||
|
||||
@@ -132,20 +128,20 @@ jobs:
|
||||
needs: [repo, gcc-amd64, gcc-arm64]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
|
||||
with:
|
||||
files: "docker/compilers/gcc/**"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -153,7 +149,7 @@ jobs:
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USER }}
|
||||
password: ${{ secrets.DOCKERHUB_PW }}
|
||||
@@ -183,11 +179,11 @@ jobs:
|
||||
needs: repo
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
|
||||
with:
|
||||
files: "docker/compilers/clang/**"
|
||||
|
||||
@@ -219,11 +215,11 @@ jobs:
|
||||
needs: [repo, gcc-merge]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
|
||||
with:
|
||||
files: "docker/tools/**"
|
||||
|
||||
@@ -250,11 +246,11 @@ jobs:
|
||||
needs: [repo, gcc-merge]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
|
||||
with:
|
||||
files: "docker/tools/**"
|
||||
|
||||
@@ -281,20 +277,20 @@ jobs:
|
||||
needs: [repo, tools-amd64, tools-arm64]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
|
||||
with:
|
||||
files: "docker/tools/**"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -316,7 +312,7 @@ jobs:
|
||||
needs: [repo, tools-merge]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/build-docker-image
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -338,7 +334,7 @@ jobs:
|
||||
needs: [repo, gcc-merge, clang, tools-merge]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/build-docker-image
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
19
.github/workflows/upload-conan-deps.yml
vendored
19
.github/workflows/upload-conan-deps.yml
vendored
@@ -22,7 +22,6 @@ on:
|
||||
|
||||
- .github/actions/conan/action.yml
|
||||
- ".github/scripts/conan/**"
|
||||
- "!.github/scripts/conan/regenerate_lockfile.sh"
|
||||
|
||||
- conanfile.py
|
||||
- conan.lock
|
||||
@@ -33,7 +32,6 @@ on:
|
||||
|
||||
- .github/actions/conan/action.yml
|
||||
- ".github/scripts/conan/**"
|
||||
- "!.github/scripts/conan/regenerate_lockfile.sh"
|
||||
|
||||
- conanfile.py
|
||||
- conan.lock
|
||||
@@ -42,17 +40,13 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Calculate conan matrix
|
||||
id: set-matrix
|
||||
@@ -75,15 +69,16 @@ jobs:
|
||||
CONAN_PROFILE: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
|
||||
with:
|
||||
enable_ccache: false
|
||||
disable_ccache: true
|
||||
|
||||
- name: Setup conan on macOS
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
shell: bash
|
||||
run: ./.github/scripts/conan/init.sh
|
||||
|
||||
- name: Show conan profile
|
||||
@@ -104,6 +99,4 @@ jobs:
|
||||
|
||||
- name: Upload Conan packages
|
||||
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' && github.event_name != 'schedule' }}
|
||||
env:
|
||||
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
|
||||
run: conan upload "*" -r=xrplf --confirm ${FORCE_OPTION}
|
||||
run: conan upload "*" -r=xrplf --confirm ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -4,11 +4,8 @@
|
||||
.build
|
||||
.cache
|
||||
.vscode
|
||||
.zed
|
||||
.python-version
|
||||
.DS_Store
|
||||
.sanitizer-report
|
||||
CMakeUserPresets.json
|
||||
config.json
|
||||
CLAUDE.md
|
||||
.claude/**
|
||||
|
||||
@@ -11,10 +11,7 @@
|
||||
#
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
exclude: |
|
||||
(?x)^(
|
||||
docs/doxygen-awesome-theme/.*
|
||||
)$
|
||||
exclude: ^(docs/doxygen-awesome-theme/|conan\.lock$)
|
||||
|
||||
repos:
|
||||
# `pre-commit sample-config` default hooks
|
||||
@@ -29,12 +26,12 @@ repos:
|
||||
|
||||
# Autoformat: YAML, JSON, Markdown, etc.
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
|
||||
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
|
||||
hooks:
|
||||
- id: prettier
|
||||
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: 76b3d32d3f4b965e1d6425253c59407420ae2c43 # frozen: v0.47.0
|
||||
rev: 192ad822316c3a22fb3d3cc8aa6eafa0b8488360 # frozen: v0.45.0
|
||||
hooks:
|
||||
- id: markdownlint-fix
|
||||
exclude: LICENSE.md
|
||||
@@ -58,17 +55,6 @@ repos:
|
||||
--ignore-words=pre-commit-hooks/codespell_ignore.txt,
|
||||
]
|
||||
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/scop/pre-commit-shfmt
|
||||
rev: 2a30809d16bc7a60d9b97353c797f42b510d3368 # frozen: v3.12.0-2
|
||||
hooks:
|
||||
- id: shfmt
|
||||
args: ["-i", "4", "--write"]
|
||||
|
||||
# Running some C++ hooks before clang-format
|
||||
# to ensure that the style is consistent.
|
||||
- repo: local
|
||||
@@ -94,16 +80,17 @@ repos:
|
||||
language: script
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: cd481d7b0bfb5c7b3090c21846317f9a8262e891 # frozen: v22.1.0
|
||||
rev: 719856d56a62953b8d2839fb9e851f25c3cfeef8 # frozen: v21.1.2
|
||||
hooks:
|
||||
- id: clang-format
|
||||
args: [--style=file]
|
||||
types: [c++]
|
||||
|
||||
- repo: https://github.com/BlankSpruce/gersemi
|
||||
rev: 0.26.0
|
||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||
rev: e2c2116d86a80e72e7146a06e68b7c228afc6319 # frozen: v0.6.13
|
||||
hooks:
|
||||
- id: gersemi
|
||||
- id: cmake-format
|
||||
additional_dependencies: [PyYAML]
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(
|
||||
clio
|
||||
VERSION ${CLIO_VERSION}
|
||||
HOMEPAGE_URL "https://github.com/XRPLF/clio"
|
||||
DESCRIPTION "An XRP Ledger API Server"
|
||||
project(clio VERSION ${CLIO_VERSION} HOMEPAGE_URL "https://github.com/XRPLF/clio"
|
||||
DESCRIPTION "An XRP Ledger API Server"
|
||||
)
|
||||
|
||||
# =========================== Options ====================================== #
|
||||
@@ -18,11 +15,7 @@ option(package "Create distribution packages" FALSE)
|
||||
option(lint "Run clang-tidy checks during compilation" FALSE)
|
||||
option(static "Statically linked Clio" FALSE)
|
||||
option(snapshot "Build snapshot tool" FALSE)
|
||||
option(
|
||||
time_trace
|
||||
"Build using -ftime-trace to create compiler trace reports"
|
||||
FALSE
|
||||
)
|
||||
option(time_trace "Build using -ftime-trace to create compiler trace reports" FALSE)
|
||||
|
||||
# ========================================================================== #
|
||||
set(san "" CACHE STRING "Add sanitizer instrumentation")
|
||||
@@ -42,9 +35,9 @@ add_library(clio_options INTERFACE)
|
||||
target_compile_features(clio_options INTERFACE cxx_std_23) # Clio needs c++23 but deps can remain c++20 for now
|
||||
target_include_directories(clio_options INTERFACE ${CMAKE_SOURCE_DIR}/src)
|
||||
|
||||
if(verbose)
|
||||
set(CMAKE_VERBOSE_MAKEFILE TRUE)
|
||||
endif()
|
||||
if (verbose)
|
||||
set(CMAKE_VERBOSE_MAKEFILE TRUE)
|
||||
endif ()
|
||||
|
||||
# Clio tweaks and checks
|
||||
include(CheckCompiler)
|
||||
@@ -64,43 +57,41 @@ include(deps/spdlog)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(tests)
|
||||
|
||||
if(benchmark)
|
||||
add_subdirectory(benchmarks)
|
||||
endif()
|
||||
if (benchmark)
|
||||
add_subdirectory(benchmarks)
|
||||
endif ()
|
||||
|
||||
# Enable selected sanitizer if enabled via `san`
|
||||
if(san)
|
||||
set(SUPPORTED_SANITIZERS "address" "thread" "memory" "undefined")
|
||||
if(NOT san IN_LIST SUPPORTED_SANITIZERS)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Error: Unsupported sanitizer '${san}'. Supported values are: ${SUPPORTED_SANITIZERS}."
|
||||
)
|
||||
endif()
|
||||
if (san)
|
||||
set(SUPPORTED_SANITIZERS "address" "thread" "memory" "undefined")
|
||||
if (NOT san IN_LIST SUPPORTED_SANITIZERS)
|
||||
message(FATAL_ERROR "Error: Unsupported sanitizer '${san}'. Supported values are: ${SUPPORTED_SANITIZERS}.")
|
||||
endif ()
|
||||
|
||||
# Sanitizers recommend minimum of -O1 for reasonable performance so we enable it for debug builds
|
||||
set(SAN_OPTIMIZATION_FLAG "")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(SAN_OPTIMIZATION_FLAG -O1)
|
||||
endif()
|
||||
target_compile_options(
|
||||
clio_options
|
||||
INTERFACE ${SAN_OPTIMIZATION_FLAG} ${SAN_FLAG} -fno-omit-frame-pointer
|
||||
)
|
||||
# Sanitizers recommend minimum of -O1 for reasonable performance so we enable it for debug builds
|
||||
set(SAN_OPTIMIZATION_FLAG "")
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(SAN_OPTIMIZATION_FLAG -O1)
|
||||
endif ()
|
||||
target_compile_options(clio_options INTERFACE ${SAN_OPTIMIZATION_FLAG} ${SAN_FLAG} -fno-omit-frame-pointer)
|
||||
|
||||
target_link_libraries(clio_options INTERFACE ${SAN_FLAG} ${SAN_LIB})
|
||||
endif()
|
||||
target_compile_definitions(
|
||||
clio_options INTERFACE $<$<STREQUAL:${san},address>:SANITIZER=ASAN> $<$<STREQUAL:${san},thread>:SANITIZER=TSAN>
|
||||
$<$<STREQUAL:${san},memory>:SANITIZER=MSAN> $<$<STREQUAL:${san},undefined>:SANITIZER=UBSAN>
|
||||
)
|
||||
target_link_libraries(clio_options INTERFACE ${SAN_FLAG} ${SAN_LIB})
|
||||
endif ()
|
||||
|
||||
# Generate `docs` target for doxygen documentation if enabled Note: use `make docs` to generate the documentation
|
||||
if(docs)
|
||||
add_subdirectory(docs)
|
||||
endif()
|
||||
if (docs)
|
||||
add_subdirectory(docs)
|
||||
endif ()
|
||||
|
||||
include(install/install)
|
||||
if(package)
|
||||
include(ClioPackage)
|
||||
endif()
|
||||
if (package)
|
||||
include(ClioPackage)
|
||||
endif ()
|
||||
|
||||
if(snapshot)
|
||||
add_subdirectory(tools/snapshot)
|
||||
endif()
|
||||
if (snapshot)
|
||||
add_subdirectory(tools/snapshot)
|
||||
endif ()
|
||||
|
||||
@@ -133,7 +133,7 @@ This is a non-exhaustive list of recommended style guidelines. These are not alw
|
||||
|
||||
Code must conform to `clang-format`, unless the result is unreasonably difficult to read or maintain.
|
||||
In most cases the `pre-commit` hook takes care of formatting and fixes any issues automatically.
|
||||
To manually format your code, run `pre-commit run clang-format --files <your changed files>` for C++ files, and `pre-commit run gersemi --files <your changed files>` for CMake files.
|
||||
To manually format your code, run `pre-commit run clang-format --files <your changed files>` for C++ files, and `pre-commit run cmake-format --files <your changed files>` for CMake files.
|
||||
|
||||
### Documentation
|
||||
|
||||
@@ -180,7 +180,6 @@ Existing maintainers can resign, or be subject to a vote for removal at the behe
|
||||
- [kuznetsss](https://github.com/kuznetsss) (Ripple)
|
||||
- [legleux](https://github.com/legleux) (Ripple)
|
||||
- [PeterChen13579](https://github.com/PeterChen13579) (Ripple)
|
||||
- [mathbunnyru](https://github.com/mathbunnyru) (Ripple)
|
||||
|
||||
### Honorable ex-Maintainers
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ Below are some useful docs to learn more about Clio.
|
||||
|
||||
- [How to configure Clio and rippled](./docs/configure-clio.md)
|
||||
- [How to run Clio](./docs/run-clio.md)
|
||||
- [Logging](./docs/logging.md)
|
||||
- [Troubleshooting guide](./docs/trouble_shooting.md)
|
||||
|
||||
**General reference material:**
|
||||
|
||||
@@ -1,27 +1,18 @@
|
||||
add_executable(clio_benchmark)
|
||||
|
||||
target_sources(
|
||||
clio_benchmark
|
||||
PRIVATE
|
||||
# Common
|
||||
Main.cpp
|
||||
Playground.cpp
|
||||
# ExecutionContext
|
||||
util/async/ExecutionContextBenchmarks.cpp
|
||||
# Logger
|
||||
util/log/LoggerBenchmark.cpp
|
||||
# WorkQueue
|
||||
rpc/WorkQueueBenchmarks.cpp
|
||||
clio_benchmark
|
||||
PRIVATE # Common
|
||||
Main.cpp
|
||||
Playground.cpp
|
||||
# ExecutionContext
|
||||
util/async/ExecutionContextBenchmarks.cpp
|
||||
# Logger
|
||||
util/log/LoggerBenchmark.cpp
|
||||
)
|
||||
|
||||
include(deps/gbench)
|
||||
|
||||
target_include_directories(clio_benchmark PRIVATE .)
|
||||
target_link_libraries(
|
||||
clio_benchmark
|
||||
PRIVATE clio_rpc clio_util benchmark::benchmark_main spdlog::spdlog
|
||||
)
|
||||
set_target_properties(
|
||||
clio_benchmark
|
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
target_link_libraries(clio_benchmark PUBLIC clio_util benchmark::benchmark_main spdlog::spdlog)
|
||||
set_target_properties(clio_benchmark PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2025, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "rpc/WorkQueue.hpp"
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/config/Array.hpp"
|
||||
#include "util/config/ConfigConstraints.hpp"
|
||||
#include "util/config/ConfigDefinition.hpp"
|
||||
#include "util/config/ConfigValue.hpp"
|
||||
#include "util/config/Types.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "util/prometheus/Prometheus.hpp"
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace rpc;
|
||||
using namespace util::config;
|
||||
|
||||
namespace {
|
||||
|
||||
auto const kCONFIG = ClioConfigDefinition{
|
||||
{"prometheus.compress_reply", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
|
||||
{"prometheus.enabled", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
|
||||
{"log.channels.[].channel", Array{ConfigValue{ConfigType::String}}},
|
||||
{"log.channels.[].level", Array{ConfigValue{ConfigType::String}}},
|
||||
{"log.level", ConfigValue{ConfigType::String}.defaultValue("info")},
|
||||
{"log.format",
|
||||
ConfigValue{ConfigType::String}.defaultValue(R"(%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v)")},
|
||||
{"log.is_async", ConfigValue{ConfigType::Boolean}.defaultValue(false)},
|
||||
{"log.enable_console", ConfigValue{ConfigType::Boolean}.defaultValue(false)},
|
||||
{"log.directory", ConfigValue{ConfigType::String}.optional()},
|
||||
{"log.rotation_size",
|
||||
ConfigValue{ConfigType::Integer}.defaultValue(2048).withConstraint(gValidateUint32)},
|
||||
{"log.directory_max_files",
|
||||
ConfigValue{ConfigType::Integer}.defaultValue(25).withConstraint(gValidateUint32)},
|
||||
{"log.tag_style", ConfigValue{ConfigType::String}.defaultValue("none")},
|
||||
};
|
||||
|
||||
// this should be a fixture but it did not work with Args very well
|
||||
void
|
||||
init()
|
||||
{
|
||||
static std::once_flag kONCE;
|
||||
std::call_once(kONCE, [] {
|
||||
PrometheusService::init(kCONFIG);
|
||||
(void)util::LogService::init(kCONFIG);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static void
|
||||
benchmarkWorkQueue(benchmark::State& state)
|
||||
{
|
||||
init();
|
||||
|
||||
auto const wqThreads = static_cast<uint32_t>(state.range(0));
|
||||
auto const maxQueueSize = static_cast<uint32_t>(state.range(1));
|
||||
auto const clientThreads = static_cast<uint32_t>(state.range(2));
|
||||
auto const itemsPerClient = static_cast<uint32_t>(state.range(3));
|
||||
auto const clientProcessingMs = static_cast<uint32_t>(state.range(4));
|
||||
|
||||
for (auto _ : state) {
|
||||
std::atomic_size_t totalExecuted = 0uz;
|
||||
std::atomic_size_t totalQueued = 0uz;
|
||||
|
||||
state.PauseTiming();
|
||||
WorkQueue queue(wqThreads, maxQueueSize);
|
||||
state.ResumeTiming();
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
threads.reserve(clientThreads);
|
||||
|
||||
for (auto t = 0uz; t < clientThreads; ++t) {
|
||||
threads.emplace_back([&] {
|
||||
for (auto i = 0uz; i < itemsPerClient; ++i) {
|
||||
totalQueued += static_cast<std::size_t>(queue.postCoro(
|
||||
[&clientProcessingMs, &totalExecuted](auto yield) {
|
||||
++totalExecuted;
|
||||
|
||||
boost::asio::steady_timer timer(
|
||||
yield.get_executor(), std::chrono::milliseconds{clientProcessingMs}
|
||||
);
|
||||
timer.async_wait(yield);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::microseconds{10});
|
||||
},
|
||||
/* isWhiteListed = */ false
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& t : threads)
|
||||
t.join();
|
||||
|
||||
queue.stop();
|
||||
|
||||
ASSERT(totalExecuted == totalQueued, "Totals don't match");
|
||||
ASSERT(totalQueued <= itemsPerClient * clientThreads, "Queued more than requested");
|
||||
|
||||
if (maxQueueSize == 0) {
|
||||
ASSERT(
|
||||
totalQueued == itemsPerClient * clientThreads, "Queued exactly the expected amount"
|
||||
);
|
||||
} else {
|
||||
ASSERT(
|
||||
totalQueued >= std::min(maxQueueSize, itemsPerClient * clientThreads),
|
||||
"Queued less than expected"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Usage example:
|
||||
/*
|
||||
./clio_benchmark \
|
||||
--benchmark_repetitions=10 \
|
||||
--benchmark_display_aggregates_only=true \
|
||||
--benchmark_min_time=1x \
|
||||
--benchmark_filter="WorkQueue"
|
||||
*/
|
||||
// TODO: figure out what happens on 1 thread
|
||||
BENCHMARK(benchmarkWorkQueue)
|
||||
->ArgsProduct({{2, 4, 8, 16}, {0, 5'000}, {4, 8, 16}, {1'000, 10'000}, {10, 100, 250}})
|
||||
->Unit(benchmark::kMillisecond);
|
||||
@@ -62,9 +62,8 @@ uniqueLogDir()
|
||||
{
|
||||
auto const epochTime = std::chrono::high_resolution_clock::now().time_since_epoch();
|
||||
auto const tmpDir = std::filesystem::temp_directory_path();
|
||||
std::string const dirName = fmt::format(
|
||||
"logs_{}", std::chrono::duration_cast<std::chrono::microseconds>(epochTime).count()
|
||||
);
|
||||
std::string const dirName =
|
||||
fmt::format("logs_{}", std::chrono::duration_cast<std::chrono::microseconds>(epochTime).count());
|
||||
return tmpDir / "clio_benchmark" / dirName;
|
||||
}
|
||||
|
||||
@@ -109,8 +108,7 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
|
||||
channel, fileSink, spdlog::thread_pool(), spdlog::async_overflow_policy::block
|
||||
);
|
||||
spdlog::register_logger(logger);
|
||||
Logger const threadLogger =
|
||||
BenchmarkLoggingInitializer::getLogger(std::move(logger));
|
||||
Logger const threadLogger = BenchmarkLoggingInitializer::getLogger(std::move(logger));
|
||||
|
||||
barrier.arrive_and_wait();
|
||||
|
||||
@@ -126,16 +124,13 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
|
||||
spdlog::shutdown();
|
||||
|
||||
auto const end = std::chrono::high_resolution_clock::now();
|
||||
state.SetIterationTime(
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count()
|
||||
);
|
||||
state.SetIterationTime(std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count());
|
||||
|
||||
std::filesystem::remove_all(logDir);
|
||||
}
|
||||
|
||||
auto const totalMessages = numThreads * messagesPerThread;
|
||||
state.counters["TotalMessagesRate"] =
|
||||
benchmark::Counter(totalMessages, benchmark::Counter::kIsRate);
|
||||
state.counters["TotalMessagesRate"] = benchmark::Counter(totalMessages, benchmark::Counter::kIsRate);
|
||||
state.counters["Threads"] = numThreads;
|
||||
state.counters["MessagesPerThread"] = messagesPerThread;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ postprocessors = [
|
||||
]
|
||||
# render body even when there are no releases to process
|
||||
# render_always = true
|
||||
# output file path
|
||||
output = "CHANGELOG.md"
|
||||
|
||||
[git]
|
||||
# parse the commits based on https://www.conventionalcommits.org
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
find_program(CCACHE_PATH "ccache")
|
||||
if(CCACHE_PATH)
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PATH}")
|
||||
message(STATUS "Using ccache: ${CCACHE_PATH}")
|
||||
endif()
|
||||
if (CCACHE_PATH)
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PATH}")
|
||||
message(STATUS "Using ccache: ${CCACHE_PATH}")
|
||||
endif ()
|
||||
|
||||
@@ -1,48 +1,42 @@
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
|
||||
message(FATAL_ERROR "Clang 16+ required for building clio")
|
||||
endif()
|
||||
set(is_clang TRUE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
|
||||
message(FATAL_ERROR "AppleClang 15+ required for building clio")
|
||||
endif()
|
||||
set(is_appleclang TRUE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12)
|
||||
message(FATAL_ERROR "GCC 12+ required for building clio")
|
||||
endif()
|
||||
set(is_gcc TRUE)
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Supported compilers: AppleClang 15+, Clang 16+, GCC 12+"
|
||||
)
|
||||
endif()
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
|
||||
message(FATAL_ERROR "Clang 16+ required for building clio")
|
||||
endif ()
|
||||
set(is_clang TRUE)
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
|
||||
message(FATAL_ERROR "AppleClang 15+ required for building clio")
|
||||
endif ()
|
||||
set(is_appleclang TRUE)
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12)
|
||||
message(FATAL_ERROR "GCC 12+ required for building clio")
|
||||
endif ()
|
||||
set(is_gcc TRUE)
|
||||
else ()
|
||||
message(FATAL_ERROR "Supported compilers: AppleClang 15+, Clang 16+, GCC 12+")
|
||||
endif ()
|
||||
|
||||
if(san)
|
||||
string(TOLOWER ${san} san)
|
||||
set(SAN_FLAG "-fsanitize=${san}")
|
||||
set(SAN_LIB "")
|
||||
if(is_gcc)
|
||||
if(san STREQUAL "address")
|
||||
set(SAN_LIB "asan")
|
||||
elseif(san STREQUAL "thread")
|
||||
set(SAN_LIB "tsan")
|
||||
elseif(san STREQUAL "memory")
|
||||
set(SAN_LIB "msan")
|
||||
elseif(san STREQUAL "undefined")
|
||||
set(SAN_LIB "ubsan")
|
||||
endif()
|
||||
endif()
|
||||
set(_saved_CRL ${CMAKE_REQUIRED_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${SAN_FLAG};${SAN_LIB}")
|
||||
check_cxx_compiler_flag(${SAN_FLAG} COMPILER_SUPPORTS_SAN)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${_saved_CRL})
|
||||
if(NOT COMPILER_SUPPORTS_SAN)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"${san} sanitizer does not seem to be supported by your compiler"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if (san)
|
||||
string(TOLOWER ${san} san)
|
||||
set(SAN_FLAG "-fsanitize=${san}")
|
||||
set(SAN_LIB "")
|
||||
if (is_gcc)
|
||||
if (san STREQUAL "address")
|
||||
set(SAN_LIB "asan")
|
||||
elseif (san STREQUAL "thread")
|
||||
set(SAN_LIB "tsan")
|
||||
elseif (san STREQUAL "memory")
|
||||
set(SAN_LIB "msan")
|
||||
elseif (san STREQUAL "undefined")
|
||||
set(SAN_LIB "ubsan")
|
||||
endif ()
|
||||
endif ()
|
||||
set(_saved_CRL ${CMAKE_REQUIRED_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${SAN_FLAG};${SAN_LIB}")
|
||||
check_cxx_compiler_flag(${SAN_FLAG} COMPILER_SUPPORTS_SAN)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${_saved_CRL})
|
||||
if (NOT COMPILER_SUPPORTS_SAN)
|
||||
message(FATAL_ERROR "${san} sanitizer does not seem to be supported by your compiler")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
@@ -1,41 +1,33 @@
|
||||
if(lint)
|
||||
# Find clang-tidy binary
|
||||
if(DEFINED ENV{CLIO_CLANG_TIDY_BIN})
|
||||
set(_CLANG_TIDY_BIN $ENV{CLIO_CLANG_TIDY_BIN})
|
||||
if((NOT EXISTS ${_CLANG_TIDY_BIN}) OR IS_DIRECTORY ${_CLANG_TIDY_BIN})
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"$ENV{CLIO_CLANG_TIDY_BIN} no such file. Check CLIO_CLANG_TIDY_BIN env variable"
|
||||
)
|
||||
endif()
|
||||
message(STATUS "Using clang-tidy from CLIO_CLANG_TIDY_BIN")
|
||||
else()
|
||||
find_program(
|
||||
_CLANG_TIDY_BIN
|
||||
NAMES "clang-tidy-20" "clang-tidy"
|
||||
REQUIRED
|
||||
)
|
||||
endif()
|
||||
if (lint)
|
||||
|
||||
if(NOT _CLANG_TIDY_BIN)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"clang-tidy binary not found. Please set the CLIO_CLANG_TIDY_BIN environment variable or install clang-tidy."
|
||||
)
|
||||
endif()
|
||||
# Find clang-tidy binary
|
||||
if (DEFINED ENV{CLIO_CLANG_TIDY_BIN})
|
||||
set(_CLANG_TIDY_BIN $ENV{CLIO_CLANG_TIDY_BIN})
|
||||
if ((NOT EXISTS ${_CLANG_TIDY_BIN}) OR IS_DIRECTORY ${_CLANG_TIDY_BIN})
|
||||
message(FATAL_ERROR "$ENV{CLIO_CLANG_TIDY_BIN} no such file. Check CLIO_CLANG_TIDY_BIN env variable")
|
||||
endif ()
|
||||
message(STATUS "Using clang-tidy from CLIO_CLANG_TIDY_BIN")
|
||||
else ()
|
||||
find_program(_CLANG_TIDY_BIN NAMES "clang-tidy-20" "clang-tidy" REQUIRED)
|
||||
endif ()
|
||||
|
||||
# Support for https://github.com/matus-chochlik/ctcache
|
||||
find_program(CLANG_TIDY_CACHE_PATH NAMES "clang-tidy-cache")
|
||||
if(CLANG_TIDY_CACHE_PATH)
|
||||
set(_CLANG_TIDY_CMD
|
||||
"${CLANG_TIDY_CACHE_PATH};${_CLANG_TIDY_BIN}"
|
||||
CACHE STRING
|
||||
"A combined command to run clang-tidy with caching wrapper"
|
||||
)
|
||||
else()
|
||||
set(_CLANG_TIDY_CMD "${_CLANG_TIDY_BIN}")
|
||||
endif()
|
||||
if (NOT _CLANG_TIDY_BIN)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"clang-tidy binary not found. Please set the CLIO_CLANG_TIDY_BIN environment variable or install clang-tidy."
|
||||
)
|
||||
endif ()
|
||||
|
||||
set(CMAKE_CXX_CLANG_TIDY "${_CLANG_TIDY_CMD};--quiet")
|
||||
message(STATUS "Using clang-tidy: ${CMAKE_CXX_CLANG_TIDY}")
|
||||
endif()
|
||||
# Support for https://github.com/matus-chochlik/ctcache
|
||||
find_program(CLANG_TIDY_CACHE_PATH NAMES "clang-tidy-cache")
|
||||
if (CLANG_TIDY_CACHE_PATH)
|
||||
set(_CLANG_TIDY_CMD "${CLANG_TIDY_CACHE_PATH};${_CLANG_TIDY_BIN}"
|
||||
CACHE STRING "A combined command to run clang-tidy with caching wrapper"
|
||||
)
|
||||
else ()
|
||||
set(_CLANG_TIDY_CMD "${_CLANG_TIDY_BIN}")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_CXX_CLANG_TIDY "${_CLANG_TIDY_CMD};--quiet")
|
||||
message(STATUS "Using clang-tidy: ${CMAKE_CXX_CLANG_TIDY}")
|
||||
endif ()
|
||||
|
||||
@@ -1,67 +1,47 @@
|
||||
find_package(Git REQUIRED)
|
||||
|
||||
if(DEFINED ENV{GITHUB_BRANCH_NAME})
|
||||
set(GIT_BUILD_BRANCH $ENV{GITHUB_BRANCH_NAME})
|
||||
set(GIT_COMMIT_HASH $ENV{GITHUB_HEAD_SHA})
|
||||
else()
|
||||
set(GIT_COMMAND branch --show-current)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_BUILD_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
|
||||
set(GIT_COMMAND rev-parse HEAD)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
endif()
|
||||
|
||||
set(GIT_COMMAND describe --tags --exact-match)
|
||||
execute_process(
|
||||
COMMAND date +%Y%m%d%H%M%S
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE BUILD_DATE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE TAG
|
||||
RESULT_VARIABLE RC
|
||||
ERROR_VARIABLE ERR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
message(STATUS "Git branch: ${GIT_BUILD_BRANCH}")
|
||||
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}")
|
||||
message(STATUS "Build date: ${BUILD_DATE}")
|
||||
if (RC EQUAL 0)
|
||||
message(STATUS "Found tag '${TAG}' in git. Will use it as Clio version")
|
||||
set(CLIO_VERSION "${TAG}")
|
||||
set(DOC_CLIO_VERSION "${TAG}")
|
||||
else ()
|
||||
message(STATUS "Error finding tag in git: ${ERR}")
|
||||
message(STATUS "Will use 'YYYYMMDDHMS-<branch>-<git-rev>' as Clio version")
|
||||
|
||||
if(
|
||||
DEFINED ENV{FORCE_CLIO_VERSION}
|
||||
AND NOT "$ENV{FORCE_CLIO_VERSION}" STREQUAL ""
|
||||
)
|
||||
message(
|
||||
STATUS
|
||||
"Using explicitly provided '${FORCE_CLIO_VERSION}' as Clio version"
|
||||
)
|
||||
set(GIT_COMMAND show -s --date=format:%Y%m%d%H%M%S --format=%cd)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE DATE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
|
||||
set(CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}")
|
||||
set(DOC_CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}")
|
||||
else()
|
||||
message(
|
||||
STATUS
|
||||
"Using 'YYYYMMDDHMS-<branch>-<git short rev>' as Clio version"
|
||||
)
|
||||
set(GIT_COMMAND branch --show-current)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
|
||||
string(SUBSTRING ${GIT_COMMIT_HASH} 0 7 GIT_COMMIT_HASH_SHORT)
|
||||
set(GIT_COMMAND rev-parse --short HEAD)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE REV
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
|
||||
set(CLIO_VERSION
|
||||
"${BUILD_DATE}-${GIT_BUILD_BRANCH}-${GIT_COMMIT_HASH_SHORT}"
|
||||
)
|
||||
set(DOC_CLIO_VERSION "develop")
|
||||
endif()
|
||||
set(CLIO_VERSION "${DATE}-${BRANCH}-${REV}")
|
||||
set(DOC_CLIO_VERSION "develop")
|
||||
endif ()
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(CLIO_VERSION "${CLIO_VERSION}+DEBUG")
|
||||
endif()
|
||||
if (CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(CLIO_VERSION "${CLIO_VERSION}+DEBUG")
|
||||
endif ()
|
||||
|
||||
message(STATUS "Build version: ${CLIO_VERSION}")
|
||||
|
||||
@@ -106,120 +106,78 @@ option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
|
||||
# Check prereqs
|
||||
find_program(GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
|
||||
|
||||
if(DEFINED CODE_COVERAGE_GCOV_TOOL)
|
||||
set(GCOV_TOOL "${CODE_COVERAGE_GCOV_TOOL}")
|
||||
elseif(DEFINED ENV{CODE_COVERAGE_GCOV_TOOL})
|
||||
set(GCOV_TOOL "$ENV{CODE_COVERAGE_GCOV_TOOL}")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
if(APPLE)
|
||||
execute_process(
|
||||
COMMAND xcrun -f llvm-cov
|
||||
OUTPUT_VARIABLE LLVMCOV_PATH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
else()
|
||||
find_program(LLVMCOV_PATH llvm-cov)
|
||||
endif()
|
||||
if(LLVMCOV_PATH)
|
||||
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
|
||||
endif()
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||
find_program(GCOV_PATH gcov)
|
||||
set(GCOV_TOOL "${GCOV_PATH}")
|
||||
endif()
|
||||
if (DEFINED CODE_COVERAGE_GCOV_TOOL)
|
||||
set(GCOV_TOOL "${CODE_COVERAGE_GCOV_TOOL}")
|
||||
elseif (DEFINED ENV{CODE_COVERAGE_GCOV_TOOL})
|
||||
set(GCOV_TOOL "$ENV{CODE_COVERAGE_GCOV_TOOL}")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
if (APPLE)
|
||||
execute_process(COMMAND xcrun -f llvm-cov OUTPUT_VARIABLE LLVMCOV_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
else ()
|
||||
find_program(LLVMCOV_PATH llvm-cov)
|
||||
endif ()
|
||||
if (LLVMCOV_PATH)
|
||||
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
|
||||
endif ()
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||
find_program(GCOV_PATH gcov)
|
||||
set(GCOV_TOOL "${GCOV_PATH}")
|
||||
endif ()
|
||||
|
||||
# Check supported compiler (Clang, GNU and Flang)
|
||||
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
foreach(LANG ${LANGUAGES})
|
||||
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Clang version must be 3.0.0 or greater! Aborting..."
|
||||
)
|
||||
endif()
|
||||
elseif(
|
||||
NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
|
||||
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang"
|
||||
)
|
||||
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
|
||||
endif()
|
||||
endforeach()
|
||||
foreach (LANG ${LANGUAGES})
|
||||
if ("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
if ("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
|
||||
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
|
||||
endif ()
|
||||
elseif (NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU" AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES
|
||||
"(LLVM)?[Ff]lang"
|
||||
)
|
||||
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
|
||||
endif ()
|
||||
endforeach ()
|
||||
|
||||
set(COVERAGE_COMPILER_FLAGS "-g --coverage" CACHE INTERNAL "")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
|
||||
if(HAVE_cxx_fprofile_abs_path)
|
||||
set(COVERAGE_CXX_COMPILER_FLAGS
|
||||
"${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path"
|
||||
)
|
||||
endif()
|
||||
include(CheckCCompilerFlag)
|
||||
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
|
||||
if(HAVE_c_fprofile_abs_path)
|
||||
set(COVERAGE_C_COMPILER_FLAGS
|
||||
"${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
|
||||
if (HAVE_cxx_fprofile_abs_path)
|
||||
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
endif ()
|
||||
include(CheckCCompilerFlag)
|
||||
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
|
||||
if (HAVE_c_fprofile_abs_path)
|
||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set(CMAKE_Fortran_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING
|
||||
"Flags used by the Fortran compiler during coverage builds."
|
||||
FORCE
|
||||
set(CMAKE_Fortran_FLAGS_COVERAGE ${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the Fortran compiler during coverage builds." FORCE
|
||||
)
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING
|
||||
"Flags used by the C++ compiler during coverage builds."
|
||||
FORCE
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE ${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds." FORCE
|
||||
)
|
||||
set(CMAKE_C_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING
|
||||
"Flags used by the C compiler during coverage builds."
|
||||
FORCE
|
||||
set(CMAKE_C_FLAGS_COVERAGE ${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C compiler during coverage builds." FORCE
|
||||
)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING
|
||||
"Flags used for linking binaries during coverage builds."
|
||||
FORCE
|
||||
)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING
|
||||
"Flags used by the shared libraries linker during coverage builds."
|
||||
FORCE
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "" CACHE STRING "Flags used for linking binaries during coverage builds." FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE ""
|
||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds." FORCE
|
||||
)
|
||||
mark_as_advanced(
|
||||
CMAKE_Fortran_FLAGS_COVERAGE
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_Fortran_FLAGS_COVERAGE CMAKE_CXX_FLAGS_COVERAGE CMAKE_C_FLAGS_COVERAGE CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
)
|
||||
|
||||
get_property(
|
||||
GENERATOR_IS_MULTI_CONFIG
|
||||
GLOBAL
|
||||
PROPERTY GENERATOR_IS_MULTI_CONFIG
|
||||
)
|
||||
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
|
||||
message(
|
||||
WARNING
|
||||
"Code coverage results with an optimised (non-Debug) build may be misleading"
|
||||
)
|
||||
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
|
||||
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if (NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
|
||||
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
|
||||
endif () # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
if(
|
||||
CMAKE_C_COMPILER_ID STREQUAL "GNU"
|
||||
OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU"
|
||||
)
|
||||
link_libraries(gcov)
|
||||
endif()
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||
link_libraries(gcov)
|
||||
endif ()
|
||||
|
||||
# Defines a target for running and collection code coverage information Builds dependencies, runs the given executable
|
||||
# and outputs reports. NOTE! The executable should always have a ZERO as exit code otherwise the coverage generation
|
||||
@@ -233,236 +191,171 @@ endif()
|
||||
# defaults to xml) EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative # to BASE_DIRECTORY,
|
||||
# with CMake 3.4+) ) The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the GCVOR
|
||||
# command.
|
||||
function(setup_target_for_coverage_gcovr)
|
||||
set(options NONE)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME FORMAT)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(
|
||||
Coverage
|
||||
"${options}"
|
||||
"${oneValueArgs}"
|
||||
"${multiValueArgs}"
|
||||
${ARGN}
|
||||
)
|
||||
function (setup_target_for_coverage_gcovr)
|
||||
set(options NONE)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME FORMAT)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT GCOV_TOOL)
|
||||
message(FATAL_ERROR "Could not find gcov or llvm-cov tool! Aborting...")
|
||||
endif()
|
||||
if (NOT GCOV_TOOL)
|
||||
message(FATAL_ERROR "Could not find gcov or llvm-cov tool! Aborting...")
|
||||
endif ()
|
||||
|
||||
if(NOT GCOVR_PATH)
|
||||
message(FATAL_ERROR "Could not find gcovr tool! Aborting...")
|
||||
endif()
|
||||
if (NOT GCOVR_PATH)
|
||||
message(FATAL_ERROR "Could not find gcovr tool! Aborting...")
|
||||
endif ()
|
||||
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if (DEFINED Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else ()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif ()
|
||||
|
||||
if(NOT DEFINED Coverage_FORMAT)
|
||||
set(Coverage_FORMAT xml)
|
||||
endif()
|
||||
if (NOT DEFINED Coverage_FORMAT)
|
||||
set(Coverage_FORMAT xml)
|
||||
endif ()
|
||||
|
||||
if("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting..."
|
||||
)
|
||||
else()
|
||||
if(
|
||||
(Coverage_FORMAT STREQUAL "html-details")
|
||||
OR (Coverage_FORMAT STREQUAL "html-nested")
|
||||
)
|
||||
set(GCOVR_OUTPUT_FILE
|
||||
${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html
|
||||
)
|
||||
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
|
||||
elseif(Coverage_FORMAT STREQUAL "html-single")
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
|
||||
elseif(
|
||||
(Coverage_FORMAT STREQUAL "json-summary")
|
||||
OR (Coverage_FORMAT STREQUAL "json-details")
|
||||
if ("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
|
||||
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting...")
|
||||
else ()
|
||||
if ((Coverage_FORMAT STREQUAL "html-details") OR (Coverage_FORMAT STREQUAL "html-nested"))
|
||||
set(GCOVR_OUTPUT_FILE ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html)
|
||||
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
|
||||
elseif (Coverage_FORMAT STREQUAL "html-single")
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
|
||||
elseif ((Coverage_FORMAT STREQUAL "json-summary") OR (Coverage_FORMAT STREQUAL "json-details")
|
||||
OR (Coverage_FORMAT STREQUAL "coveralls")
|
||||
)
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
|
||||
elseif(Coverage_FORMAT STREQUAL "txt")
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
|
||||
elseif(Coverage_FORMAT STREQUAL "csv")
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
|
||||
else()
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(
|
||||
(Coverage_FORMAT STREQUAL "cobertura")
|
||||
OR (Coverage_FORMAT STREQUAL "xml")
|
||||
)
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty)
|
||||
set(Coverage_FORMAT cobertura) # overwrite xml
|
||||
elseif(Coverage_FORMAT STREQUAL "sonarqube")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}")
|
||||
elseif(Coverage_FORMAT STREQUAL "json-summary")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
|
||||
elseif(Coverage_FORMAT STREQUAL "json-details")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
|
||||
elseif(Coverage_FORMAT STREQUAL "coveralls")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
|
||||
elseif(Coverage_FORMAT STREQUAL "csv")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --csv "${GCOVR_OUTPUT_FILE}")
|
||||
elseif(Coverage_FORMAT STREQUAL "txt")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --txt "${GCOVR_OUTPUT_FILE}")
|
||||
elseif(Coverage_FORMAT STREQUAL "html-single")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html-self-contained)
|
||||
elseif(Coverage_FORMAT STREQUAL "html-nested")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html-nested "${GCOVR_OUTPUT_FILE}")
|
||||
elseif(Coverage_FORMAT STREQUAL "html-details")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details "${GCOVR_OUTPUT_FILE}")
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Unsupported output style ${Coverage_FORMAT}! Aborting..."
|
||||
)
|
||||
endif()
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
|
||||
elseif (Coverage_FORMAT STREQUAL "txt")
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
|
||||
elseif (Coverage_FORMAT STREQUAL "csv")
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
|
||||
else ()
|
||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||
set(GCOVR_EXCLUDES "")
|
||||
foreach(
|
||||
EXCLUDE
|
||||
${Coverage_EXCLUDE}
|
||||
${COVERAGE_EXCLUDES}
|
||||
${COVERAGE_GCOVR_EXCLUDES}
|
||||
)
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(
|
||||
EXCLUDE
|
||||
${EXCLUDE}
|
||||
ABSOLUTE
|
||||
BASE_DIR ${BASEDIR}
|
||||
)
|
||||
endif()
|
||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
||||
if ((Coverage_FORMAT STREQUAL "cobertura") OR (Coverage_FORMAT STREQUAL "xml"))
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty)
|
||||
set(Coverage_FORMAT cobertura) # overwrite xml
|
||||
elseif (Coverage_FORMAT STREQUAL "sonarqube")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}")
|
||||
elseif (Coverage_FORMAT STREQUAL "json-summary")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
|
||||
elseif (Coverage_FORMAT STREQUAL "json-details")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
|
||||
elseif (Coverage_FORMAT STREQUAL "coveralls")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
|
||||
elseif (Coverage_FORMAT STREQUAL "csv")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --csv "${GCOVR_OUTPUT_FILE}")
|
||||
elseif (Coverage_FORMAT STREQUAL "txt")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --txt "${GCOVR_OUTPUT_FILE}")
|
||||
elseif (Coverage_FORMAT STREQUAL "html-single")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html "${GCOVR_OUTPUT_FILE}")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html-self-contained)
|
||||
elseif (Coverage_FORMAT STREQUAL "html-nested")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html-nested "${GCOVR_OUTPUT_FILE}")
|
||||
elseif (Coverage_FORMAT STREQUAL "html-details")
|
||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details "${GCOVR_OUTPUT_FILE}")
|
||||
else ()
|
||||
message(FATAL_ERROR "Unsupported output style ${Coverage_FORMAT}! Aborting...")
|
||||
endif ()
|
||||
|
||||
# Combine excludes to several -e arguments
|
||||
set(GCOVR_EXCLUDE_ARGS "")
|
||||
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
||||
endforeach()
|
||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||
set(GCOVR_EXCLUDES "")
|
||||
foreach (EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||
endif ()
|
||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
||||
endforeach ()
|
||||
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
||||
|
||||
# Set up commands which will be run to generate coverage data Run tests
|
||||
set(GCOVR_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
|
||||
# Combine excludes to several -e arguments
|
||||
set(GCOVR_EXCLUDE_ARGS "")
|
||||
foreach (EXCLUDE ${GCOVR_EXCLUDES})
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
||||
endforeach ()
|
||||
|
||||
# Create folder
|
||||
if(DEFINED GCOVR_CREATE_FOLDER)
|
||||
set(GCOVR_FOLDER_CMD
|
||||
${CMAKE_COMMAND}
|
||||
-E
|
||||
make_directory
|
||||
${GCOVR_CREATE_FOLDER}
|
||||
)
|
||||
else()
|
||||
set(GCOVR_FOLDER_CMD echo) # dummy
|
||||
endif()
|
||||
# Set up commands which will be run to generate coverage data Run tests
|
||||
set(GCOVR_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
|
||||
|
||||
# Running gcovr
|
||||
set(GCOVR_CMD
|
||||
${GCOVR_PATH}
|
||||
--gcov-executable
|
||||
${GCOV_TOOL}
|
||||
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
|
||||
-r
|
||||
${BASEDIR}
|
||||
${GCOVR_ADDITIONAL_ARGS}
|
||||
${GCOVR_EXCLUDE_ARGS}
|
||||
--object-directory=${PROJECT_BINARY_DIR}
|
||||
)
|
||||
# Create folder
|
||||
if (DEFINED GCOVR_CREATE_FOLDER)
|
||||
set(GCOVR_FOLDER_CMD ${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
|
||||
else ()
|
||||
set(GCOVR_FOLDER_CMD echo) # dummy
|
||||
endif ()
|
||||
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Executed command report")
|
||||
# Running gcovr
|
||||
set(GCOVR_CMD
|
||||
${GCOVR_PATH}
|
||||
--gcov-executable
|
||||
${GCOV_TOOL}
|
||||
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
|
||||
-r
|
||||
${BASEDIR}
|
||||
${GCOVR_ADDITIONAL_ARGS}
|
||||
${GCOVR_EXCLUDE_ARGS}
|
||||
--object-directory=${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
message(STATUS "Command to run tests: ")
|
||||
string(
|
||||
REPLACE ";"
|
||||
" "
|
||||
GCOVR_EXEC_TESTS_CMD_SPACED
|
||||
"${GCOVR_EXEC_TESTS_CMD}"
|
||||
)
|
||||
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
|
||||
if (CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Executed command report")
|
||||
|
||||
if(NOT GCOVR_FOLDER_CMD STREQUAL "echo")
|
||||
message(STATUS "Command to create a folder: ")
|
||||
string(
|
||||
REPLACE ";"
|
||||
" "
|
||||
GCOVR_FOLDER_CMD_SPACED
|
||||
"${GCOVR_FOLDER_CMD}"
|
||||
)
|
||||
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
|
||||
endif()
|
||||
message(STATUS "Command to run tests: ")
|
||||
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
|
||||
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to generate gcovr coverage data: ")
|
||||
string(REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD}")
|
||||
message(STATUS "${GCOVR_CMD_SPACED}")
|
||||
endif()
|
||||
if (NOT GCOVR_FOLDER_CMD STREQUAL "echo")
|
||||
message(STATUS "Command to create a folder: ")
|
||||
string(REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD}")
|
||||
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
|
||||
endif ()
|
||||
|
||||
add_custom_target(
|
||||
${Coverage_NAME}
|
||||
COMMAND ${GCOVR_EXEC_TESTS_CMD}
|
||||
COMMAND ${GCOVR_FOLDER_CMD}
|
||||
COMMAND ${GCOVR_CMD}
|
||||
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Running gcovr to produce code coverage report."
|
||||
)
|
||||
message(STATUS "Command to generate gcovr coverage data: ")
|
||||
string(REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD}")
|
||||
message(STATUS "${GCOVR_CMD_SPACED}")
|
||||
endif ()
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(
|
||||
TARGET ${Coverage_NAME}
|
||||
POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT
|
||||
"Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
|
||||
)
|
||||
endfunction() # setup_target_for_coverage_gcovr
|
||||
add_custom_target(
|
||||
${Coverage_NAME}
|
||||
COMMAND ${GCOVR_EXEC_TESTS_CMD}
|
||||
COMMAND ${GCOVR_FOLDER_CMD}
|
||||
COMMAND ${GCOVR_CMD}
|
||||
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Running gcovr to produce code coverage report."
|
||||
)
|
||||
|
||||
function(append_coverage_compiler_flags)
|
||||
set(CMAKE_C_FLAGS
|
||||
"${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
set(CMAKE_Fortran_FLAGS
|
||||
"${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
message(
|
||||
STATUS
|
||||
"Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
endfunction() # append_coverage_compiler_flags
|
||||
# Show info where to find the report
|
||||
add_custom_command(
|
||||
TARGET ${Coverage_NAME} POST_BUILD COMMAND ;
|
||||
COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
|
||||
)
|
||||
endfunction () # setup_target_for_coverage_gcovr
|
||||
|
||||
function (append_coverage_compiler_flags)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
|
||||
endfunction () # append_coverage_compiler_flags
|
||||
|
||||
# Setup coverage for specific library
|
||||
function(append_coverage_compiler_flags_to_target name mode)
|
||||
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
|
||||
target_compile_options(${name} ${mode} ${_flag_list})
|
||||
if(
|
||||
CMAKE_C_COMPILER_ID STREQUAL "GNU"
|
||||
OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU"
|
||||
)
|
||||
target_link_libraries(${name} ${mode} gcov)
|
||||
endif()
|
||||
endfunction()
|
||||
function (append_coverage_compiler_flags_to_target name mode)
|
||||
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
|
||||
target_compile_options(${name} ${mode} ${_flag_list})
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(${name} ${mode} gcov)
|
||||
endif ()
|
||||
endfunction ()
|
||||
|
||||
@@ -12,9 +12,9 @@ set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||
|
||||
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT})
|
||||
add_custom_target(
|
||||
docs
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen"
|
||||
VERBATIM
|
||||
docs
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
if(DEFINED CMAKE_LINKER_TYPE)
|
||||
message(STATUS "Custom linker is already set: ${CMAKE_LINKER_TYPE}")
|
||||
return()
|
||||
endif()
|
||||
if (DEFINED CMAKE_LINKER_TYPE)
|
||||
message(STATUS "Custom linker is already set: ${CMAKE_LINKER_TYPE}")
|
||||
return()
|
||||
endif ()
|
||||
|
||||
find_program(MOLD_PATH mold)
|
||||
|
||||
if(MOLD_PATH AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
message(STATUS "Using Mold linker: ${MOLD_PATH}")
|
||||
set(CMAKE_LINKER_TYPE MOLD)
|
||||
endif()
|
||||
if (MOLD_PATH AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
message(STATUS "Using Mold linker: ${MOLD_PATH}")
|
||||
set(CMAKE_LINKER_TYPE MOLD)
|
||||
endif ()
|
||||
|
||||
@@ -30,58 +30,53 @@ set(COMPILER_FLAGS
|
||||
# TODO: re-enable when we change CI #884 if (is_gcc AND NOT lint) list(APPEND COMPILER_FLAGS -Wduplicated-branches
|
||||
# -Wduplicated-cond -Wlogical-op -Wuseless-cast ) endif ()
|
||||
|
||||
if(is_clang)
|
||||
# gcc is too aggressive with shadowing
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78147
|
||||
list(APPEND COMPILER_FLAGS -Wshadow)
|
||||
endif()
|
||||
if (is_clang)
|
||||
list(APPEND COMPILER_FLAGS -Wshadow # gcc is to aggressive with shadowing
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78147
|
||||
)
|
||||
endif ()
|
||||
|
||||
if(is_appleclang)
|
||||
list(APPEND COMPILER_FLAGS -Wreorder-init-list)
|
||||
endif()
|
||||
if (is_appleclang)
|
||||
list(APPEND COMPILER_FLAGS -Wreorder-init-list)
|
||||
endif ()
|
||||
|
||||
if(san)
|
||||
# When building with sanitizers some compilers will actually produce extra warnings/errors. We don't want this yet,
|
||||
# at least not until we have fixed all runtime issues reported by the sanitizers. Once that is done we can start
|
||||
# removing some of these and trying to fix it in our codebase. We can never remove all of below because most of them
|
||||
# are reported from deep inside libraries like boost or libxrpl.
|
||||
#
|
||||
# TODO: Address in https://github.com/XRPLF/clio/issues/1885
|
||||
list(
|
||||
APPEND COMPILER_FLAGS
|
||||
-Wno-error=tsan # Disables treating TSAN warnings as errors
|
||||
-Wno-tsan # Disables TSAN warnings (thread-safety analysis)
|
||||
-Wno-uninitialized # Disables warnings about uninitialized variables (AddressSanitizer,
|
||||
# UndefinedBehaviorSanitizer, etc.)
|
||||
-Wno-stringop-overflow # Disables warnings about potential string operation overflows (AddressSanitizer)
|
||||
-Wno-unsafe-buffer-usage # Disables warnings about unsafe memory operations (AddressSanitizer)
|
||||
-Wno-frame-larger-than # Disables warnings about stack frame size being too large (AddressSanitizer)
|
||||
-Wno-unused-function # Disables warnings about unused functions (LeakSanitizer, memory-related issues)
|
||||
-Wno-unused-but-set-variable # Disables warnings about unused variables (MemorySanitizer)
|
||||
-Wno-thread-safety-analysis # Disables warnings related to thread safety usage (ThreadSanitizer)
|
||||
-Wno-thread-safety # Disables warnings related to thread safety usage (ThreadSanitizer)
|
||||
-Wno-sign-compare # Disables warnings about signed/unsigned comparison (UndefinedBehaviorSanitizer)
|
||||
-Wno-nonnull # Disables warnings related to null pointer dereferencing (UndefinedBehaviorSanitizer)
|
||||
-Wno-address # Disables warnings about address-related issues (UndefinedBehaviorSanitizer)
|
||||
-Wno-array-bounds # Disables array bounds checks (UndefinedBehaviorSanitizer)
|
||||
)
|
||||
endif()
|
||||
if (san)
|
||||
# When building with sanitizers some compilers will actually produce extra warnings/errors. We don't want this yet, at
|
||||
# least not until we have fixed all runtime issues reported by the sanitizers. Once that is done we can start removing
|
||||
# some of these and trying to fix it in our codebase. We can never remove all of below because most of them are
|
||||
# reported from deep inside libraries like boost or libxrpl.
|
||||
#
|
||||
# TODO: Address in https://github.com/XRPLF/clio/issues/1885
|
||||
list(
|
||||
APPEND
|
||||
COMPILER_FLAGS
|
||||
-Wno-error=tsan # Disables treating TSAN warnings as errors
|
||||
-Wno-tsan # Disables TSAN warnings (thread-safety analysis)
|
||||
-Wno-uninitialized # Disables warnings about uninitialized variables (AddressSanitizer, UndefinedBehaviorSanitizer,
|
||||
# etc.)
|
||||
-Wno-stringop-overflow # Disables warnings about potential string operation overflows (AddressSanitizer)
|
||||
-Wno-unsafe-buffer-usage # Disables warnings about unsafe memory operations (AddressSanitizer)
|
||||
-Wno-frame-larger-than # Disables warnings about stack frame size being too large (AddressSanitizer)
|
||||
-Wno-unused-function # Disables warnings about unused functions (LeakSanitizer, memory-related issues)
|
||||
-Wno-unused-but-set-variable # Disables warnings about unused variables (MemorySanitizer)
|
||||
-Wno-thread-safety-analysis # Disables warnings related to thread safety usage (ThreadSanitizer)
|
||||
-Wno-thread-safety # Disables warnings related to thread safety usage (ThreadSanitizer)
|
||||
-Wno-sign-compare # Disables warnings about signed/unsigned comparison (UndefinedBehaviorSanitizer)
|
||||
-Wno-nonnull # Disables warnings related to null pointer dereferencing (UndefinedBehaviorSanitizer)
|
||||
-Wno-address # Disables warnings about address-related issues (UndefinedBehaviorSanitizer)
|
||||
-Wno-array-bounds # Disables array bounds checks (UndefinedBehaviorSanitizer)
|
||||
)
|
||||
endif ()
|
||||
|
||||
# See https://github.com/cpp-best-practices/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#gcc--clang for
|
||||
# the flags description
|
||||
|
||||
if(time_trace)
|
||||
if(is_clang OR is_appleclang)
|
||||
list(APPEND COMPILER_FLAGS -ftime-trace)
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Clang or AppleClang is required to use `-ftime-trace`"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if (time_trace)
|
||||
if (is_clang OR is_appleclang)
|
||||
list(APPEND COMPILER_FLAGS -ftime-trace)
|
||||
else ()
|
||||
message(FATAL_ERROR "Clang or AppleClang is required to use `-ftime-trace`")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
target_compile_options(clio_options INTERFACE ${COMPILER_FLAGS})
|
||||
|
||||
# Add debug symbols for all builds, including Release. This is needed to get useful stack traces in production.
|
||||
target_compile_options(clio_options INTERFACE -g)
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
include(CheckIncludeFileCXX)
|
||||
|
||||
check_include_file_cxx("source_location" SOURCE_LOCATION_AVAILABLE)
|
||||
if(SOURCE_LOCATION_AVAILABLE)
|
||||
target_compile_definitions(clio_options INTERFACE "HAS_SOURCE_LOCATION")
|
||||
endif()
|
||||
if (SOURCE_LOCATION_AVAILABLE)
|
||||
target_compile_definitions(clio_options INTERFACE "HAS_SOURCE_LOCATION")
|
||||
endif ()
|
||||
|
||||
check_include_file_cxx(
|
||||
"experimental/source_location"
|
||||
EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE
|
||||
)
|
||||
if(EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE)
|
||||
target_compile_definitions(
|
||||
clio_options
|
||||
INTERFACE "HAS_EXPERIMENTAL_SOURCE_LOCATION"
|
||||
)
|
||||
endif()
|
||||
check_include_file_cxx("experimental/source_location" EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE)
|
||||
if (EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE)
|
||||
target_compile_definitions(clio_options INTERFACE "HAS_EXPERIMENTAL_SOURCE_LOCATION")
|
||||
endif ()
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
|
||||
find_package(
|
||||
Boost
|
||||
1.82
|
||||
REQUIRED
|
||||
CONFIG
|
||||
COMPONENTS program_options coroutine system log log_setup
|
||||
)
|
||||
find_package(Boost 1.82 REQUIRED CONFIG COMPONENTS program_options coroutine system log log_setup)
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
find_package(OpenSSL 1.1.1 REQUIRED CONFIG)
|
||||
|
||||
set_target_properties(
|
||||
OpenSSL::SSL
|
||||
PROPERTIES INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2
|
||||
)
|
||||
set_target_properties(OpenSSL::SSL PROPERTIES INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2)
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
if("${san}" STREQUAL "")
|
||||
target_compile_definitions(clio_options INTERFACE BOOST_STACKTRACE_LINK)
|
||||
target_compile_definitions(
|
||||
clio_options
|
||||
INTERFACE BOOST_STACKTRACE_USE_BACKTRACE
|
||||
)
|
||||
find_package(libbacktrace REQUIRED CONFIG)
|
||||
else()
|
||||
# Some sanitizers (TSAN and ASAN for sure) can't be used with libbacktrace because they have their own backtracing
|
||||
# capabilities and there are conflicts. In any case, this makes sure Clio code knows that backtrace is not
|
||||
# available. See relevant conan profiles for sanitizers where we disable stacktrace in Boost explicitly.
|
||||
target_compile_definitions(clio_options INTERFACE CLIO_WITHOUT_STACKTRACE)
|
||||
message(STATUS "Sanitizer enabled, disabling stacktrace")
|
||||
endif()
|
||||
if ("${san}" STREQUAL "")
|
||||
target_compile_definitions(clio_options INTERFACE BOOST_STACKTRACE_LINK)
|
||||
target_compile_definitions(clio_options INTERFACE BOOST_STACKTRACE_USE_BACKTRACE)
|
||||
find_package(libbacktrace REQUIRED CONFIG)
|
||||
else ()
|
||||
# Some sanitizers (TSAN and ASAN for sure) can't be used with libbacktrace because they have their own backtracing
|
||||
# capabilities and there are conflicts. In any case, this makes sure Clio code knows that backtrace is not available.
|
||||
# See relevant conan profiles for sanitizers where we disable stacktrace in Boost explicitly.
|
||||
target_compile_definitions(clio_options INTERFACE CLIO_WITHOUT_STACKTRACE)
|
||||
message(STATUS "Sanitizer enabled, disabling stacktrace")
|
||||
endif ()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
find_package(spdlog REQUIRED)
|
||||
|
||||
if(NOT TARGET spdlog::spdlog)
|
||||
message(FATAL_ERROR "spdlog::spdlog target not found")
|
||||
endif()
|
||||
if (NOT TARGET spdlog::spdlog)
|
||||
message(FATAL_ERROR "spdlog::spdlog target not found")
|
||||
endif ()
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
[Unit]
|
||||
Description=Clio XRPL API server
|
||||
Documentation=https://github.com/XRPLF/clio.git
|
||||
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=@CLIO_INSTALL_DIR@/bin/clio_server @CLIO_INSTALL_DIR@/etc/config.json
|
||||
Restart=on-failure
|
||||
User=clio
|
||||
Group=clio
|
||||
LimitNOFILE=65536
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,10 +1,5 @@
|
||||
set(CLIO_INSTALL_DIR "/opt/clio")
|
||||
set(CMAKE_INSTALL_PREFIX
|
||||
"${CLIO_INSTALL_DIR}"
|
||||
CACHE PATH
|
||||
"Install prefix"
|
||||
FORCE
|
||||
)
|
||||
set(CMAKE_INSTALL_PREFIX "${CLIO_INSTALL_DIR}" CACHE PATH "Install prefix" FORCE)
|
||||
|
||||
set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
@@ -15,17 +10,4 @@ install(TARGETS clio_server DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
file(READ docs/examples/config/example-config.json config)
|
||||
string(REGEX REPLACE "./clio_log" "/var/log/clio/" config "${config}")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/install-config.json "${config}")
|
||||
install(
|
||||
FILES ${CMAKE_BINARY_DIR}/install-config.json
|
||||
DESTINATION etc
|
||||
RENAME config.json
|
||||
)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/cmake/install/clio.service.in"
|
||||
"${CMAKE_BINARY_DIR}/clio.service"
|
||||
)
|
||||
install(
|
||||
FILES "${CMAKE_BINARY_DIR}/clio.service"
|
||||
DESTINATION /lib/systemd/system
|
||||
)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/install-config.json DESTINATION etc RENAME config.json)
|
||||
|
||||
@@ -10,36 +10,37 @@ CLIO_BIN="$CLIO_PREFIX/bin/${CLIO_EXECUTABLE}"
|
||||
CLIO_CONFIG="$CLIO_PREFIX/etc/config.json"
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
if ! id -u "$USER_NAME" >/dev/null 2>&1; then
|
||||
# Users who should not have a home directory should have their home directory set to /nonexistent
|
||||
# https://www.debian.org/doc/debian-policy/ch-opersys.html#non-existent-home-directories
|
||||
useradd \
|
||||
--system \
|
||||
--home-dir /nonexistent \
|
||||
--no-create-home \
|
||||
--shell /usr/sbin/nologin \
|
||||
--comment "system user for ${CLIO_EXECUTABLE}" \
|
||||
--user-group \
|
||||
${USER_NAME}
|
||||
fi
|
||||
configure)
|
||||
if ! id -u "$USER_NAME" >/dev/null 2>&1; then
|
||||
# Users who should not have a home directory should have their home directory set to /nonexistent
|
||||
# https://www.debian.org/doc/debian-policy/ch-opersys.html#non-existent-home-directories
|
||||
useradd \
|
||||
--system \
|
||||
--home-dir /nonexistent \
|
||||
--no-create-home \
|
||||
--shell /usr/sbin/nologin \
|
||||
--comment "system user for ${CLIO_EXECUTABLE}" \
|
||||
--user-group \
|
||||
${USER_NAME}
|
||||
fi
|
||||
|
||||
install -d -o "$USER_NAME" -g "$GROUP_NAME" /var/log/clio
|
||||
install -d -o "$USER_NAME" -g "$GROUP_NAME" /var/log/clio
|
||||
|
||||
if [ -f "$CLIO_CONFIG" ]; then
|
||||
chown "$USER_NAME:$GROUP_NAME" "$CLIO_CONFIG"
|
||||
fi
|
||||
if [ -f "$CLIO_CONFIG" ]; then
|
||||
chown "$USER_NAME:$GROUP_NAME" "$CLIO_CONFIG"
|
||||
fi
|
||||
|
||||
chown -R "$USER_NAME:$GROUP_NAME" "$CLIO_PREFIX"
|
||||
chown -R "$USER_NAME:$GROUP_NAME" "$CLIO_PREFIX"
|
||||
|
||||
ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
|
||||
ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
|
||||
|
||||
;;
|
||||
abort-upgrade | abort-remove | abort-deconfigure) ;;
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
;;
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
64
conan.lock
64
conan.lock
@@ -1,59 +1,55 @@
|
||||
{
|
||||
"version": "0.5",
|
||||
"requires": [
|
||||
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
|
||||
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
|
||||
"xrpl/3.1.0#3d408ab8c8020014fa7dd52bc7cc7ea8%1769706825.165",
|
||||
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926",
|
||||
"spdlog/1.17.0#bcbaaf7147bda6ad24ffbd1ac3d7142c%1768312128.781",
|
||||
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1765850149.46",
|
||||
"re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103",
|
||||
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
|
||||
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1756234289.683",
|
||||
"xrpl/2.6.1#973af2bf9631f239941dd9f5a100bb84%1759275059.342",
|
||||
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1756234266.869",
|
||||
"spdlog/1.15.3#3ca0e9e6b83af4d0151e26541d140c86%1754401846.61",
|
||||
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318",
|
||||
"re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1756234257.976",
|
||||
"rapidjson/cci.20220822#1b9d8c2256876a154172dc5cfbe447c6%1754325007.656",
|
||||
"protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456",
|
||||
"protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
|
||||
"openssl/1.1.1w#a8f0792d7c5121b954578a7149d23e03%1756223730.729",
|
||||
"nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32",
|
||||
"nudb/2.0.9#c62cfd501e57055a7e0d8ee3d5e5427d%1756234237.107",
|
||||
"minizip/1.2.13#9e87d57804bd372d6d1e32b1871517a3%1754325004.374",
|
||||
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
|
||||
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999",
|
||||
"libuv/1.46.0#dc28c1f653fa197f00db5b577a6f6011%1754325003.592",
|
||||
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
|
||||
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
|
||||
"libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736",
|
||||
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64",
|
||||
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1756230911.03",
|
||||
"libarchive/3.8.1#5cf685686322e906cb42706ab7e099a8%1756234256.696",
|
||||
"http_parser/2.9.4#98d91690d6fd021e9e624218a85d9d97%1754325001.385",
|
||||
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
|
||||
"gtest/1.14.0#f8f0757a574a8dd747d16af62d6eb1b7%1754325000.842",
|
||||
"grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1756234248.958",
|
||||
"fmt/12.1.0#50abab23274d56bb8f42c94b3b9a40c7%1763984116.926",
|
||||
"fmt/11.2.0#579bb2cdf4a7607621beea4eb4651e0f%1754324999.086",
|
||||
"doctest/2.4.11#a4211dfc329a16ba9f280f9574025659%1756234220.819",
|
||||
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
|
||||
"cassandra-cpp-driver/2.17.0#bd3934138689482102c265d01288a316%1764175359.611",
|
||||
"c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336",
|
||||
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
|
||||
"boost/1.83.0#91d8b1572534d2c334d6790e3c34d0c1%1764175359.61",
|
||||
"date/3.0.4#f74bbba5a08fa388256688743136cb6f%1756234217.493",
|
||||
"cassandra-cpp-driver/2.17.0#e50919efac8418c26be6671fd702540a%1754324997.363",
|
||||
"c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1756234217.915",
|
||||
"bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1756234261.716",
|
||||
"boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368%1754325043.336",
|
||||
"benchmark/1.9.4#ce4403f7a24d3e1f907cd9da4b678be4%1754578869.672",
|
||||
"abseil/20230802.1#90ba607d4ee8fb5fb157c3db540671fc%1764175359.429"
|
||||
"abseil/20230802.1#f0f91485b111dc9837a68972cb19ca7b%1756234220.907"
|
||||
],
|
||||
"build_requires": [
|
||||
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
|
||||
"protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456",
|
||||
"cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1765850153.937",
|
||||
"cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479",
|
||||
"b2/5.3.3#107c15377719889654eb9a162a673975%1765850144.355"
|
||||
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
|
||||
"protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
|
||||
"cmake/3.31.8#dde3bde00bb843687e55aea5afa0e220%1756234232.89",
|
||||
"b2/5.3.3#107c15377719889654eb9a162a673975%1756234226.28"
|
||||
],
|
||||
"python_requires": [],
|
||||
"overrides": {
|
||||
"protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88": [
|
||||
"boost/1.83.0": [
|
||||
null,
|
||||
"boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368"
|
||||
],
|
||||
"protobuf/3.21.12": [
|
||||
null,
|
||||
"protobuf/3.21.12"
|
||||
],
|
||||
"boost/1.83.0#91d8b1572534d2c334d6790e3c34d0c1": [
|
||||
null,
|
||||
"boost/1.83.0#91d8b1572534d2c334d6790e3c34d0c1"
|
||||
],
|
||||
"lz4/1.9.4": [
|
||||
"lz4/1.10.0"
|
||||
],
|
||||
"boost/1.90.0": [
|
||||
"boost/1.83.0"
|
||||
],
|
||||
"sqlite3/3.44.2": [
|
||||
"sqlite3/3.49.1"
|
||||
]
|
||||
|
||||
74
conanfile.py
74
conanfile.py
@@ -3,60 +3,62 @@ from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
|
||||
|
||||
|
||||
class ClioConan(ConanFile):
|
||||
name = "clio"
|
||||
license = "ISC"
|
||||
author = "Alex Kremer <akremer@ripple.com>, John Freeman <jfreeman@ripple.com>, Ayaz Salikhov <asalikhov@ripple.com>"
|
||||
url = "https://github.com/xrplf/clio"
|
||||
description = "Clio RPC server"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
name = 'clio'
|
||||
license = 'ISC'
|
||||
author = 'Alex Kremer <akremer@ripple.com>, John Freeman <jfreeman@ripple.com>, Ayaz Salikhov <asalikhov@ripple.com>'
|
||||
url = 'https://github.com/xrplf/clio'
|
||||
description = 'Clio RPC server'
|
||||
settings = 'os', 'compiler', 'build_type', 'arch'
|
||||
options = {}
|
||||
|
||||
requires = [
|
||||
"cassandra-cpp-driver/2.17.0",
|
||||
"fmt/12.1.0",
|
||||
"grpc/1.50.1",
|
||||
"libbacktrace/cci.20210118",
|
||||
"openssl/1.1.1w",
|
||||
"protobuf/3.21.12",
|
||||
"spdlog/1.17.0",
|
||||
"xrpl/3.1.0",
|
||||
"zlib/1.3.1",
|
||||
'boost/1.83.0',
|
||||
'cassandra-cpp-driver/2.17.0',
|
||||
'fmt/11.2.0',
|
||||
'protobuf/3.21.12',
|
||||
'grpc/1.50.1',
|
||||
'openssl/1.1.1w',
|
||||
'xrpl/2.6.1',
|
||||
'zlib/1.3.1',
|
||||
'libbacktrace/cci.20210118',
|
||||
'spdlog/1.15.3',
|
||||
]
|
||||
|
||||
default_options = {
|
||||
"cassandra-cpp-driver/*:shared": False,
|
||||
"date/*:header_only": True,
|
||||
"grpc/*:secure": True,
|
||||
"grpc/*:shared": False,
|
||||
"gtest/*:no_main": True,
|
||||
"libpq/*:shared": False,
|
||||
"lz4/*:shared": False,
|
||||
"openssl/*:shared": False,
|
||||
"protobuf/*:shared": False,
|
||||
"protobuf/*:with_zlib": True,
|
||||
"snappy/*:shared": False,
|
||||
"xrpl/*:rocksdb": False,
|
||||
"xrpl/*:tests": False,
|
||||
'xrpl/*:tests': False,
|
||||
'xrpl/*:rocksdb': False,
|
||||
'cassandra-cpp-driver/*:shared': False,
|
||||
'date/*:header_only': True,
|
||||
'grpc/*:shared': False,
|
||||
'grpc/*:secure': True,
|
||||
'libpq/*:shared': False,
|
||||
'lz4/*:shared': False,
|
||||
'openssl/*:shared': False,
|
||||
'protobuf/*:shared': False,
|
||||
'protobuf/*:with_zlib': True,
|
||||
'snappy/*:shared': False,
|
||||
'gtest/*:no_main': True,
|
||||
}
|
||||
|
||||
exports_sources = ("CMakeLists.txt", "cmake/*", "src/*")
|
||||
exports_sources = (
|
||||
'CMakeLists.txt', 'cmake/*', 'src/*'
|
||||
)
|
||||
|
||||
def requirements(self):
|
||||
self.requires("boost/1.83.0", force=True)
|
||||
self.requires("gtest/1.17.0")
|
||||
self.requires("benchmark/1.9.4")
|
||||
self.requires('gtest/1.14.0')
|
||||
self.requires('benchmark/1.9.4')
|
||||
|
||||
def configure(self):
|
||||
if self.settings.compiler == "apple-clang":
|
||||
self.options["boost"].visibility = "global"
|
||||
if self.settings.compiler == 'apple-clang':
|
||||
self.options['boost'].visibility = 'global'
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
# Fix this setting to follow the default introduced in Conan 1.48
|
||||
# to align with our build instructions.
|
||||
self.folders.generators = "build/generators"
|
||||
self.folders.generators = 'build/generators'
|
||||
|
||||
generators = "CMakeDeps"
|
||||
generators = 'CMakeDeps'
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
|
||||
@@ -36,6 +36,7 @@ RUN apt-get update \
|
||||
libmpfr-dev \
|
||||
libncurses-dev \
|
||||
make \
|
||||
ninja-build \
|
||||
wget \
|
||||
zip \
|
||||
&& apt-get clean \
|
||||
@@ -54,11 +55,8 @@ RUN pip install -q --no-cache-dir \
|
||||
# lxml 6.0.0 is not compatible with our image
|
||||
'lxml<6.0.0' \
|
||||
cmake \
|
||||
conan==2.24.0 \
|
||||
gcovr \
|
||||
# We're adding pre-commit to this image as well,
|
||||
# because clang-tidy workflow requires it
|
||||
pre-commit
|
||||
conan==2.20.1 \
|
||||
gcovr
|
||||
|
||||
# Install LLVM tools
|
||||
ARG LLVM_TOOLS_VERSION=20
|
||||
@@ -106,7 +104,6 @@ COPY --from=clio-tools \
|
||||
/usr/local/bin/git-cliff \
|
||||
/usr/local/bin/gh \
|
||||
/usr/local/bin/gdb \
|
||||
/usr/local/bin/ninja \
|
||||
/usr/local/bin/
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
@@ -5,18 +5,17 @@ It is used in [Clio Github Actions](https://github.com/XRPLF/clio/actions) but c
|
||||
|
||||
The image is based on Ubuntu 20.04 and contains:
|
||||
|
||||
- ccache 4.12.2
|
||||
- ccache 4.11.3
|
||||
- Clang 19
|
||||
- ClangBuildAnalyzer 1.6.0
|
||||
- Conan 2.24.0
|
||||
- Doxygen 1.16.1
|
||||
- Conan 2.20.1
|
||||
- Doxygen 1.14
|
||||
- GCC 15.2.0
|
||||
- GDB 17.1
|
||||
- gh 2.83.2
|
||||
- git-cliff 2.11.0
|
||||
- mold 2.40.4
|
||||
- Ninja 1.13.2
|
||||
- Python 3.8
|
||||
- GDB 16.3
|
||||
- gh 2.74
|
||||
- git-cliff 2.9.1
|
||||
- mold 2.40.1
|
||||
- Python 3.13
|
||||
- and some other useful tools
|
||||
|
||||
Conan is set up to build Clio without any additional steps.
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
{% set sanitizer_opt_map = {"asan": "address", "tsan": "thread", "ubsan": "undefined"} %}
|
||||
{% set sanitizer = sanitizer_opt_map[sani] %}
|
||||
|
||||
{% set sanitizer_b2_flags_map = {
|
||||
"address": "context-impl=ucontext address-sanitizer=norecover",
|
||||
"thread": "context-impl=ucontext thread-sanitizer=norecover",
|
||||
"undefined": "undefined-sanitizer=norecover"
|
||||
} %}
|
||||
{% set sanitizer_b2_flags_str = sanitizer_b2_flags_map[sanitizer] %}
|
||||
|
||||
{% set sanitizer_build_flags_str = "-fsanitize=" ~ sanitizer ~ " -g -O1 -fno-omit-frame-pointer" %}
|
||||
{% set sanitizer_build_flags = sanitizer_build_flags_str.split(' ') %}
|
||||
{% set sanitizer_link_flags_str = "-fsanitize=" ~ sanitizer %}
|
||||
@@ -18,8 +11,7 @@
|
||||
include({{ compiler }})
|
||||
|
||||
[options]
|
||||
boost/*:extra_b2_flags="{{ sanitizer_b2_flags_str }}"
|
||||
boost/*:without_context=False
|
||||
boost/*:extra_b2_flags="cxxflags=\"{{ sanitizer_build_flags_str }}\" linkflags=\"{{ sanitizer_link_flags_str }}\""
|
||||
boost/*:without_stacktrace=True
|
||||
|
||||
[conf]
|
||||
@@ -28,10 +20,4 @@ tools.build:cxxflags+={{ sanitizer_build_flags }}
|
||||
tools.build:exelinkflags+={{ sanitizer_link_flags }}
|
||||
tools.build:sharedlinkflags+={{ sanitizer_link_flags }}
|
||||
|
||||
{% if sanitizer == "address" %}
|
||||
tools.build:defines+=["BOOST_USE_ASAN", "BOOST_USE_UCONTEXT"]
|
||||
{% elif sanitizer == "thread" %}
|
||||
tools.build:defines+=["BOOST_USE_TSAN", "BOOST_USE_UCONTEXT"]
|
||||
{% endif %}
|
||||
|
||||
tools.info.package_id:confs+=["tools.build:cflags", "tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]
|
||||
tools.info.package_id:confs+=["tools.build:cflags", "tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"]
|
||||
|
||||
@@ -8,7 +8,7 @@ ARG UBUNTU_VERSION
|
||||
|
||||
ARG GCC_MAJOR_VERSION
|
||||
|
||||
ARG BUILD_VERSION=0
|
||||
ARG BUILD_VERSION=1
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG TARGETARCH
|
||||
@@ -34,7 +34,6 @@ RUN wget --progress=dot:giga https://gcc.gnu.org/pub/gcc/releases/gcc-$GCC_VERSI
|
||||
WORKDIR /gcc-$GCC_VERSION
|
||||
RUN ./contrib/download_prerequisites
|
||||
|
||||
# hadolint ignore=DL3059
|
||||
RUN mkdir /gcc-build
|
||||
WORKDIR /gcc-build
|
||||
RUN /gcc-$GCC_VERSION/configure \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
clio_develop:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d
|
||||
volumes:
|
||||
- clio_develop_conan_data:/root/.conan2/p
|
||||
- clio_develop_ccache:/root/.ccache
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
script_dir=$(dirname $0)
|
||||
|
||||
pushd $script_dir >/dev/null
|
||||
pushd $script_dir > /dev/null
|
||||
|
||||
function start_container {
|
||||
if [ -z "$(docker ps -q -f name=clio_develop)" ]; then
|
||||
@@ -41,26 +41,21 @@ EOF
|
||||
}
|
||||
|
||||
case $1 in
|
||||
-h | --help)
|
||||
print_help
|
||||
;;
|
||||
-h|--help)
|
||||
print_help ;;
|
||||
|
||||
-t | --terminal)
|
||||
open_terminal
|
||||
;;
|
||||
-t|--terminal)
|
||||
open_terminal ;;
|
||||
|
||||
-s | --stop)
|
||||
stop_container
|
||||
;;
|
||||
-s|--stop)
|
||||
stop_container ;;
|
||||
|
||||
-*)
|
||||
echo "Unknown option: $1"
|
||||
print_help
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1"
|
||||
print_help ;;
|
||||
|
||||
*)
|
||||
run "$@"
|
||||
;;
|
||||
*)
|
||||
run "$@" ;;
|
||||
esac
|
||||
|
||||
popd >/dev/null
|
||||
popd > /dev/null
|
||||
|
||||
@@ -8,10 +8,11 @@ ARG TARGETARCH
|
||||
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
ARG BUILD_VERSION=0
|
||||
ARG BUILD_VERSION=2
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
ninja-build \
|
||||
python3 \
|
||||
python3-pip \
|
||||
software-properties-common \
|
||||
@@ -23,16 +24,7 @@ RUN apt-get update \
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
ARG NINJA_VERSION=1.13.2
|
||||
|
||||
RUN wget --progress=dot:giga "https://github.com/ninja-build/ninja/archive/refs/tags/v${NINJA_VERSION}.tar.gz" \
|
||||
&& tar xf "v${NINJA_VERSION}.tar.gz" \
|
||||
&& cd "ninja-${NINJA_VERSION}" \
|
||||
&& ./configure.py --bootstrap \
|
||||
&& mv ninja /usr/local/bin/ninja \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
ARG MOLD_VERSION=2.40.4
|
||||
ARG MOLD_VERSION=2.40.1
|
||||
RUN wget --progress=dot:giga "https://github.com/rui314/mold/archive/refs/tags/v${MOLD_VERSION}.tar.gz" \
|
||||
&& tar xf "v${MOLD_VERSION}.tar.gz" \
|
||||
&& cd "mold-${MOLD_VERSION}" \
|
||||
@@ -42,7 +34,7 @@ RUN wget --progress=dot:giga "https://github.com/rui314/mold/archive/refs/tags/v
|
||||
&& ninja install \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
ARG CCACHE_VERSION=4.12.2
|
||||
ARG CCACHE_VERSION=4.11.3
|
||||
RUN wget --progress=dot:giga "https://github.com/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.gz" \
|
||||
&& tar xf "ccache-${CCACHE_VERSION}.tar.gz" \
|
||||
&& cd "ccache-${CCACHE_VERSION}" \
|
||||
@@ -59,7 +51,7 @@ RUN apt-get update \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG DOXYGEN_VERSION=1.16.1
|
||||
ARG DOXYGEN_VERSION=1.14.0
|
||||
RUN wget --progress=dot:giga "https://github.com/doxygen/doxygen/releases/download/Release_${DOXYGEN_VERSION//./_}/doxygen-${DOXYGEN_VERSION}.src.tar.gz" \
|
||||
&& tar xf "doxygen-${DOXYGEN_VERSION}.src.tar.gz" \
|
||||
&& cd "doxygen-${DOXYGEN_VERSION}" \
|
||||
@@ -79,13 +71,13 @@ RUN wget --progress=dot:giga "https://github.com/aras-p/ClangBuildAnalyzer/archi
|
||||
&& ninja install \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
ARG GIT_CLIFF_VERSION=2.11.0
|
||||
ARG GIT_CLIFF_VERSION=2.9.1
|
||||
RUN wget --progress=dot:giga "https://github.com/orhun/git-cliff/releases/download/v${GIT_CLIFF_VERSION}/git-cliff-${GIT_CLIFF_VERSION}-x86_64-unknown-linux-musl.tar.gz" \
|
||||
&& tar xf git-cliff-${GIT_CLIFF_VERSION}-x86_64-unknown-linux-musl.tar.gz \
|
||||
&& mv git-cliff-${GIT_CLIFF_VERSION}/git-cliff /usr/local/bin/git-cliff \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
ARG GH_VERSION=2.83.2
|
||||
ARG GH_VERSION=2.74.0
|
||||
RUN wget --progress=dot:giga "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz" \
|
||||
&& tar xf gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz \
|
||||
&& mv gh_${GH_VERSION}_linux_${TARGETARCH}/bin/gh /usr/local/bin/gh \
|
||||
@@ -100,7 +92,7 @@ RUN apt-get update \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG GDB_VERSION=17.1
|
||||
ARG GDB_VERSION=16.3
|
||||
RUN wget --progress=dot:giga "https://sourceware.org/pub/gdb/releases/gdb-${GDB_VERSION}.tar.gz" \
|
||||
&& tar xf "gdb-${GDB_VERSION}.tar.gz" \
|
||||
&& cd "gdb-${GDB_VERSION}" \
|
||||
|
||||
@@ -3,6 +3,8 @@ project(docs)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ClioVersion.cmake)
|
||||
|
||||
# cmake-format: off
|
||||
# Generate `docs` target for doxygen documentation
|
||||
# Note: use `cmake --build . --target docs` from your `build` directory to generate the documentation
|
||||
# cmake-format: on
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Docs.cmake)
|
||||
|
||||
@@ -97,14 +97,30 @@ Now you should be able to download the prebuilt dependencies (including `xrpl` p
|
||||
|
||||
#### Conan lockfile
|
||||
|
||||
To achieve reproducible dependencies, we use a [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html).
|
||||
To achieve reproducible dependencies, we use [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html).
|
||||
|
||||
The `conan.lock` file in the repository contains a "snapshot" of the current dependencies.
|
||||
It is implicitly used when running `conan` commands, you don't need to specify it.
|
||||
|
||||
You have to update this file every time you add a new dependency or change a revision or version of an existing dependency.
|
||||
|
||||
To update a lockfile, run from the repository root: `./.github/scripts/conan/regenerate_lockfile.sh`
|
||||
> [!NOTE]
|
||||
> Conan uses local cache by default when creating a lockfile.
|
||||
>
|
||||
> To ensure, that lockfile creation works the same way on all developer machines, you should clear the local cache before creating a new lockfile.
|
||||
|
||||
To create a new lockfile, run the following commands in the repository root:
|
||||
|
||||
```bash
|
||||
conan remove '*' --confirm
|
||||
rm conan.lock
|
||||
# This ensure that xrplf remote is the first to be consulted
|
||||
conan remote add --force --index 0 xrplf https://conan.ripplex.io
|
||||
conan lock create .
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If some dependencies are exclusive for some OS, you may need to run the last command for them adding `--profile:all <PROFILE>`.
|
||||
|
||||
## Building Clio
|
||||
|
||||
@@ -175,7 +191,7 @@ Open the `index.html` file in your browser to see the documentation pages.
|
||||
It is also possible to build Clio using [Docker](https://www.docker.com/) if you don't want to install all the dependencies on your machine.
|
||||
|
||||
```sh
|
||||
docker run -it ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
docker run -it ghcr.io/xrplf/clio-ci:b2be4b51d1d81548ca48e2f2b8f67356b880c96d
|
||||
git clone https://github.com/XRPLF/clio
|
||||
cd clio
|
||||
```
|
||||
|
||||
@@ -293,7 +293,7 @@ This document provides a list of all available Clio configuration properties in
|
||||
|
||||
- **Required**: True
|
||||
- **Type**: int
|
||||
- **Default value**: `1000`
|
||||
- **Default value**: `1`
|
||||
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
|
||||
- **Description**: The maximum size of the server's request queue. If set to `0`, this means there is no queue size limit.
|
||||
|
||||
@@ -391,7 +391,7 @@ This document provides a list of all available Clio configuration properties in
|
||||
- **Type**: double
|
||||
- **Default value**: `10`
|
||||
- **Constraints**: The value must be a positive double number.
|
||||
- **Description**: The number of seconds the server waits to shutdown gracefully. If Clio does not shutdown gracefully after the specified value, it will be killed instead.
|
||||
- **Description**: The number of milliseconds the server waits to shutdown gracefully. If Clio does not shutdown gracefully after the specified value, it will be killed instead.
|
||||
|
||||
### cache.num_diffs
|
||||
|
||||
@@ -433,14 +433,6 @@ This document provides a list of all available Clio configuration properties in
|
||||
- **Constraints**: The minimum value is `1`. The maximum value is `65535`.
|
||||
- **Description**: The number of ledger objects to fetch concurrently per marker.
|
||||
|
||||
### cache.limit_load_in_cluster
|
||||
|
||||
- **Required**: True
|
||||
- **Type**: boolean
|
||||
- **Default value**: `False`
|
||||
- **Constraints**: None
|
||||
- **Description**: If enabled only one clio node in a cluster (sharing the same database) will load cache at a time
|
||||
|
||||
### cache.load
|
||||
|
||||
- **Required**: True
|
||||
@@ -449,30 +441,6 @@ This document provides a list of all available Clio configuration properties in
|
||||
- **Constraints**: The value must be one of the following: `sync`, `async`, `none`.
|
||||
- **Description**: The strategy used for Cache loading.
|
||||
|
||||
### cache.file.path
|
||||
|
||||
- **Required**: False
|
||||
- **Type**: string
|
||||
- **Default value**: None
|
||||
- **Constraints**: None
|
||||
- **Description**: The path to a file where cache will be saved to on shutdown and loaded from on startup. If the file couldn't be read Clio will load cache as usual (from DB or from rippled).
|
||||
|
||||
### cache.file.max_sequence_age
|
||||
|
||||
- **Required**: True
|
||||
- **Type**: int
|
||||
- **Default value**: `5000`
|
||||
- **Constraints**: None
|
||||
- **Description**: Max allowed difference between the latest sequence in DB and in cache file. If the cache file is too old (contains too low latest sequence) Clio will reject using it.
|
||||
|
||||
### cache.file.async_save
|
||||
|
||||
- **Required**: True
|
||||
- **Type**: boolean
|
||||
- **Default value**: `False`
|
||||
- **Constraints**: None
|
||||
- **Description**: When false, Clio waits for cache saving to finish before shutting down. When true, cache saving runs in parallel with other shutdown operations.
|
||||
|
||||
### log.channels.[].channel
|
||||
|
||||
- **Required**: False
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"ip": "0.0.0.0",
|
||||
"port": 51233,
|
||||
// Max number of requests to queue up before rejecting further requests.
|
||||
// Defaults to 1000 (use 0 to make the queue unbound).
|
||||
// Defaults to 0, which disables the limit.
|
||||
"max_queue_size": 500,
|
||||
// If request contains header with authorization, Clio will check if it matches the prefix 'Password ' + this value's sha256 hash
|
||||
// If matches, the request will be considered as admin request
|
||||
@@ -137,11 +137,7 @@
|
||||
// "num_cursors_from_account": 3200, // Read the cursors from the account table until we have enough cursors to partition the ledger to load concurrently.
|
||||
"num_markers": 48, // The number of markers is the number of coroutines to load the cache concurrently.
|
||||
"page_fetch_size": 512, // The number of rows to load for each page.
|
||||
"load": "async", // "sync" to load cache synchronously or "async" to load cache asynchronously or "none"/"no" to turn off the cache.
|
||||
"file": {
|
||||
"path": "./cache.bin",
|
||||
"max_sequence_age": 5000
|
||||
}
|
||||
"load": "async" // "sync" to load cache synchronously or "async" to load cache asynchronously or "none"/"no" to turn off the cache.
|
||||
},
|
||||
"prometheus": {
|
||||
"enabled": true,
|
||||
|
||||
@@ -93,42 +93,3 @@ To completely disable Prometheus metrics add `"prometheus": { "enabled": false }
|
||||
It is important to know that Clio responds to Prometheus request only if they are admin requests. If you are using the admin password feature, the same password should be provided in the Authorization header of Prometheus requests.
|
||||
|
||||
You can find an example Docker Compose file, with Prometheus and Grafana configs, in [examples/infrastructure](../docs/examples/infrastructure/).
|
||||
|
||||
## Ledger cache file
|
||||
|
||||
Since version 2.7.0, Clio supports saving the ledger cache to a local file on shutdown and loading it on startup. This feature is disabled by default but can significantly improve restart times.
|
||||
|
||||
### Benefits
|
||||
|
||||
- **Faster startup**: Loading cache from a file takes less than a minute, compared to 40-90 minutes on Mainnet when loading from the database.
|
||||
- **Reduced database load**: Clio doesn't put extra load on the database when starting with a cache file.
|
||||
- **Improved availability**: Faster restart times mean less downtime during maintenance or updates.
|
||||
|
||||
> [!NOTE]
|
||||
> This feature only works when Clio is restarted. When starting Clio for the first time, the cache must be loaded from `rippled` or the database as usual.
|
||||
|
||||
### Configuration
|
||||
|
||||
To enable the ledger cache file feature, specify the [`cache.file.path`](./config-description.md#cachefilepath) option in your `config.json`:
|
||||
|
||||
```json
|
||||
"cache": {
|
||||
"file": {
|
||||
"path": "/path/to/cache/file"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can optionally configure additional settings such as [`cache.file.max_sequence_age`](./config-description.md#cachefilemax_sequence_age) and [`cache.file.async_save`](./config-description.md#cachefileasync_save) to fine-tune the behavior. For a complete list of available options and their default values, see the [Configuration Description](./config-description.md#cachefilepath) documentation.
|
||||
|
||||
### How it works
|
||||
|
||||
1. **On shutdown**: Clio saves the current ledger cache to the specified file path. The file includes a hash for integrity verification.
|
||||
2. **On startup**: Clio checks if a cache file exists at the configured path. If the file exists, Clio will:
|
||||
- Verify the file's integrity to ensure it is complete and not corrupted.
|
||||
- Compare the latest ledger sequence in the cache file with the latest sequence in the database.
|
||||
- Use the cache file only if the difference is less than [`cache.file.max_sequence_age`](./config-description.md#cachefilemax_sequence_age).
|
||||
- If validation fails or the cache is too old, Clio will fall back to loading from the database.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The cache file path should point to a location with sufficient disk space. On typical deployments, the cache file size can be several gigabytes.
|
||||
|
||||
@@ -45,7 +45,7 @@ if [[ "1.14.0" > "$version" ]]; then
|
||||
|
||||
ERROR
|
||||
-----------------------------------------------------------------------------
|
||||
A minimum of version 1.14 of $(which doxygen) is required.
|
||||
A minimum of version 1.14 of `which doxygen` is required.
|
||||
Your version is $version. Please upgrade it.
|
||||
|
||||
Your changes may fail CI checks.
|
||||
@@ -55,26 +55,26 @@ EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p ${DOCDIR} >/dev/null 2>&1
|
||||
pushd ${DOCDIR} >/dev/null 2>&1
|
||||
mkdir -p ${DOCDIR} > /dev/null 2>&1
|
||||
pushd ${DOCDIR} > /dev/null 2>&1
|
||||
|
||||
cat ${ROOT}/docs/Doxyfile |
|
||||
sed \
|
||||
-e "s/\${LINT}/YES/" \
|
||||
-e "s/\${WARN_AS_ERROR}/NO/" \
|
||||
-e "s!\${SOURCE}!${ROOT}!" \
|
||||
-e "s/\${USE_DOT}/NO/" \
|
||||
-e "s/\${EXCLUDES}/impl/" |
|
||||
${DOXYGEN} - 2>${TMPFILE} 1>/dev/null
|
||||
cat ${ROOT}/docs/Doxyfile | \
|
||||
sed \
|
||||
-e "s/\${LINT}/YES/" \
|
||||
-e "s/\${WARN_AS_ERROR}/NO/" \
|
||||
-e "s!\${SOURCE}!${ROOT}!" \
|
||||
-e "s/\${USE_DOT}/NO/" \
|
||||
-e "s/\${EXCLUDES}/impl/" \
|
||||
| ${DOXYGEN} - 2> ${TMPFILE} 1> /dev/null
|
||||
|
||||
# We don't want to check for default values and typedefs as well as for member variables
|
||||
OUT=$(cat ${TMPFILE} |
|
||||
grep -v "=default" |
|
||||
grep -v "\(variable\)" |
|
||||
grep -v "\(typedef\)")
|
||||
OUT=$(cat ${TMPFILE} \
|
||||
| grep -v "=default" \
|
||||
| grep -v "\(variable\)" \
|
||||
| grep -v "\(typedef\)")
|
||||
|
||||
rm -rf ${TMPFILE} >/dev/null 2>&1
|
||||
popd >/dev/null 2>&1
|
||||
rm -rf ${TMPFILE} > /dev/null 2>&1
|
||||
popd > /dev/null 2>&1
|
||||
|
||||
if [[ ! -z "$OUT" ]]; then
|
||||
cat <<EOF
|
||||
|
||||
@@ -23,10 +23,10 @@ fix_includes() {
|
||||
file_path_fixed="${file_path}.tmp.fixed"
|
||||
|
||||
# Make all includes to be <...> style
|
||||
sed -E 's|#include "(.*)"|#include <\1>|g' "$file_path" >"$file_path_all_global"
|
||||
sed -E 's|#include "(.*)"|#include <\1>|g' "$file_path" > "$file_path_all_global"
|
||||
|
||||
# Make local includes to be "..." style
|
||||
sed -E "s|#include <(($main_src_dirs)/.*)>|#include \"\1\"|g" "$file_path_all_global" >"$file_path_fixed"
|
||||
sed -E "s|#include <(($main_src_dirs)/.*)>|#include \"\1\"|g" "$file_path_all_global" > "$file_path_fixed"
|
||||
rm "$file_path_all_global"
|
||||
|
||||
# Check if the temporary file is different from the original file
|
||||
|
||||
@@ -4,6 +4,7 @@ import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
PATTERN = r'R"JSON\((.*?)\)JSON"'
|
||||
|
||||
|
||||
@@ -39,22 +40,16 @@ def fix_colon_spacing(cpp_content: str) -> str:
|
||||
raw_json = match.group(1)
|
||||
raw_json = re.sub(r'":\n\s*(\[|\{)', r'": \1', raw_json)
|
||||
return f'R"JSON({raw_json})JSON"'
|
||||
|
||||
return re.sub(PATTERN, replace_json, cpp_content, flags=re.DOTALL)
|
||||
|
||||
|
||||
def fix_indentation(cpp_content: str) -> str:
|
||||
if "JSON(" not in cpp_content:
|
||||
return cpp_content
|
||||
|
||||
lines = cpp_content.splitlines()
|
||||
|
||||
ends_with_newline = cpp_content.endswith("\n")
|
||||
|
||||
def find_indentation(line: str) -> int:
|
||||
return len(line) - len(line.lstrip())
|
||||
|
||||
for line_num, (line, next_line) in enumerate(zip(lines[:-1], lines[1:])):
|
||||
for (line_num, (line, next_line)) in enumerate(zip(lines[:-1], lines[1:])):
|
||||
if "JSON(" in line and ")JSON" not in line:
|
||||
indent = find_indentation(line)
|
||||
next_indent = find_indentation(next_line)
|
||||
@@ -69,17 +64,9 @@ def fix_indentation(cpp_content: str) -> str:
|
||||
if ")JSON" in lines[i]:
|
||||
lines[i] = " " * indent + lines[i].lstrip()
|
||||
break
|
||||
lines[i] = (
|
||||
lines[i][by_how_much:]
|
||||
if by_how_much > 0
|
||||
else " " * (-by_how_much) + lines[i]
|
||||
)
|
||||
lines[i] = lines[i][by_how_much:] if by_how_much > 0 else " " * (-by_how_much) + lines[i]
|
||||
|
||||
result = "\n".join(lines)
|
||||
|
||||
if ends_with_newline:
|
||||
result += "\n"
|
||||
return result
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def process_file(file_path: Path, dry_run: bool) -> bool:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
set -e -o pipefail
|
||||
|
||||
if ! command -v gofmt &>/dev/null; then
|
||||
if ! command -v gofmt &> /dev/null ; then
|
||||
echo "gofmt not installed or available in the PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
|
||||
# git for-each-ref refs/tags # see which tags are annotated and which are lightweight. Annotated tags are "tag" objects.
|
||||
# # Set these so your commits and tags are always signed
|
||||
@@ -6,7 +7,7 @@
|
||||
# git config tag.gpgsign true
|
||||
|
||||
verify_commit_signed() {
|
||||
if git verify-commit HEAD &>/dev/null; then
|
||||
if git verify-commit HEAD &> /dev/null; then
|
||||
:
|
||||
# echo "HEAD commit seems signed..."
|
||||
else
|
||||
@@ -16,7 +17,7 @@ verify_commit_signed() {
|
||||
}
|
||||
|
||||
verify_tag() {
|
||||
if git describe --exact-match --tags HEAD &>/dev/null; then
|
||||
if git describe --exact-match --tags HEAD &> /dev/null; then
|
||||
: # You might be ok to push
|
||||
# echo "Tag is annotated."
|
||||
return 0
|
||||
@@ -27,7 +28,7 @@ verify_tag() {
|
||||
}
|
||||
|
||||
verify_tag_signed() {
|
||||
if git verify-tag "$version" &>/dev/null; then
|
||||
if git verify-tag "$version" &> /dev/null ; then
|
||||
: # ok, I guess we'll let you push
|
||||
# echo "Tag appears signed"
|
||||
return 0
|
||||
@@ -39,11 +40,11 @@ verify_tag_signed() {
|
||||
}
|
||||
|
||||
# Check some things if we're pushing a branch called "release/"
|
||||
if echo "$PRE_COMMIT_REMOTE_BRANCH" | grep ^refs\/heads\/release\/ &>/dev/null; then
|
||||
if echo "$PRE_COMMIT_REMOTE_BRANCH" | grep ^refs\/heads\/release\/ &> /dev/null ; then
|
||||
version=$(git tag --points-at HEAD)
|
||||
echo "Looks like you're trying to push a $version release..."
|
||||
echo "Making sure you've signed and tagged it."
|
||||
if verify_commit_signed && verify_tag && verify_tag_signed; then
|
||||
if verify_commit_signed && verify_tag && verify_tag_signed ; then
|
||||
: # Ok, I guess you can push
|
||||
else
|
||||
exit 1
|
||||
|
||||
@@ -2,6 +2,7 @@ add_subdirectory(util)
|
||||
add_subdirectory(data)
|
||||
add_subdirectory(cluster)
|
||||
add_subdirectory(etl)
|
||||
add_subdirectory(etlng)
|
||||
add_subdirectory(feed)
|
||||
add_subdirectory(rpc)
|
||||
add_subdirectory(web)
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
add_library(clio_app)
|
||||
target_sources(
|
||||
clio_app
|
||||
PRIVATE CliArgs.cpp ClioApplication.cpp Stopper.cpp WebHandlers.cpp
|
||||
)
|
||||
target_sources(clio_app PRIVATE CliArgs.cpp ClioApplication.cpp Stopper.cpp WebHandlers.cpp)
|
||||
|
||||
target_link_libraries(
|
||||
clio_app
|
||||
PUBLIC clio_cluster clio_etl clio_feed clio_migration clio_rpc clio_web
|
||||
PRIVATE Boost::program_options
|
||||
clio_app
|
||||
PUBLIC clio_cluster
|
||||
clio_etl
|
||||
clio_etlng
|
||||
clio_feed
|
||||
clio_web
|
||||
clio_rpc
|
||||
clio_migration
|
||||
PRIVATE Boost::program_options
|
||||
)
|
||||
|
||||
@@ -58,16 +58,12 @@ CliArgs::parse(int argc, char const* argv[])
|
||||
positional.add("conf", 1);
|
||||
|
||||
auto const printHelp = [&description]() {
|
||||
std::cout << "Clio server " << util::build::getClioFullVersionString() << "\n\n"
|
||||
<< description;
|
||||
std::cout << "Clio server " << util::build::getClioFullVersionString() << "\n\n" << description;
|
||||
};
|
||||
|
||||
po::variables_map parsed;
|
||||
try {
|
||||
po::store(
|
||||
po::command_line_parser(argc, argv).options(description).positional(positional).run(),
|
||||
parsed
|
||||
);
|
||||
po::store(po::command_line_parser(argc, argv).options(description).positional(positional).run(), parsed);
|
||||
po::notify(parsed);
|
||||
} catch (po::error const& e) {
|
||||
std::cerr << "Error: " << e.what() << std::endl << std::endl;
|
||||
@@ -81,18 +77,14 @@ CliArgs::parse(int argc, char const* argv[])
|
||||
}
|
||||
|
||||
if (parsed.contains("version")) {
|
||||
std::cout << util::build::getClioFullVersionString() << '\n'
|
||||
<< "Git commit hash: " << util::build::getGitCommitHash() << '\n'
|
||||
<< "Git build branch: " << util::build::getGitBuildBranch() << '\n'
|
||||
<< "Build date: " << util::build::getBuildDate() << '\n';
|
||||
std::cout << util::build::getClioFullVersionString() << '\n';
|
||||
return Action{Action::Exit{EXIT_SUCCESS}};
|
||||
}
|
||||
|
||||
if (parsed.contains("config-description")) {
|
||||
std::filesystem::path const filePath = parsed["config-description"].as<std::string>();
|
||||
|
||||
auto const res =
|
||||
util::config::ClioConfigDescription::generateConfigDescriptionToFile(filePath);
|
||||
auto const res = util::config::ClioConfigDescription::generateConfigDescriptionToFile(filePath);
|
||||
if (res.has_value())
|
||||
return Action{Action::Exit{EXIT_SUCCESS}};
|
||||
|
||||
@@ -104,22 +96,15 @@ CliArgs::parse(int argc, char const* argv[])
|
||||
|
||||
if (parsed.contains("migrate")) {
|
||||
auto const opt = parsed["migrate"].as<std::string>();
|
||||
if (opt == "status") {
|
||||
return Action{Action::Migrate{
|
||||
.configPath = std::move(configPath), .subCmd = MigrateSubCmd::status()
|
||||
}};
|
||||
}
|
||||
return Action{Action::Migrate{
|
||||
.configPath = std::move(configPath), .subCmd = MigrateSubCmd::migration(opt)
|
||||
}};
|
||||
if (opt == "status")
|
||||
return Action{Action::Migrate{.configPath = std::move(configPath), .subCmd = MigrateSubCmd::status()}};
|
||||
return Action{Action::Migrate{.configPath = std::move(configPath), .subCmd = MigrateSubCmd::migration(opt)}};
|
||||
}
|
||||
|
||||
if (parsed.contains("verify"))
|
||||
return Action{Action::VerifyConfig{.configPath = std::move(configPath)}};
|
||||
|
||||
return Action{Action::Run{
|
||||
.configPath = std::move(configPath), .useNgWebServer = parsed.contains("ng-web-server")
|
||||
}};
|
||||
return Action{Action::Run{.configPath = std::move(configPath), .useNgWebServer = parsed.contains("ng-web-server")}};
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
@@ -79,8 +79,7 @@ public:
|
||||
/**
|
||||
* @brief Apply a function to the action.
|
||||
*
|
||||
* @tparam Processors Action processors types. Must be callable with the action type and
|
||||
* return int.
|
||||
* @tparam Processors Action processors types. Must be callable with the action type and return int.
|
||||
* @param processors Action processors.
|
||||
* @return Exit code.
|
||||
*/
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
#include "data/AmendmentCenter.hpp"
|
||||
#include "data/BackendFactory.hpp"
|
||||
#include "data/LedgerCache.hpp"
|
||||
#include "data/LedgerCacheSaver.hpp"
|
||||
#include "etl/ETLService.hpp"
|
||||
#include "etl/LoadBalancer.hpp"
|
||||
#include "etl/NetworkValidatedLedgers.hpp"
|
||||
#include "etl/SystemState.hpp"
|
||||
#include "etlng/LoadBalancer.hpp"
|
||||
#include "etlng/LoadBalancerInterface.hpp"
|
||||
#include "feed/SubscriptionManager.hpp"
|
||||
#include "migration/MigrationInspectorFactory.hpp"
|
||||
#include "rpc/Counters.hpp"
|
||||
@@ -57,7 +57,6 @@
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -92,7 +91,6 @@ ClioApplication::ClioApplication(util::config::ClioConfigDefinition const& confi
|
||||
{
|
||||
LOG(util::LogService::info()) << "Clio version: " << util::build::getClioFullVersionString();
|
||||
signalsHandler_.subscribeToStop([this]() { appStopper_.stop(); });
|
||||
appStopper_.setOnComplete([this]() { signalsHandler_.notifyGracefulShutdownComplete(); });
|
||||
}
|
||||
|
||||
int
|
||||
@@ -101,32 +99,26 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
auto const threads = config_.get<uint16_t>("io_threads");
|
||||
LOG(util::LogService::info()) << "Number of io threads = " << threads;
|
||||
|
||||
// Similarly we need a context to run ETL on
|
||||
// In the future we can remove the raw ioc and use ctx instead
|
||||
// This context should be above ioc because its reference is getting into tasks inside ioc
|
||||
util::async::CoroExecutionContext ctx{threads};
|
||||
|
||||
// IO context to handle all incoming requests, as well as other things.
|
||||
// This is not the only io context in the application.
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// Similarly we need a context to run ETLng on
|
||||
// In the future we can remove the raw ioc and use ctx instead
|
||||
util::async::CoroExecutionContext ctx{threads};
|
||||
|
||||
// Rate limiter, to prevent abuse
|
||||
auto whitelistHandler = web::dosguard::WhitelistHandler{config_};
|
||||
auto const dosguardWeights = web::dosguard::Weights::make(config_);
|
||||
auto dosGuard = web::dosguard::DOSGuard{config_, whitelistHandler, dosguardWeights};
|
||||
auto sweepHandler = web::dosguard::IntervalSweepHandler{config_, ioc, dosGuard};
|
||||
|
||||
auto cache = data::LedgerCache{};
|
||||
auto cacheSaver = data::LedgerCacheSaver{config_, cache};
|
||||
|
||||
// Interface to the database
|
||||
auto backend = data::makeBackend(config_, cache);
|
||||
|
||||
auto systemState = etl::SystemState::makeSystemState(config_);
|
||||
|
||||
auto [clusterCommunicationService, cacheLoadingState] =
|
||||
cluster::ClusterCommunicationService::make(config_, backend, systemState);
|
||||
clusterCommunicationService->run();
|
||||
cluster::ClusterCommunicationService clusterCommunicationService{backend};
|
||||
clusterCommunicationService.run();
|
||||
|
||||
auto const amendmentCenter = std::make_shared<data::AmendmentCenter const>(backend);
|
||||
|
||||
@@ -134,15 +126,14 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
auto const migrationInspector = migration::makeMigrationInspector(config_, backend);
|
||||
// Check if any migration is blocking Clio server starting.
|
||||
if (migrationInspector->isBlockingClio() and backend->hardFetchLedgerRangeNoThrow()) {
|
||||
LOG(util::LogService::error()) << "Existing Migration is blocking Clio, Please "
|
||||
"complete the database migration first.";
|
||||
LOG(util::LogService::error())
|
||||
<< "Existing Migration is blocking Clio, Please complete the database migration first.";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// Manages clients subscribed to streams
|
||||
auto subscriptions =
|
||||
feed::SubscriptionManager::makeSubscriptionManager(config_, backend, amendmentCenter);
|
||||
auto subscriptions = feed::SubscriptionManager::makeSubscriptionManager(config_, backend, amendmentCenter);
|
||||
|
||||
// Tracks which ledgers have been validated by the network
|
||||
auto ledgers = etl::NetworkValidatedLedgers::makeValidatedLedgers();
|
||||
@@ -151,22 +142,20 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
// ETL uses the balancer to extract data.
|
||||
// The server uses the balancer to forward RPCs to a rippled node.
|
||||
// The balancer itself publishes to streams (transactions_proposed and accounts_proposed)
|
||||
auto balancer = etl::LoadBalancer::makeLoadBalancer(
|
||||
config_, ioc, backend, subscriptions, std::make_unique<util::MTRandomGenerator>(), ledgers
|
||||
);
|
||||
auto balancer = [&] -> std::shared_ptr<etlng::LoadBalancerInterface> {
|
||||
if (config_.get<bool>("__ng_etl")) {
|
||||
return etlng::LoadBalancer::makeLoadBalancer(
|
||||
config_, ioc, backend, subscriptions, std::make_unique<util::MTRandomGenerator>(), ledgers
|
||||
);
|
||||
}
|
||||
|
||||
// ETL is responsible for writing and publishing to streams. In read-only mode, ETL only
|
||||
// publishes
|
||||
auto etl = etl::ETLService::makeETLService(
|
||||
config_,
|
||||
std::move(systemState),
|
||||
std::move(cacheLoadingState),
|
||||
ctx,
|
||||
backend,
|
||||
subscriptions,
|
||||
balancer,
|
||||
ledgers
|
||||
);
|
||||
return etl::LoadBalancer::makeLoadBalancer(
|
||||
config_, ioc, backend, subscriptions, std::make_unique<util::MTRandomGenerator>(), ledgers
|
||||
);
|
||||
}();
|
||||
|
||||
// ETL is responsible for writing and publishing to streams. In read-only mode, ETL only publishes
|
||||
auto etl = etl::ETLService::makeETLService(config_, ioc, ctx, backend, subscriptions, balancer, ledgers);
|
||||
|
||||
auto workQueue = rpc::WorkQueue::makeWorkQueue(config_);
|
||||
auto counters = rpc::Counters::makeCounters(workQueue);
|
||||
@@ -176,19 +165,15 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
);
|
||||
|
||||
using RPCEngineType = rpc::RPCEngine<rpc::Counters>;
|
||||
auto const rpcEngine = RPCEngineType::makeRPCEngine(
|
||||
config_, backend, balancer, dosGuard, workQueue, counters, handlerProvider
|
||||
);
|
||||
auto const rpcEngine =
|
||||
RPCEngineType::makeRPCEngine(config_, backend, balancer, dosGuard, workQueue, counters, handlerProvider);
|
||||
|
||||
if (useNgWebServer or config_.get<bool>("server.__ng_web_server")) {
|
||||
web::ng::RPCServerHandler<RPCEngineType> handler{
|
||||
config_, backend, rpcEngine, etl, dosGuard
|
||||
};
|
||||
web::ng::RPCServerHandler<RPCEngineType> handler{config_, backend, rpcEngine, etl, dosGuard};
|
||||
|
||||
auto expectedAdminVerifier = web::makeAdminVerificationStrategy(config_);
|
||||
if (not expectedAdminVerifier.has_value()) {
|
||||
LOG(util::LogService::error())
|
||||
<< "Error creating admin verifier: " << expectedAdminVerifier.error();
|
||||
LOG(util::LogService::error()) << "Error creating admin verifier: " << expectedAdminVerifier.error();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const adminVerifier = std::move(expectedAdminVerifier).value();
|
||||
@@ -202,7 +187,7 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
httpServer->onGet("/metrics", MetricsHandler{adminVerifier, workQueue});
|
||||
httpServer->onGet("/metrics", MetricsHandler{adminVerifier});
|
||||
httpServer->onGet("/health", HealthCheckHandler{});
|
||||
httpServer->onGet("/cache_state", CacheStateHandler{cache});
|
||||
auto requestHandler = RequestHandler{adminVerifier, handler};
|
||||
@@ -216,16 +201,7 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
}
|
||||
|
||||
appStopper_.setOnStop(
|
||||
Stopper::makeOnStopCallback(
|
||||
httpServer.value(),
|
||||
*balancer,
|
||||
*etl,
|
||||
*subscriptions,
|
||||
*backend,
|
||||
cacheSaver,
|
||||
*clusterCommunicationService,
|
||||
ioc
|
||||
)
|
||||
Stopper::makeOnStopCallback(httpServer.value(), *balancer, *etl, *subscriptions, *backend, ioc)
|
||||
);
|
||||
|
||||
// Blocks until stopped.
|
||||
@@ -237,23 +213,9 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
}
|
||||
|
||||
// Init the web server
|
||||
auto handler = std::make_shared<web::RPCServerHandler<RPCEngineType>>(
|
||||
config_, backend, rpcEngine, etl, dosGuard
|
||||
);
|
||||
auto handler = std::make_shared<web::RPCServerHandler<RPCEngineType>>(config_, backend, rpcEngine, etl, dosGuard);
|
||||
|
||||
auto const httpServer = web::makeHttpServer(config_, ioc, dosGuard, handler, cache);
|
||||
appStopper_.setOnStop(
|
||||
Stopper::makeOnStopCallback(
|
||||
*httpServer,
|
||||
*balancer,
|
||||
*etl,
|
||||
*subscriptions,
|
||||
*backend,
|
||||
cacheSaver,
|
||||
*clusterCommunicationService,
|
||||
ioc
|
||||
)
|
||||
);
|
||||
|
||||
// Blocks until stopped.
|
||||
// When stopped, shared_ptrs fall out of scope
|
||||
|
||||
@@ -38,18 +38,7 @@ Stopper::~Stopper()
|
||||
void
|
||||
Stopper::setOnStop(std::function<void(boost::asio::yield_context)> cb)
|
||||
{
|
||||
util::spawn(ctx_, [this, cb = std::move(cb)](auto yield) {
|
||||
cb(yield);
|
||||
|
||||
if (onCompleteCallback_)
|
||||
onCompleteCallback_();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Stopper::setOnComplete(std::function<void()> cb)
|
||||
{
|
||||
onCompleteCallback_ = std::move(cb);
|
||||
util::spawn(ctx_, std::move(cb));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -19,15 +19,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cluster/Concepts.hpp"
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "data/LedgerCacheSaver.hpp"
|
||||
#include "etl/ETLServiceInterface.hpp"
|
||||
#include "etl/LoadBalancerInterface.hpp"
|
||||
#include "etlng/ETLServiceInterface.hpp"
|
||||
#include "etlng/LoadBalancerInterface.hpp"
|
||||
#include "feed/SubscriptionManagerInterface.hpp"
|
||||
#include "util/CoroutineGroup.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "web/interface/Concepts.hpp"
|
||||
#include "web/ng/Server.hpp"
|
||||
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
@@ -39,13 +37,11 @@
|
||||
namespace app {
|
||||
|
||||
/**
|
||||
* @brief Application stopper class. On stop it will create a new thread to run all the shutdown
|
||||
* tasks.
|
||||
* @brief Application stopper class. On stop it will create a new thread to run all the shutdown tasks.
|
||||
*/
|
||||
class Stopper {
|
||||
boost::asio::io_context ctx_;
|
||||
std::thread worker_;
|
||||
std::function<void()> onCompleteCallback_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -61,14 +57,6 @@ public:
|
||||
void
|
||||
setOnStop(std::function<void(boost::asio::yield_context)> cb);
|
||||
|
||||
/**
|
||||
* @brief Set the callback to be called when graceful shutdown completes.
|
||||
*
|
||||
* @param cb The callback to be called when shutdown completes.
|
||||
*/
|
||||
void
|
||||
setOnComplete(std::function<void()> cb);
|
||||
|
||||
/**
|
||||
* @brief Stop the application and run the shutdown tasks.
|
||||
*/
|
||||
@@ -83,30 +71,21 @@ public:
|
||||
* @param etl The ETL service to stop.
|
||||
* @param subscriptions The subscription manager to stop.
|
||||
* @param backend The backend to stop.
|
||||
* @param cacheSaver The ledger cache saver
|
||||
* @param clusterCommunicationService The cluster communication service to stop.
|
||||
* @param ioc The io_context to stop.
|
||||
* @return The callback to be called on application stop.
|
||||
*/
|
||||
template <
|
||||
web::SomeServer ServerType,
|
||||
data::SomeLedgerCacheSaver LedgerCacheSaverType,
|
||||
cluster::SomeClusterCommunicationService ClusterCommunicationServiceType>
|
||||
template <web::ng::SomeServer ServerType>
|
||||
static std::function<void(boost::asio::yield_context)>
|
||||
makeOnStopCallback(
|
||||
ServerType& server,
|
||||
etl::LoadBalancerInterface& balancer,
|
||||
etl::ETLServiceInterface& etl,
|
||||
etlng::LoadBalancerInterface& balancer,
|
||||
etlng::ETLServiceInterface& etl,
|
||||
feed::SubscriptionManagerInterface& subscriptions,
|
||||
data::BackendInterface& backend,
|
||||
LedgerCacheSaverType& cacheSaver,
|
||||
ClusterCommunicationServiceType& clusterCommunicationService,
|
||||
boost::asio::io_context& ioc
|
||||
)
|
||||
{
|
||||
return [&](boost::asio::yield_context yield) {
|
||||
cacheSaver.save();
|
||||
|
||||
util::CoroutineGroup coroutineGroup{yield};
|
||||
coroutineGroup.spawn(yield, [&server](auto innerYield) {
|
||||
server.stop(innerYield);
|
||||
@@ -118,8 +97,6 @@ public:
|
||||
});
|
||||
coroutineGroup.asyncWait(yield);
|
||||
|
||||
clusterCommunicationService.stop();
|
||||
|
||||
etl.stop();
|
||||
LOG(util::LogService::info()) << "ETL stopped";
|
||||
|
||||
@@ -129,8 +106,6 @@ public:
|
||||
backend.waitForWritesToFinish();
|
||||
LOG(util::LogService::info()) << "Backend writes finished";
|
||||
|
||||
cacheSaver.waitToFinish();
|
||||
|
||||
ioc.stop();
|
||||
LOG(util::LogService::info()) << "io_context stopped";
|
||||
|
||||
|
||||
@@ -41,8 +41,7 @@ parseConfig(std::string_view configPath)
|
||||
|
||||
auto const json = ConfigFileJson::makeConfigFileJson(configPath);
|
||||
if (!json.has_value()) {
|
||||
std::cerr << "Error parsing json from config: " << configPath << "\n"
|
||||
<< json.error().error << std::endl;
|
||||
std::cerr << "Error parsing json from config: " << configPath << "\n" << json.error().error << std::endl;
|
||||
return false;
|
||||
}
|
||||
auto const errors = getClioConfig().parse(json.value());
|
||||
|
||||
@@ -19,10 +19,7 @@
|
||||
|
||||
#include "app/WebHandlers.hpp"
|
||||
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/WorkQueue.hpp"
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/CoroutineGroup.hpp"
|
||||
#include "util/prometheus/Http.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
#include "web/SubscriptionContextInterface.hpp"
|
||||
@@ -34,7 +31,6 @@
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/beast/http/status.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
@@ -51,9 +47,9 @@ OnConnectCheck::operator()(web::ng::Connection const& connection)
|
||||
{
|
||||
dosguard_.get().increment(connection.ip());
|
||||
if (not dosguard_.get().isOk(connection.ip())) {
|
||||
return std::unexpected{web::ng::Response{
|
||||
boost::beast::http::status::too_many_requests, "Too many requests", connection
|
||||
}};
|
||||
return std::unexpected{
|
||||
web::ng::Response{boost::beast::http::status::too_many_requests, "Too many requests", connection}
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -80,11 +76,8 @@ DisconnectHook::operator()(web::ng::Connection const& connection)
|
||||
dosguard_.get().decrement(connection.ip());
|
||||
}
|
||||
|
||||
MetricsHandler::MetricsHandler(
|
||||
std::shared_ptr<web::AdminVerificationStrategy> adminVerifier,
|
||||
rpc::WorkQueue& workQueue
|
||||
)
|
||||
: adminVerifier_{std::move(adminVerifier)}, workQueue_{std::ref(workQueue)}
|
||||
MetricsHandler::MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier)
|
||||
: adminVerifier_{std::move(adminVerifier)}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -93,47 +86,19 @@ MetricsHandler::operator()(
|
||||
web::ng::Request const& request,
|
||||
web::ng::ConnectionMetadata& connectionMetadata,
|
||||
web::SubscriptionContextPtr,
|
||||
boost::asio::yield_context yield
|
||||
boost::asio::yield_context
|
||||
)
|
||||
{
|
||||
std::optional<web::ng::Response> response;
|
||||
util::CoroutineGroup coroutineGroup{yield, 1};
|
||||
auto const onTaskComplete = coroutineGroup.registerForeign(yield);
|
||||
ASSERT(onTaskComplete.has_value(), "Coroutine group can't be full");
|
||||
auto const maybeHttpRequest = request.asHttpRequest();
|
||||
ASSERT(maybeHttpRequest.has_value(), "Got not a http request in Get");
|
||||
auto const& httpRequest = maybeHttpRequest->get();
|
||||
|
||||
bool const postSuccessful = workQueue_.get().postCoro(
|
||||
[this, &request, &response, &onTaskComplete = onTaskComplete.value(), &connectionMetadata](
|
||||
boost::asio::yield_context
|
||||
) mutable {
|
||||
auto const maybeHttpRequest = request.asHttpRequest();
|
||||
ASSERT(maybeHttpRequest.has_value(), "Got not a http request in Get");
|
||||
auto const& httpRequest = maybeHttpRequest->get();
|
||||
|
||||
auto maybeResponse = util::prometheus::handlePrometheusRequest(
|
||||
httpRequest, adminVerifier_->isAdmin(httpRequest, connectionMetadata.ip())
|
||||
);
|
||||
ASSERT(maybeResponse.has_value(), "Got unexpected request for Prometheus");
|
||||
response = web::ng::Response{std::move(maybeResponse).value(), request};
|
||||
// notify the coroutine group that the foreign task is done
|
||||
onTaskComplete();
|
||||
},
|
||||
/* isWhiteListed= */ true,
|
||||
rpc::WorkQueue::Priority::High
|
||||
// FIXME(#1702): Using veb server thread to handle prometheus request. Better to post on work queue.
|
||||
auto maybeResponse = util::prometheus::handlePrometheusRequest(
|
||||
httpRequest, adminVerifier_->isAdmin(httpRequest, connectionMetadata.ip())
|
||||
);
|
||||
|
||||
if (!postSuccessful) {
|
||||
return web::ng::Response{
|
||||
boost::beast::http::status::too_many_requests,
|
||||
rpc::makeError(rpc::RippledError::rpcTOO_BUSY),
|
||||
request
|
||||
};
|
||||
}
|
||||
|
||||
// Put the coroutine to sleep until the foreign task is done
|
||||
coroutineGroup.asyncWait(yield);
|
||||
ASSERT(response.has_value(), "Woke up coroutine without setting response");
|
||||
|
||||
return std::move(response).value();
|
||||
ASSERT(maybeResponse.has_value(), "Got unexpected request for Prometheus");
|
||||
return web::ng::Response{std::move(maybeResponse).value(), request};
|
||||
}
|
||||
|
||||
web::ng::Response
|
||||
@@ -182,9 +147,7 @@ CacheStateHandler::operator()(
|
||||
if (cache_.get().isFull())
|
||||
return web::ng::Response{boost::beast::http::status::ok, kCACHE_CHECK_LOADED_HTML, request};
|
||||
|
||||
return web::ng::Response{
|
||||
boost::beast::http::status::service_unavailable, kCACHE_CHECK_NOT_LOADED_HTML, request
|
||||
};
|
||||
return web::ng::Response{boost::beast::http::status::service_unavailable, kCACHE_CHECK_NOT_LOADED_HTML, request};
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/WorkQueue.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
#include "web/SubscriptionContextInterface.hpp"
|
||||
@@ -68,8 +67,8 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A function object that is called when the IP of a connection changes (usually if proxy
|
||||
* detected). This is used to update the DOS guard.
|
||||
* @brief A function object that is called when the IP of a connection changes (usually if proxy detected).
|
||||
* This is used to update the DOS guard.
|
||||
*/
|
||||
class IpChangeHook {
|
||||
std::reference_wrapper<web::dosguard::DOSGuardInterface> dosguard_;
|
||||
@@ -120,27 +119,20 @@ public:
|
||||
*/
|
||||
class MetricsHandler {
|
||||
std::shared_ptr<web::AdminVerificationStrategy> adminVerifier_;
|
||||
std::reference_wrapper<rpc::WorkQueue> workQueue_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new MetricsHandler object
|
||||
*
|
||||
* @param adminVerifier The AdminVerificationStrategy to use for verifying the connection for
|
||||
* admin access.
|
||||
* @param workQueue The WorkQueue to use for handling the request.
|
||||
* @param adminVerifier The AdminVerificationStrategy to use for verifying the connection for admin access.
|
||||
*/
|
||||
MetricsHandler(
|
||||
std::shared_ptr<web::AdminVerificationStrategy> adminVerifier,
|
||||
rpc::WorkQueue& workQueue
|
||||
);
|
||||
MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier);
|
||||
|
||||
/**
|
||||
* @brief The call of the function object.
|
||||
*
|
||||
* @param request The request to handle.
|
||||
* @param connectionMetadata The connection metadata.
|
||||
* @param yield The yield context.
|
||||
* @return The response to the request.
|
||||
*/
|
||||
web::ng::Response
|
||||
@@ -148,7 +140,7 @@ public:
|
||||
web::ng::Request const& request,
|
||||
web::ng::ConnectionMetadata& connectionMetadata,
|
||||
web::SubscriptionContextPtr,
|
||||
boost::asio::yield_context yield
|
||||
boost::asio::yield_context
|
||||
);
|
||||
};
|
||||
|
||||
@@ -218,14 +210,10 @@ public:
|
||||
/**
|
||||
* @brief Construct a new RequestHandler object
|
||||
*
|
||||
* @param adminVerifier The AdminVerificationStrategy to use for verifying the connection for
|
||||
* admin access.
|
||||
* @param adminVerifier The AdminVerificationStrategy to use for verifying the connection for admin access.
|
||||
* @param rpcHandler The RPC handler to use for handling the request.
|
||||
*/
|
||||
RequestHandler(
|
||||
std::shared_ptr<web::AdminVerificationStrategy> adminVerifier,
|
||||
RpcHandlerType& rpcHandler
|
||||
)
|
||||
RequestHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier, RpcHandlerType& rpcHandler)
|
||||
: adminVerifier_(std::move(adminVerifier)), rpcHandler_(rpcHandler)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2025, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "cluster/Backend.hpp"
|
||||
|
||||
#include "cluster/ClioNode.hpp"
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "data/LedgerCacheLoadingState.hpp"
|
||||
#include "etl/WriterState.hpp"
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/serialize.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_from.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <boost/uuid/random_generator.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace cluster {
|
||||
|
||||
Backend::Backend(
|
||||
boost::asio::thread_pool& ctx,
|
||||
std::shared_ptr<data::BackendInterface> backend,
|
||||
std::unique_ptr<etl::WriterStateInterface const> writerState,
|
||||
std::unique_ptr<data::LedgerCacheLoadingStateInterface const> cacheLoadingState,
|
||||
std::chrono::steady_clock::duration readInterval,
|
||||
std::chrono::steady_clock::duration writeInterval
|
||||
)
|
||||
: backend_(std::move(backend))
|
||||
, writerState_(std::move(writerState))
|
||||
, cacheLoadingState_(std::move(cacheLoadingState))
|
||||
, readerTask_(readInterval, ctx)
|
||||
, writerTask_(writeInterval, ctx)
|
||||
, selfUuid_(std::make_shared<boost::uuids::uuid>(boost::uuids::random_generator{}()))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Backend::run()
|
||||
{
|
||||
readerTask_.run([this](boost::asio::yield_context yield) {
|
||||
auto clusterData = doRead(yield);
|
||||
onNewState_(selfUuid_, std::make_shared<ClusterData>(std::move(clusterData)));
|
||||
});
|
||||
|
||||
writerTask_.run([this]() { doWrite(); });
|
||||
}
|
||||
|
||||
Backend::~Backend()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void
|
||||
Backend::stop()
|
||||
{
|
||||
readerTask_.stop();
|
||||
writerTask_.stop();
|
||||
}
|
||||
|
||||
ClioNode::CUuid
|
||||
Backend::selfId() const
|
||||
{
|
||||
return selfUuid_;
|
||||
}
|
||||
|
||||
Backend::ClusterData
|
||||
Backend::doRead(boost::asio::yield_context yield)
|
||||
{
|
||||
BackendInterface::ClioNodesDataFetchResult expectedResult;
|
||||
try {
|
||||
expectedResult = backend_->fetchClioNodesData(yield);
|
||||
} catch (...) {
|
||||
expectedResult = std::unexpected{"Failed to fetch Clio nodes data"};
|
||||
}
|
||||
|
||||
if (!expectedResult.has_value()) {
|
||||
return std::unexpected{std::move(expectedResult).error()};
|
||||
}
|
||||
|
||||
std::vector<ClioNode> otherNodesData;
|
||||
for (auto const& [uuid, nodeDataStr] : expectedResult.value()) {
|
||||
if (uuid == *selfUuid_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::system::error_code errorCode;
|
||||
auto const json = boost::json::parse(nodeDataStr, errorCode);
|
||||
if (errorCode.failed()) {
|
||||
return std::unexpected{fmt::format("Error parsing json from DB: {}", nodeDataStr)};
|
||||
}
|
||||
|
||||
auto expectedNodeData = boost::json::try_value_to<ClioNode>(json);
|
||||
if (expectedNodeData.has_error()) {
|
||||
return std::unexpected{
|
||||
fmt::format("Error converting json to ClioNode: {}", nodeDataStr)
|
||||
};
|
||||
}
|
||||
*expectedNodeData->uuid = uuid;
|
||||
otherNodesData.push_back(std::move(expectedNodeData).value());
|
||||
}
|
||||
otherNodesData.push_back(ClioNode::from(selfUuid_, *writerState_, *cacheLoadingState_));
|
||||
return otherNodesData;
|
||||
}
|
||||
|
||||
void
|
||||
Backend::doWrite()
|
||||
{
|
||||
auto const selfData = ClioNode::from(selfUuid_, *writerState_, *cacheLoadingState_);
|
||||
boost::json::value jsonValue{};
|
||||
boost::json::value_from(selfData, jsonValue);
|
||||
backend_->writeNodeMessage(*selfData.uuid, boost::json::serialize(jsonValue.as_object()));
|
||||
}
|
||||
|
||||
} // namespace cluster
|
||||
@@ -1,152 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2025, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cluster/ClioNode.hpp"
|
||||
#include "cluster/impl/RepeatedTask.hpp"
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "data/LedgerCacheLoadingState.hpp"
|
||||
#include "etl/WriterState.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
#include <boost/asio/cancellation_signal.hpp>
|
||||
#include <boost/asio/execution_context.hpp>
|
||||
#include <boost/asio/executor.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
#include <boost/signals2/connection.hpp>
|
||||
#include <boost/signals2/signal.hpp>
|
||||
#include <boost/signals2/variadic_signal.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <concepts>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace cluster {
|
||||
|
||||
/**
|
||||
* @brief Backend communication handler for cluster state synchronization.
|
||||
*
|
||||
* This class manages reading and writing cluster state information to/from the backend database.
|
||||
* It periodically reads the state of other nodes in the cluster and writes the current node's
|
||||
* state, enabling cluster-wide coordination and awareness.
|
||||
*/
|
||||
class Backend {
|
||||
public:
|
||||
/** @brief Type representing cluster data result - either a vector of nodes or an error message
|
||||
*/
|
||||
using ClusterData = std::expected<std::vector<ClioNode>, std::string>;
|
||||
|
||||
private:
|
||||
util::Logger log_{"ClusterCommunication"};
|
||||
|
||||
std::shared_ptr<data::BackendInterface> backend_;
|
||||
std::unique_ptr<etl::WriterStateInterface const> writerState_;
|
||||
std::unique_ptr<data::LedgerCacheLoadingStateInterface const> cacheLoadingState_;
|
||||
|
||||
impl::RepeatedTask<boost::asio::thread_pool> readerTask_;
|
||||
impl::RepeatedTask<boost::asio::thread_pool> writerTask_;
|
||||
|
||||
ClioNode::Uuid selfUuid_;
|
||||
|
||||
boost::signals2::signal<void(ClioNode::CUuid, std::shared_ptr<ClusterData const>)> onNewState_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a Backend communication handler.
|
||||
*
|
||||
* @param ctx The execution context for asynchronous operations
|
||||
* @param backend Interface to the backend database
|
||||
* @param writerState State indicating whether this node is writing to the database
|
||||
* @param cacheLoadingState State controlling whether this node is allowed to load the cache
|
||||
* @param readInterval How often to read cluster state from the backend
|
||||
* @param writeInterval How often to write this node's state to the backend
|
||||
*/
|
||||
Backend(
|
||||
boost::asio::thread_pool& ctx,
|
||||
std::shared_ptr<data::BackendInterface> backend,
|
||||
std::unique_ptr<etl::WriterStateInterface const> writerState,
|
||||
std::unique_ptr<data::LedgerCacheLoadingStateInterface const> cacheLoadingState,
|
||||
std::chrono::steady_clock::duration readInterval,
|
||||
std::chrono::steady_clock::duration writeInterval
|
||||
);
|
||||
|
||||
~Backend();
|
||||
|
||||
Backend(Backend&&) = delete;
|
||||
Backend&
|
||||
operator=(Backend&&) = delete;
|
||||
Backend(Backend const&) = delete;
|
||||
Backend&
|
||||
operator=(Backend const&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Start the backend read and write tasks.
|
||||
*
|
||||
* Begins periodic reading of cluster state from the backend and writing of this node's state.
|
||||
*/
|
||||
void
|
||||
run();
|
||||
|
||||
/**
|
||||
* @brief Stop the backend read and write tasks.
|
||||
*
|
||||
* Stops all periodic tasks and waits for them to complete.
|
||||
*/
|
||||
void
|
||||
stop();
|
||||
|
||||
/**
|
||||
* @brief Subscribe to new cluster state notifications.
|
||||
*
|
||||
* @tparam S Callable type accepting (ClioNode::cUUID, ClusterData)
|
||||
* @param s Subscriber callback to be invoked when new cluster state is available
|
||||
* @return A connection object that can be used to unsubscribe
|
||||
*/
|
||||
template <typename S>
|
||||
requires std::invocable<S, ClioNode::CUuid, std::shared_ptr<ClusterData const>>
|
||||
boost::signals2::connection
|
||||
subscribeToNewState(S&& s)
|
||||
{
|
||||
return onNewState_.connect(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the UUID of this node in the cluster.
|
||||
*
|
||||
* @return The UUID of this node.
|
||||
*/
|
||||
ClioNode::CUuid
|
||||
selfId() const;
|
||||
|
||||
private:
|
||||
ClusterData
|
||||
doRead(boost::asio::yield_context yield);
|
||||
|
||||
void
|
||||
doWrite();
|
||||
};
|
||||
|
||||
} // namespace cluster
|
||||
@@ -1,14 +1,5 @@
|
||||
add_library(clio_cluster)
|
||||
|
||||
target_sources(
|
||||
clio_cluster
|
||||
PRIVATE
|
||||
Backend.cpp
|
||||
CacheLoaderDecider.cpp
|
||||
ClioNode.cpp
|
||||
ClusterCommunicationService.cpp
|
||||
Metrics.cpp
|
||||
WriterDecider.cpp
|
||||
)
|
||||
target_sources(clio_cluster PRIVATE ClioNode.cpp ClusterCommunicationService.cpp)
|
||||
|
||||
target_link_libraries(clio_cluster PRIVATE clio_util clio_data)
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2026, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "cluster/CacheLoaderDecider.hpp"
|
||||
|
||||
#include "cluster/Backend.hpp"
|
||||
#include "cluster/ClioNode.hpp"
|
||||
#include "data/LedgerCacheLoadingState.hpp"
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/Spawn.hpp"
|
||||
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace cluster {
|
||||
|
||||
CacheLoaderDecider::CacheLoaderDecider(
|
||||
boost::asio::thread_pool& ctx,
|
||||
std::unique_ptr<data::LedgerCacheLoadingStateInterface> cacheLoadingState
|
||||
)
|
||||
: ctx_(ctx), cacheLoadingState_(std::move(cacheLoadingState))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CacheLoaderDecider::onNewState(
|
||||
ClioNode::CUuid selfId,
|
||||
std::shared_ptr<Backend::ClusterData const> clusterData
|
||||
)
|
||||
{
|
||||
if (not clusterData->has_value())
|
||||
return;
|
||||
|
||||
util::spawn(
|
||||
ctx_,
|
||||
[cacheLoadingState = cacheLoadingState_->clone(),
|
||||
selfId = std::move(selfId),
|
||||
clusterData = clusterData->value()](auto&&) mutable {
|
||||
auto const selfData = std::ranges::find_if(
|
||||
clusterData, [&selfId](ClioNode const& node) { return node.uuid == selfId; }
|
||||
);
|
||||
ASSERT(selfData != clusterData.end(), "Self data should always be in the cluster data");
|
||||
|
||||
if (selfData->cacheIsFull)
|
||||
return;
|
||||
|
||||
std::vector<ClioNode> notFullNodes;
|
||||
std::ranges::copy_if(
|
||||
clusterData, std::back_inserter(notFullNodes), [](ClioNode const& node) {
|
||||
return not node.cacheIsFull;
|
||||
}
|
||||
);
|
||||
|
||||
auto const someNodeIsLoadingCache = std::ranges::any_of(
|
||||
notFullNodes, [](ClioNode const& node) { return node.cacheIsCurrentlyLoading; }
|
||||
);
|
||||
if (someNodeIsLoadingCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::ranges::sort(notFullNodes, [](ClioNode const& lhs, ClioNode const& rhs) {
|
||||
return *lhs.uuid < *rhs.uuid;
|
||||
});
|
||||
|
||||
if (*notFullNodes.front().uuid == *selfId) {
|
||||
cacheLoadingState->allowLoading();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace cluster
|
||||
@@ -1,80 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2026, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cluster/Backend.hpp"
|
||||
#include "cluster/ClioNode.hpp"
|
||||
#include "data/LedgerCacheLoadingState.hpp"
|
||||
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace cluster {
|
||||
|
||||
/**
|
||||
* @brief Decides which node in the cluster should load the ledger cache.
|
||||
*
|
||||
* This class monitors cluster state changes and determines whether the current node
|
||||
* should begin loading the ledger cache from the backend. The decision is made by:
|
||||
* 1. Doing nothing if this node's cache is already full
|
||||
* 2. Doing nothing if any node in the cluster is currently loading the cache
|
||||
* 3. Sorting all nodes whose cache is not yet full by UUID for deterministic ordering
|
||||
* 4. Permitting loading on this node if it is the first in the sorted list
|
||||
*
|
||||
* This ensures at most one node in the cluster loads the cache at a time.
|
||||
*/
|
||||
class CacheLoaderDecider {
|
||||
/** @brief Thread pool for spawning asynchronous tasks */
|
||||
boost::asio::thread_pool& ctx_;
|
||||
|
||||
/** @brief Interface for controlling cache loading permission of this node */
|
||||
std::unique_ptr<data::LedgerCacheLoadingStateInterface> cacheLoadingState_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a CacheLoaderDecider.
|
||||
*
|
||||
* @param ctx Thread pool for executing asynchronous operations
|
||||
* @param cacheLoadingState Cache loading state interface for permitting cache load
|
||||
*/
|
||||
CacheLoaderDecider(
|
||||
boost::asio::thread_pool& ctx,
|
||||
std::unique_ptr<data::LedgerCacheLoadingStateInterface> cacheLoadingState
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Handles cluster state changes and decides whether this node should load the cache.
|
||||
*
|
||||
* This method is called when cluster state changes. It asynchronously:
|
||||
* - Does nothing if this node's cache is already full
|
||||
* - Does nothing if any node in the cluster is currently loading the cache
|
||||
* - Sorts all not-yet-full nodes by UUID to establish a deterministic order
|
||||
* - Permits cache loading on this node if it is first in the sorted list
|
||||
*
|
||||
* @param selfId The UUID of the current node
|
||||
* @param clusterData Shared pointer to current cluster data; may be empty if communication
|
||||
* failed
|
||||
*/
|
||||
void
|
||||
onNewState(ClioNode::CUuid selfId, std::shared_ptr<Backend::ClusterData const> clusterData);
|
||||
};
|
||||
|
||||
} // namespace cluster
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
#include "cluster/ClioNode.hpp"
|
||||
|
||||
#include "data/LedgerCacheLoadingState.hpp"
|
||||
#include "etl/WriterState.hpp"
|
||||
#include "util/TimeUtils.hpp"
|
||||
|
||||
#include <boost/json/conversion.hpp>
|
||||
@@ -28,107 +26,39 @@
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace cluster {
|
||||
|
||||
namespace {
|
||||
|
||||
struct JsonFields {
|
||||
struct Fields {
|
||||
static constexpr std::string_view const kUPDATE_TIME = "update_time";
|
||||
static constexpr std::string_view const kDB_ROLE = "db_role";
|
||||
static constexpr std::string_view const kETL_STARTED = "etl_started";
|
||||
static constexpr std::string_view const kCACHE_IS_FULL = "cache_is_full";
|
||||
static constexpr std::string_view const kCACHE_IS_CURRENTLY_LOADING =
|
||||
"cache_is_currently_loading";
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
ClioNode
|
||||
ClioNode::from(
|
||||
ClioNode::Uuid uuid,
|
||||
etl::WriterStateInterface const& writerState,
|
||||
data::LedgerCacheLoadingStateInterface const& cacheLoadingState
|
||||
)
|
||||
{
|
||||
auto const dbRole = [&writerState]() {
|
||||
if (writerState.isReadOnly()) {
|
||||
return ClioNode::DbRole::ReadOnly;
|
||||
}
|
||||
if (writerState.isFallback()) {
|
||||
return ClioNode::DbRole::Fallback;
|
||||
}
|
||||
|
||||
return writerState.isWriting() ? ClioNode::DbRole::Writer : ClioNode::DbRole::NotWriter;
|
||||
}();
|
||||
return ClioNode{
|
||||
.uuid = std::move(uuid),
|
||||
.updateTime = std::chrono::system_clock::now(),
|
||||
.dbRole = dbRole,
|
||||
.etlStarted = writerState.isEtlStarted(),
|
||||
.cacheIsFull = writerState.isCacheFull(),
|
||||
.cacheIsCurrentlyLoading = cacheLoadingState.isCurrentlyLoading()
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, ClioNode const& node)
|
||||
{
|
||||
jv = {
|
||||
{JsonFields::kUPDATE_TIME, util::systemTpToUtcStr(node.updateTime, ClioNode::kTIME_FORMAT)},
|
||||
{JsonFields::kDB_ROLE, static_cast<int64_t>(node.dbRole)},
|
||||
{JsonFields::kETL_STARTED, node.etlStarted},
|
||||
{JsonFields::kCACHE_IS_FULL, node.cacheIsFull},
|
||||
{JsonFields::kCACHE_IS_CURRENTLY_LOADING, node.cacheIsCurrentlyLoading}
|
||||
{Fields::kUPDATE_TIME, util::systemTpToUtcStr(node.updateTime, ClioNode::kTIME_FORMAT)},
|
||||
};
|
||||
}
|
||||
|
||||
ClioNode
|
||||
tag_invoke(boost::json::value_to_tag<ClioNode>, boost::json::value const& jv)
|
||||
{
|
||||
auto const& obj = jv.as_object();
|
||||
auto const& updateTimeStr = obj.at(JsonFields::kUPDATE_TIME).as_string();
|
||||
auto const updateTime =
|
||||
util::systemTpFromUtcStr(std::string(updateTimeStr), ClioNode::kTIME_FORMAT);
|
||||
auto const& updateTimeStr = jv.as_object().at(Fields::kUPDATE_TIME).as_string();
|
||||
auto const updateTime = util::systemTpFromUtcStr(std::string(updateTimeStr), ClioNode::kTIME_FORMAT);
|
||||
if (!updateTime.has_value()) {
|
||||
throw std::runtime_error("Failed to parse update time");
|
||||
}
|
||||
|
||||
// Each field has a default value for backward compatibility
|
||||
auto dbRole = ClioNode::DbRole::Fallback;
|
||||
if (auto const* v = obj.if_contains(JsonFields::kDB_ROLE)) {
|
||||
auto const dbRoleValue = v->as_int64();
|
||||
if (dbRoleValue > static_cast<int64_t>(ClioNode::DbRole::MAX))
|
||||
throw std::runtime_error("Invalid db_role value");
|
||||
dbRole = static_cast<ClioNode::DbRole>(dbRoleValue);
|
||||
}
|
||||
|
||||
auto const etlStarted =
|
||||
obj.contains(JsonFields::kETL_STARTED) ? obj.at(JsonFields::kETL_STARTED).as_bool() : true;
|
||||
auto const cacheIsFull = obj.contains(JsonFields::kCACHE_IS_FULL)
|
||||
? obj.at(JsonFields::kCACHE_IS_FULL).as_bool()
|
||||
: true;
|
||||
auto const cacheIsCurrentlyLoading = obj.contains(JsonFields::kCACHE_IS_CURRENTLY_LOADING)
|
||||
? obj.at(JsonFields::kCACHE_IS_CURRENTLY_LOADING).as_bool()
|
||||
: false;
|
||||
|
||||
return ClioNode{
|
||||
// Json data doesn't contain uuid so leaving it empty here. It will be filled outside of
|
||||
// this parsing
|
||||
.uuid = std::make_shared<boost::uuids::uuid>(),
|
||||
.updateTime = updateTime.value(),
|
||||
.dbRole = dbRole,
|
||||
.etlStarted = etlStarted,
|
||||
.cacheIsFull = cacheIsFull,
|
||||
.cacheIsCurrentlyLoading = cacheIsCurrentlyLoading
|
||||
};
|
||||
return ClioNode{.uuid = std::make_shared<boost::uuids::uuid>(), .updateTime = updateTime.value()};
|
||||
}
|
||||
|
||||
} // namespace cluster
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheLoadingState.hpp"
|
||||
#include "etl/WriterState.hpp"
|
||||
|
||||
#include <boost/json/conversion.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
@@ -40,46 +37,16 @@ struct ClioNode {
|
||||
*/
|
||||
static constexpr char const* kTIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ";
|
||||
|
||||
/**
|
||||
* @brief Database role of a node in the cluster.
|
||||
*
|
||||
* Roles are used to coordinate which node writes to the database:
|
||||
* - ReadOnly: Node is configured to never write (strict read-only mode)
|
||||
* - NotWriter: Node can write but is currently not the designated writer
|
||||
* - Writer: Node is actively writing to the database
|
||||
* - Fallback: Node is using the fallback writer decision mechanism
|
||||
*
|
||||
* When any node in the cluster is in Fallback mode, the entire cluster switches
|
||||
* from the cluster communication mechanism to the slower but more reliable
|
||||
* database-based conflict detection mechanism.
|
||||
*/
|
||||
enum class DbRole { ReadOnly = 0, NotWriter = 1, Writer = 2, Fallback = 3, MAX = 3 };
|
||||
// enum class WriterRole {
|
||||
// ReadOnly,
|
||||
// NotWriter,
|
||||
// Writer
|
||||
// };
|
||||
|
||||
using Uuid = std::shared_ptr<boost::uuids::uuid>;
|
||||
using CUuid = std::shared_ptr<boost::uuids::uuid const>;
|
||||
std::shared_ptr<boost::uuids::uuid> uuid; ///< The UUID of the node.
|
||||
std::chrono::system_clock::time_point updateTime; ///< The time the data about the node was last updated.
|
||||
|
||||
Uuid uuid; ///< The UUID of the node.
|
||||
std::chrono::system_clock::time_point
|
||||
updateTime; ///< The time the data about the node was last updated.
|
||||
DbRole dbRole; ///< The database role of the node
|
||||
bool etlStarted; ///< Whether the ETL monitor has started on this node
|
||||
bool cacheIsFull; ///< Whether the ledger cache is fully loaded on this node
|
||||
bool cacheIsCurrentlyLoading; ///< Whether this node is currently loading the ledger cache
|
||||
|
||||
/**
|
||||
* @brief Create a ClioNode from writer state and cache loading state.
|
||||
*
|
||||
* @param uuid The UUID of the node
|
||||
* @param writerState The writer state to determine the node's database role
|
||||
* @param cacheLoadingState The cache loading state to determine if cache is being loaded
|
||||
* @return A ClioNode with the current time and role derived from writerState
|
||||
*/
|
||||
static ClioNode
|
||||
from(
|
||||
Uuid uuid,
|
||||
etl::WriterStateInterface const& writerState,
|
||||
data::LedgerCacheLoadingStateInterface const& cacheLoadingState
|
||||
);
|
||||
// WriterRole writerRole;
|
||||
};
|
||||
|
||||
void
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user