Compare commits

...

33 Commits

Author SHA1 Message Date
Ayaz Salikhov
c69091bded chore: Add Git information compile-time info to only one file (#6464)
The existing code added the git commit info (`GIT_COMMIT_HASH` and `GIT_BRANCH`) to every file, which was a problem for leveraging `ccache` to cache build objects. This change adds a separate C++ file from where these compile-time variables are propagated to wherever they are needed. A new CMake file is added to set the commit info if the `git` binary is available.
2026-03-04 19:45:28 +00:00
Alex Kremer
595f0dd461 chore: Enable clang-tidy bugprone-sizeof-expression check (#6466) 2026-03-04 19:15:22 +00:00
Alex Kremer
b451d5e412 chore: Enable clang-tidy bugprone-return-const-ref-from-parameter check (#6459) 2026-03-04 18:10:10 +00:00
Alex Kremer
af97df5a63 chore: Enable clang-tidy bugprone-move-forwarding-reference check (#6457) 2026-03-04 17:03:27 +00:00
Peter Chen
e39954d128 fix: Gateway balance with MPT (#6143)
When `gateway_balances` gets called on an account that is involved in the `EscrowCreate` transaction (with MPT being escrowed), the method returns internal error. This change fixes this case by excluding the MPT type when totaling escrow amount.
2026-03-04 15:50:51 +00:00
tequ
3cd1e3d94e refactor: Update PermissionedDomainDelete to use keylet for sle access (#6063) 2026-03-04 04:11:58 +01:00
Ayaz Salikhov
fcec31ed20 chore: Update pre-commit hooks (#6460) 2026-03-03 20:23:22 +00:00
dependabot[bot]
0abd762781 ci: [DEPENDABOT] bump actions/upload-artifact from 6.0.0 to 7.0.0 (#6450) 2026-03-03 17:17:08 +00:00
Sergey Kuznetsov
5300e65686 tests: Improve stability of Subscribe tests (#6420)
The `Subscribe` tests were flaky, because each test performs some operations (e.g. sends transactions) and waits for messages to appear in subscription with a 100ms timeout. If tests are slow (e.g. compiled in debug mode or a slow machine) then some of them could fail. This change adds an attempt to synchronize the background Env's thread and the test's thread by ensuring that all the scheduled operations are started before the test's thread starts to wait for a websocket message. This is done by limiting I/O threads of the app inside Env to 1 and adding a synchronization barrier after closing the ledger.
2026-03-03 08:46:55 -05:00
Alex Kremer
afc660a1b5 refactor: Fix clang-tidy bugprone-empty-catch check (#6419)
This change fixes or suppresses instances detected by the `bugprone-empty-catch` clang-tidy check.
2026-03-02 17:08:56 +00:00
Vito Tumas
1a7f824b89 refactor: Splits invariant checks into multiple classes (#6440)
The invariant check system had grown into a single monolithic file pair containing 24 invariant checker classes. The large `InvariantCheck.cpp` file was a frequent source of merge conflicts and difficult to navigate. This refactoring improves maintainability and readability with zero behavioral changes.

In particular, this change:
- Splits `InvariantCheck.h` and `InvariantCheck.cpp` into 10 focused header/source pairs organized by domain under a new `invariants/` subdirectory.
- Extracts the shared `Privilege` enum and `hasPrivilege()` function into a dedicated `InvariantCheckPrivilege.h` header, so domain-specific files can reference them independently.
2026-02-27 21:02:39 +00:00
Sergey Kuznetsov
b58c681189 chore: Make nix hook optional (#6431)
This change makes the `nix` pre-commit hook optional in development environments, and enforced only inside Github Actions.
2026-02-27 13:36:10 -05:00
Mayukha Vadari
404f35d556 test: Grep for failures in CI (#6339)
This change adjusts the CI tests to make it easier to spot errors, without needing to sift through the thousands of lines of output.
2026-02-27 03:01:38 +00:00
Alex Kremer
2e595b6031 chore: Enable clang-tidy checks without issues (#6414)
This change enables all clang-tidy checks that are already passing. It also modifies the clang-tidy CI job, so it runs against all files if .clang-tidy changed.
2026-02-26 18:26:58 +00:00
Bart
3a8a18c2ca refactor: Use uint256 directly as key instead of void pointer (#6313)
This change replaces `void const*` by `uint256 const&` for database fetches.

Object hashes are expressed using the `uint256` data type, and are converted to `void *` when calling the `fetch` or `fetchBatch` functions. However, in these fetch functions they are converted back to `uint256`, making the conversion process unnecessary. In a few cases the underlying pointer is needed, but that can then be easy obtained via `[hash variable].data()`.
2026-02-25 18:23:34 -05:00
Ayaz Salikhov
65e63ebef3 chore: Update cleanup-workspace to delete old .conan2 dir on macOS (#6412) 2026-02-25 01:12:16 +00:00
Valentin Balaschenko
bdd106d992 Explicitly trim the heap after cache sweeps (#6022)
Limited to Linux/glibc builds.
2026-02-24 21:33:13 +00:00
Valentin Balaschenko
24cbaf76a5 ci: Update prepare-runner action to fix macOS build environment (empty)
Updates XRPLF/actions prepare-runner to version 2cbf48101 which fixes
pip upgrade failures on macOS runners with Homebrew-managed Python.

* This commit was cherry-picked from "release-3.1", but ended up empty
  because the changes are already present. It is included only for
  accounting - to indicate that all changes/commits from the previous
  release will be in the next one.
2026-02-24 12:52:32 -05:00
Valentin Balaschenko
3a805cc646 Disable featureBatch and fixBatchInnerSigs amendments (#6402) 2026-02-24 12:49:59 -05:00
Sergey Kuznetsov
0fd237d707 chore: Add nix development environment (#6314)
---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-23 20:10:07 -05:00
dependabot[bot]
3542daa4cc ci: [DEPENDABOT] bump actions/upload-artifact from 4.6.2 to 6.0.0 (#6396)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 6.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](ea165f8d65...b7c566a772)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 22:48:01 +00:00
dependabot[bot]
fd9f57ec97 ci: [DEPENDABOT] bump actions/checkout from 4.3.0 to 6.0.2 (#6397)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.3.0 to 6.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.3.0...de0fac2e4500dabe0009e67214ff5f5447ce83dd)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 22:09:48 +00:00
dependabot[bot]
625becff18 ci: [DEPENDABOT] bump actions/setup-python from 5.6.0 to 6.2.0 (#6395)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.6.0 to 6.2.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](a26af69be9...a309ff8b42)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 6.2.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 21:29:05 +00:00
dependabot[bot]
4bcbc6e50f ci: [DEPENDABOT] bump tj-actions/changed-files from 46.0.5 to 47.0.4 (#6394)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 46.0.5 to 47.0.4.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](ed68ef82c0...7dee1b0c15)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-version: 47.0.4
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 19:59:37 +00:00
dependabot[bot]
0bc4a0cfe8 ci: [DEPENDABOT] bump codecov/codecov-action from 5.4.3 to 5.5.2 (#6398)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.3 to 5.5.2.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](18283e04ce...671740ac38)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 5.5.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 19:11:26 +00:00
Ayaz Salikhov
cb54adefed ci: Build docs in PRs and in private repos (#6400) 2026-02-20 13:41:43 -05:00
Ayaz Salikhov
d03d72bfd5 ci: Add dependabot config (#6379) 2026-02-20 09:19:00 +00:00
Ed Hennis
6f35d94b2f Fix tautological assertion (#6393) 2026-02-20 01:58:47 +00:00
Ayaz Salikhov
2c1fad1023 chore: Apply clang-format width 100 (#6387) 2026-02-19 23:30:00 +00:00
Ayaz Salikhov
25cca46553 chore: Set clang-format width to 100 in config file (#6387) 2026-02-19 23:29:46 +00:00
Ayaz Salikhov
469ce9f291 chore: Set cmake-format width to 100 (#6386) 2026-02-19 19:42:51 +00:00
Sergey Kuznetsov
31302877ab ci: Add clang tidy workflow to ci (#6369) 2026-02-19 14:06:44 -05:00
Jingchen
0976b2b68b refactor: Modularize app/tx (#6228) 2026-02-17 18:10:07 +00:00
942 changed files with 32151 additions and 16621 deletions

View File

@@ -37,7 +37,7 @@ BinPackParameters: false
BreakBeforeBinaryOperators: false BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true BreakConstructorInitializersBeforeComma: true
ColumnLimit: 120 ColumnLimit: 100
CommentPragmas: "^ IWYU pragma:" CommentPragmas: "^ IWYU pragma:"
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4

201
.clang-tidy Normal file
View File

@@ -0,0 +1,201 @@
---
Checks: "-*,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-bad-signal-to-kill-thread,
bugprone-bool-pointer-implicit-conversion,
bugprone-casting-through-void,
bugprone-chained-comparison,
bugprone-compare-pointer-to-member-virtual-function,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-empty-catch,
bugprone-fold-init-type,
bugprone-forward-declaration-namespace,
bugprone-inaccurate-erase,
bugprone-incorrect-enable-if,
bugprone-incorrect-roundings,
bugprone-infinite-loop,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multi-level-implicit-pointer-conversion,
bugprone-multiple-new-in-one-expression,
bugprone-multiple-statement-macro,
bugprone-no-escape,
bugprone-non-zero-enum-to-bool-conversion,
bugprone-parent-virtual-call,
bugprone-posix-return,
bugprone-redundant-branch-condition,
bugprone-return-const-ref-from-parameter,
bugprone-shared-ptr-array-mismatch,
bugprone-signal-handler,
bugprone-signed-char-misuse,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-standalone-empty,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-stringview-nullptr,
bugprone-suspicious-enum-usage,
bugprone-suspicious-include,
bugprone-suspicious-memory-comparison,
bugprone-suspicious-memset-usage,
bugprone-suspicious-realloc-usage,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-exception-at-new,
bugprone-unique-ptr-array-mismatch,
bugprone-unsafe-functions,
bugprone-virtual-near-miss,
cppcoreguidelines-no-suspend-with-lock,
cppcoreguidelines-virtual-class-destructor,
hicpp-ignored-remove-result,
misc-definitions-in-headers,
misc-header-include-cycle,
misc-misplaced-const,
misc-static-assert,
misc-throw-by-value-catch-by-reference,
misc-unused-alias-decls,
misc-unused-using-decls,
readability-duplicate-include,
readability-enum-initial-value,
readability-misleading-indentation,
readability-non-const-parameter,
readability-redundant-declaration,
readability-reference-to-constructed-temporary,
modernize-deprecated-headers,
modernize-make-shared,
modernize-make-unique,
performance-implicit-conversion-in-loop,
performance-move-constructor-init,
performance-trivially-destructible
"
# ---
# more checks that have some issues that need to be resolved:
#
# bugprone-crtp-constructor-accessibility,
# bugprone-inc-dec-in-conditions,
# bugprone-reserved-identifier,
# bugprone-move-forwarding-reference,
# bugprone-unused-local-non-trivial-variable,
# bugprone-switch-missing-default-case,
# bugprone-suspicious-stringview-data-usage,
# bugprone-suspicious-missing-comma,
# bugprone-pointer-arithmetic-on-polymorphic-object,
# bugprone-optional-value-conversion,
# bugprone-too-small-loop-variable,
# bugprone-unused-return-value,
# bugprone-use-after-move,
# bugprone-unhandled-self-assignment,
# bugprone-unused-raii,
#
# cppcoreguidelines-misleading-capture-default-by-value,
# cppcoreguidelines-init-variables,
# cppcoreguidelines-pro-type-member-init,
# cppcoreguidelines-pro-type-static-cast-downcast,
# cppcoreguidelines-use-default-member-init,
# cppcoreguidelines-rvalue-reference-param-not-moved,
#
# llvm-namespace-comment,
# misc-const-correctness,
# misc-include-cleaner,
# misc-redundant-expression,
#
# readability-avoid-nested-conditional-operator,
# readability-avoid-return-with-void-value,
# readability-braces-around-statements,
# readability-container-contains,
# readability-container-size-empty,
# readability-convert-member-functions-to-static,
# readability-const-return-type,
# readability-else-after-return,
# readability-implicit-bool-conversion,
# readability-inconsistent-declaration-parameter-name,
# readability-identifier-naming,
# readability-make-member-function-const,
# readability-math-missing-parentheses,
# readability-redundant-inline-specifier,
# readability-redundant-member-init,
# readability-redundant-casting,
# readability-redundant-string-init,
# readability-simplify-boolean-expr,
# readability-static-definition-in-anonymous-namespace,
# readability-suspicious-call-argument,
# readability-use-std-min-max,
# readability-static-accessed-through-instance,
#
# modernize-concat-nested-namespaces,
# modernize-pass-by-value,
# modernize-type-traits,
# modernize-use-designated-initializers,
# modernize-use-emplace,
# modernize-use-equals-default,
# modernize-use-equals-delete,
# modernize-use-override,
# modernize-use-ranges,
# modernize-use-starts-ends-with,
# modernize-use-std-numbers,
# modernize-use-using,
#
# performance-faster-string-find,
# performance-for-range-copy,
# performance-inefficient-vector-operation,
# performance-move-const-arg,
# performance-no-automatic-move,
# ---
#
CheckOptions:
# readability-braces-around-statements.ShortStatementLines: 2
# readability-identifier-naming.MacroDefinitionCase: UPPER_CASE
# readability-identifier-naming.ClassCase: CamelCase
# readability-identifier-naming.StructCase: CamelCase
# readability-identifier-naming.UnionCase: CamelCase
# readability-identifier-naming.EnumCase: CamelCase
# readability-identifier-naming.EnumConstantCase: CamelCase
# readability-identifier-naming.ScopedEnumConstantCase: CamelCase
# readability-identifier-naming.GlobalConstantCase: UPPER_CASE
# readability-identifier-naming.GlobalConstantPrefix: "k"
# readability-identifier-naming.GlobalVariableCase: CamelCase
# readability-identifier-naming.GlobalVariablePrefix: "g"
# readability-identifier-naming.ConstexprFunctionCase: camelBack
# readability-identifier-naming.ConstexprMethodCase: camelBack
# readability-identifier-naming.ClassMethodCase: camelBack
# readability-identifier-naming.ClassMemberCase: camelBack
# readability-identifier-naming.ClassConstantCase: UPPER_CASE
# readability-identifier-naming.ClassConstantPrefix: "k"
# readability-identifier-naming.StaticConstantCase: UPPER_CASE
# readability-identifier-naming.StaticConstantPrefix: "k"
# readability-identifier-naming.StaticVariableCase: UPPER_CASE
# readability-identifier-naming.StaticVariablePrefix: "k"
# readability-identifier-naming.ConstexprVariableCase: UPPER_CASE
# readability-identifier-naming.ConstexprVariablePrefix: "k"
# readability-identifier-naming.LocalConstantCase: camelBack
# readability-identifier-naming.LocalVariableCase: camelBack
# readability-identifier-naming.TemplateParameterCase: CamelCase
# readability-identifier-naming.ParameterCase: camelBack
# readability-identifier-naming.FunctionCase: camelBack
# readability-identifier-naming.MemberCase: camelBack
# readability-identifier-naming.PrivateMemberSuffix: _
# readability-identifier-naming.ProtectedMemberSuffix: _
# readability-identifier-naming.PublicMemberSuffix: ""
# readability-identifier-naming.FunctionIgnoredRegexp: ".*tag_invoke.*"
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
# bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
# misc-include-cleaner.IgnoreHeaders: '.*/(detail|impl)/.*;.*(expected|unexpected).*;.*ranges_lower_bound\.h;time.h;stdlib.h;__chrono/.*;fmt/chrono.h;boost/uuid/uuid_hash.hpp'
#
# HeaderFilterRegex: '^.*/(src|tests)/.*\.(h|hpp)$'
WarningsAsErrors: "*"

View File

@@ -29,7 +29,7 @@ format:
disable: false disable: false
_help_line_width: _help_line_width:
- How wide to allow formatted cmake files - How wide to allow formatted cmake files
line_width: 120 line_width: 100
_help_tab_size: _help_tab_size:
- How many spaces to tab for indent - How many spaces to tab for indent
tab_size: 4 tab_size: 4

56
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
- package-ecosystem: github-actions
directory: .github/actions/build-deps/
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
- package-ecosystem: github-actions
directory: .github/actions/generate-version/
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
- package-ecosystem: github-actions
directory: .github/actions/print-env/
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
- package-ecosystem: github-actions
directory: .github/actions/setup-conan/
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop

View File

@@ -32,6 +32,14 @@ libxrpl.server > xrpl.server
libxrpl.shamap > xrpl.basics libxrpl.shamap > xrpl.basics
libxrpl.shamap > xrpl.protocol libxrpl.shamap > xrpl.protocol
libxrpl.shamap > xrpl.shamap libxrpl.shamap > xrpl.shamap
libxrpl.tx > xrpl.basics
libxrpl.tx > xrpl.conditions
libxrpl.tx > xrpl.core
libxrpl.tx > xrpl.json
libxrpl.tx > xrpl.ledger
libxrpl.tx > xrpl.protocol
libxrpl.tx > xrpl.server
libxrpl.tx > xrpl.tx
test.app > test.jtx test.app > test.jtx
test.app > test.rpc test.app > test.rpc
test.app > test.toplevel test.app > test.toplevel
@@ -49,6 +57,7 @@ test.app > xrpl.protocol
test.app > xrpl.rdb test.app > xrpl.rdb
test.app > xrpl.resource test.app > xrpl.resource
test.app > xrpl.server test.app > xrpl.server
test.app > xrpl.tx
test.basics > test.jtx test.basics > test.jtx
test.basics > test.unit_test test.basics > test.unit_test
test.basics > xrpl.basics test.basics > xrpl.basics
@@ -67,6 +76,7 @@ test.consensus > xrpld.app
test.consensus > xrpld.consensus test.consensus > xrpld.consensus
test.consensus > xrpl.json test.consensus > xrpl.json
test.consensus > xrpl.ledger test.consensus > xrpl.ledger
test.consensus > xrpl.tx
test.core > test.jtx test.core > test.jtx
test.core > test.toplevel test.core > test.toplevel
test.core > test.unit_test test.core > test.unit_test
@@ -93,6 +103,7 @@ test.jtx > xrpl.net
test.jtx > xrpl.protocol test.jtx > xrpl.protocol
test.jtx > xrpl.resource test.jtx > xrpl.resource
test.jtx > xrpl.server test.jtx > xrpl.server
test.jtx > xrpl.tx
test.ledger > test.jtx test.ledger > test.jtx
test.ledger > test.toplevel test.ledger > test.toplevel
test.ledger > xrpl.basics test.ledger > xrpl.basics
@@ -138,9 +149,11 @@ test.rpc > xrpld.core
test.rpc > xrpld.overlay test.rpc > xrpld.overlay
test.rpc > xrpld.rpc test.rpc > xrpld.rpc
test.rpc > xrpl.json test.rpc > xrpl.json
test.rpc > xrpl.ledger
test.rpc > xrpl.protocol test.rpc > xrpl.protocol
test.rpc > xrpl.resource test.rpc > xrpl.resource
test.rpc > xrpl.server test.rpc > xrpl.server
test.rpc > xrpl.tx
test.server > test.jtx test.server > test.jtx
test.server > test.toplevel test.server > test.toplevel
test.server > test.unit_test test.server > test.unit_test
@@ -171,6 +184,7 @@ xrpl.json > xrpl.basics
xrpl.ledger > xrpl.basics xrpl.ledger > xrpl.basics
xrpl.ledger > xrpl.protocol xrpl.ledger > xrpl.protocol
xrpl.ledger > xrpl.server xrpl.ledger > xrpl.server
xrpl.ledger > xrpl.shamap
xrpl.net > xrpl.basics xrpl.net > xrpl.basics
xrpl.nodestore > xrpl.basics xrpl.nodestore > xrpl.basics
xrpl.nodestore > xrpl.protocol xrpl.nodestore > xrpl.protocol
@@ -192,9 +206,12 @@ xrpl.server > xrpl.shamap
xrpl.shamap > xrpl.basics xrpl.shamap > xrpl.basics
xrpl.shamap > xrpl.nodestore xrpl.shamap > xrpl.nodestore
xrpl.shamap > xrpl.protocol xrpl.shamap > xrpl.protocol
xrpl.tx > xrpl.basics
xrpl.tx > xrpl.core
xrpl.tx > xrpl.ledger
xrpl.tx > xrpl.protocol
xrpld.app > test.unit_test xrpld.app > test.unit_test
xrpld.app > xrpl.basics xrpld.app > xrpl.basics
xrpld.app > xrpl.conditions
xrpld.app > xrpl.core xrpld.app > xrpl.core
xrpld.app > xrpld.consensus xrpld.app > xrpld.consensus
xrpld.app > xrpld.core xrpld.app > xrpld.core
@@ -207,6 +224,7 @@ xrpld.app > xrpl.rdb
xrpld.app > xrpl.resource xrpld.app > xrpl.resource
xrpld.app > xrpl.server xrpld.app > xrpl.server
xrpld.app > xrpl.shamap xrpld.app > xrpl.shamap
xrpld.app > xrpl.tx
xrpld.consensus > xrpl.basics xrpld.consensus > xrpl.basics
xrpld.consensus > xrpl.json xrpld.consensus > xrpl.json
xrpld.consensus > xrpl.protocol xrpld.consensus > xrpl.protocol
@@ -225,6 +243,7 @@ xrpld.overlay > xrpl.protocol
xrpld.overlay > xrpl.rdb xrpld.overlay > xrpl.rdb
xrpld.overlay > xrpl.resource xrpld.overlay > xrpl.resource
xrpld.overlay > xrpl.server xrpld.overlay > xrpl.server
xrpld.overlay > xrpl.tx
xrpld.peerfinder > xrpl.basics xrpld.peerfinder > xrpl.basics
xrpld.peerfinder > xrpld.core xrpld.peerfinder > xrpld.core
xrpld.peerfinder > xrpl.protocol xrpld.peerfinder > xrpl.protocol
@@ -244,4 +263,5 @@ xrpld.rpc > xrpl.protocol
xrpld.rpc > xrpl.rdb xrpld.rpc > xrpl.rdb
xrpld.rpc > xrpl.resource xrpld.rpc > xrpl.resource
xrpld.rpc > xrpl.server xrpld.rpc > xrpl.server
xrpld.rpc > xrpl.tx
xrpld.shamap > xrpl.shamap xrpld.shamap > xrpl.shamap

View File

@@ -33,7 +33,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Determine changed files - name: Determine changed files
# This step checks whether any files have changed that should # This step checks whether any files have changed that should
# cause the next jobs to run. We do it this way rather than # cause the next jobs to run. We do it this way rather than
@@ -46,7 +46,7 @@ jobs:
# that Github considers any skipped jobs to have passed, and in # that Github considers any skipped jobs to have passed, and in
# turn the required checks as well. # turn the required checks as well.
id: changes id: changes
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5 uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4
with: with:
files: | files: |
# These paths are unique to `on-pr.yml`. # These paths are unique to `on-pr.yml`.
@@ -65,9 +65,12 @@ jobs:
.github/workflows/reusable-build.yml .github/workflows/reusable-build.yml
.github/workflows/reusable-build-test-config.yml .github/workflows/reusable-build-test-config.yml
.github/workflows/reusable-build-test.yml .github/workflows/reusable-build-test.yml
.github/workflows/reusable-clang-tidy.yml
.github/workflows/reusable-clang-tidy-files.yml
.github/workflows/reusable-strategy-matrix.yml .github/workflows/reusable-strategy-matrix.yml
.github/workflows/reusable-test.yml .github/workflows/reusable-test.yml
.github/workflows/reusable-upload-recipe.yml .github/workflows/reusable-upload-recipe.yml
.clang-tidy
.codecov.yml .codecov.yml
cmake/** cmake/**
conan/** conan/**
@@ -107,6 +110,17 @@ jobs:
if: ${{ needs.should-run.outputs.go == 'true' }} if: ${{ needs.should-run.outputs.go == 'true' }}
uses: ./.github/workflows/reusable-check-rename.yml uses: ./.github/workflows/reusable-check-rename.yml
clang-tidy:
needs: should-run
if: ${{ needs.should-run.outputs.go == 'true' }}
uses: ./.github/workflows/reusable-clang-tidy.yml
permissions:
issues: write
contents: read
with:
check_only_changed: true
create_issue_on_failure: false
build-test: build-test:
needs: should-run needs: should-run
if: ${{ needs.should-run.outputs.go == 'true' }} if: ${{ needs.should-run.outputs.go == 'true' }}
@@ -156,6 +170,7 @@ jobs:
needs: needs:
- check-levelization - check-levelization
- check-rename - check-rename
- clang-tidy
- build-test - build-test
- upload-recipe - upload-recipe
- notify-clio - notify-clio

View File

@@ -22,9 +22,12 @@ on:
- ".github/workflows/reusable-build.yml" - ".github/workflows/reusable-build.yml"
- ".github/workflows/reusable-build-test-config.yml" - ".github/workflows/reusable-build-test-config.yml"
- ".github/workflows/reusable-build-test.yml" - ".github/workflows/reusable-build-test.yml"
- ".github/workflows/reusable-clang-tidy.yml"
- ".github/workflows/reusable-clang-tidy-files.yml"
- ".github/workflows/reusable-strategy-matrix.yml" - ".github/workflows/reusable-strategy-matrix.yml"
- ".github/workflows/reusable-test.yml" - ".github/workflows/reusable-test.yml"
- ".github/workflows/reusable-upload-recipe.yml" - ".github/workflows/reusable-upload-recipe.yml"
- ".clang-tidy"
- ".codecov.yml" - ".codecov.yml"
- "cmake/**" - "cmake/**"
- "conan/**" - "conan/**"
@@ -60,6 +63,15 @@ defaults:
shell: bash shell: bash
jobs: jobs:
clang-tidy:
uses: ./.github/workflows/reusable-clang-tidy.yml
permissions:
issues: write
contents: read
with:
check_only_changed: false
create_issue_on_failure: ${{ github.event_name == 'schedule' }}
build-test: build-test:
uses: ./.github/workflows/reusable-build-test.yml uses: ./.github/workflows/reusable-build-test.yml
strategy: strategy:

View File

@@ -11,7 +11,7 @@ on:
jobs: jobs:
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks. # Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
run-hooks: run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@320be44621ca2a080f05aeb15817c44b84518108 uses: XRPLF/actions/.github/workflows/pre-commit.yml@56de1bdf19639e009639a50b8d17c28ca954f267
with: with:
runs_on: ubuntu-latest runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-ab4d1f0" }' container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'

View File

@@ -4,6 +4,18 @@ name: Build and publish documentation
on: on:
push: push:
branches:
- "develop"
- "release*"
paths:
- ".github/workflows/publish-docs.yml"
- "*.md"
- "**/*.md"
- "docs/**"
- "include/**"
- "src/libxrpl/**"
- "src/xrpld/**"
pull_request:
paths: paths:
- ".github/workflows/publish-docs.yml" - ".github/workflows/publish-docs.yml"
- "*.md" - "*.md"
@@ -23,7 +35,9 @@ defaults:
env: env:
BUILD_DIR: build BUILD_DIR: build
NPROC_SUBTRACT: 2 # ubuntu-latest has only 2 CPUs for private repositories
# https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for--private-repositories
NPROC_SUBTRACT: ${{ github.event.repository.private && '1' || '2' }}
jobs: jobs:
publish: publish:
@@ -33,7 +47,12 @@ jobs:
contents: write contents: write
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
with:
enable_ccache: false
- name: Get number of processors - name: Get number of processors
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
@@ -65,7 +84,7 @@ jobs:
cmake --build . --target docs --parallel ${BUILD_NPROC} cmake --build . --target docs --parallel ${BUILD_NPROC}
- name: Publish documentation - name: Publish documentation
if: ${{ github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch }} if: ${{ github.event_name == 'push' }}
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -101,10 +101,10 @@ jobs:
steps: steps:
- name: Cleanup workspace (macOS and Windows) - name: Cleanup workspace (macOS and Windows)
if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }} if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }}
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
@@ -177,7 +177,7 @@ jobs:
- name: Upload the binary (Linux) - name: Upload the binary (Linux)
if: ${{ github.repository_owner == 'XRPLF' && runner.os == 'Linux' }} if: ${{ github.repository_owner == 'XRPLF' && runner.os == 'Linux' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: xrpld-${{ inputs.config_name }} name: xrpld-${{ inputs.config_name }}
path: ${{ env.BUILD_DIR }}/xrpld path: ${{ env.BUILD_DIR }}/xrpld
@@ -229,8 +229,21 @@ jobs:
env: env:
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }} BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
run: | run: |
./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" set -o pipefail
./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
- name: Show test failure summary
if: ${{ failure() && !inputs.build_only }}
working-directory: ${{ runner.os == 'Windows' && format('{0}/{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
run: |
if [ ! -f unittest.log ]; then
echo "unittest.log not found; embedded tests may not have run."
exit 0
fi
if ! grep -E "failed" unittest.log; then
echo "Log present but no failure lines found in unittest.log."
fi
- name: Debug failure (Linux) - name: Debug failure (Linux)
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }} if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}
run: | run: |
@@ -254,7 +267,7 @@ jobs:
- name: Upload coverage report - name: Upload coverage report
if: ${{ github.repository_owner == 'XRPLF' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }} if: ${{ github.repository_owner == 'XRPLF' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }}
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3 uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
with: with:
disable_search: true disable_search: true
disable_telem: true disable_telem: true

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check levelization - name: Check levelization
run: .github/scripts/levelization/generate.sh run: .github/scripts/levelization/generate.sh
- name: Check for differences - name: Check for differences

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check definitions - name: Check definitions
run: .github/scripts/rename/definitions.sh . run: .github/scripts/rename/definitions.sh .
- name: Check copyright notices - name: Check copyright notices

View File

@@ -0,0 +1,162 @@
name: Run clang-tidy on files
on:
workflow_call:
inputs:
files:
description: "List of files to check (empty means check all files)"
type: string
default: ""
create_issue_on_failure:
description: "Whether to create an issue if the check failed"
type: boolean
default: false
defaults:
run:
shell: bash
env:
# Conan installs the generators in the build/generators directory, see the
# layout() method in conanfile.py. We then run CMake from the build directory.
BUILD_DIR: build
BUILD_TYPE: Release
jobs:
run-clang-tidy:
name: Run clang tidy
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: "ghcr.io/xrplf/ci/debian-trixie:clang-21-sha-53033a2"
permissions:
issues: write
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
with:
enable_ccache: false
- name: Print build environment
uses: ./.github/actions/print-env
- name: Get number of processors
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
id: nproc
- name: Setup Conan
uses: ./.github/actions/setup-conan
- name: Build dependencies
uses: ./.github/actions/build-deps
with:
build_nproc: ${{ steps.nproc.outputs.nproc }}
build_type: ${{ env.BUILD_TYPE }}
log_verbosity: verbose
- name: Configure CMake
working-directory: ${{ env.BUILD_DIR }}
run: |
cmake \
-G 'Ninja' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-Dtests=ON \
-Dwerr=ON \
-Dxrpld=ON \
..
# clang-tidy needs headers generated from proto files
- name: Build libxrpl.libpb
working-directory: ${{ env.BUILD_DIR }}
run: |
ninja -j ${{ steps.nproc.outputs.nproc }} xrpl.libpb
- name: Run clang tidy
id: run_clang_tidy
continue-on-error: true
env:
TARGETS: ${{ inputs.files != '' && inputs.files || 'src tests' }}
run: |
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" ${TARGETS} 2>&1 | tee clang-tidy-output.txt
- name: Upload clang-tidy output
if: steps.run_clang_tidy.outcome != 'success'
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: clang-tidy-results
path: clang-tidy-output.txt
retention-days: 30
- name: Create an issue
if: steps.run_clang_tidy.outcome != 'success' && inputs.create_issue_on_failure
id: create_issue
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
# Prepare issue body with clang-tidy output
cat > issue.md <<EOF
## Clang-tidy Check Failed
**Workflow:** ${{ github.workflow }}
**Run ID:** ${{ github.run_id }}
**Commit:** ${{ github.sha }}
**Branch/Ref:** ${{ github.ref }}
**Triggered by:** ${{ github.actor }}
### Clang-tidy Output:
\`\`\`
EOF
# Append clang-tidy output (filter for errors and warnings)
if [ -f clang-tidy-output.txt ]; then
# Extract lines containing 'error:', 'warning:', or 'note:'
grep -E '(error:|warning:|note:)' clang-tidy-output.txt > filtered-output.txt || true
# If filtered output is empty, use original (might be a different error format)
if [ ! -s filtered-output.txt ]; then
cp clang-tidy-output.txt filtered-output.txt
fi
# Truncate if too large
head -c 60000 filtered-output.txt >> issue.md
if [ "$(wc -c < filtered-output.txt)" -gt 60000 ]; then
echo "" >> issue.md
echo "... (output truncated, see artifacts for full output)" >> issue.md
fi
rm filtered-output.txt
else
echo "No output file found" >> issue.md
fi
cat >> issue.md <<EOF
\`\`\`
**Workflow run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
---
*This issue was automatically created by the clang-tidy workflow.*
EOF
# Create the issue
gh issue create \
--label "Bug,Clang-tidy" \
--title "Clang-tidy check failed" \
--body-file ./issue.md \
> create_issue.log
created_issue="$(sed 's|.*/||' create_issue.log)"
echo "created_issue=$created_issue" >> $GITHUB_OUTPUT
echo "Created issue #$created_issue"
rm -f create_issue.log issue.md clang-tidy-output.txt
- name: Fail the workflow if clang-tidy failed
if: steps.run_clang_tidy.outcome != 'success'
run: |
echo "Clang-tidy check failed!"
exit 1

View File

@@ -0,0 +1,55 @@
name: Clang-tidy check
on:
workflow_call:
inputs:
check_only_changed:
description: "Check only changed files in PR. If false, checks all files in the repository."
type: boolean
default: false
create_issue_on_failure:
description: "Whether to create an issue if the check failed"
type: boolean
default: false
defaults:
run:
shell: bash
jobs:
determine-files:
name: Determine files to check
if: ${{ inputs.check_only_changed }}
runs-on: ubuntu-latest
outputs:
clang_tidy_config_changed: ${{ steps.changed_clang_tidy.outputs.any_changed }}
any_cpp_changed: ${{ steps.changed_files.outputs.any_changed }}
all_changed_files: ${{ steps.changed_files.outputs.all_changed_files }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Get changed C++ files
id: changed_files
uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4
with:
files: |
**/*.cpp
**/*.h
**/*.ipp
separator: " "
- name: Get changed clang-tidy configuration
id: changed_clang_tidy
uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4
with:
files: |
.clang-tidy
run-clang-tidy:
needs: [determine-files]
if: ${{ always() && !cancelled() && (!inputs.check_only_changed || needs.determine-files.outputs.any_cpp_changed == 'true' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
uses: ./.github/workflows/reusable-clang-tidy-files.yml
with:
files: ${{ (needs.determine-files.outputs.clang_tidy_config_changed == 'true' && '') || (inputs.check_only_changed && needs.determine-files.outputs.all_changed_files || '') }}
create_issue_on_failure: ${{ inputs.create_issue_on_failure }}

View File

@@ -29,10 +29,10 @@ jobs:
matrix: ${{ steps.generate.outputs.matrix }} matrix: ${{ steps.generate.outputs.matrix }}
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Python - name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with: with:
python-version: 3.13 python-version: 3.13

View File

@@ -43,7 +43,7 @@ jobs:
container: ghcr.io/xrplf/ci/ubuntu-noble:gcc-13-sha-5dd7158 container: ghcr.io/xrplf/ci/ubuntu-noble:gcc-13-sha-5dd7158
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Generate build version number - name: Generate build version number
id: version id: version

View File

@@ -64,10 +64,10 @@ jobs:
steps: steps:
- name: Cleanup workspace (macOS and Windows) - name: Cleanup workspace (macOS and Windows)
if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }} if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }}
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d

6
.gitignore vendored
View File

@@ -42,6 +42,9 @@ gmon.out
# Locally patched Conan recipes # Locally patched Conan recipes
external/conan-center-index/ external/conan-center-index/
# Local conan directory
.conan
# XCode IDE. # XCode IDE.
*.pbxuser *.pbxuser
!default.pbxuser !default.pbxuser
@@ -72,5 +75,8 @@ DerivedData
/.claude /.claude
/CLAUDE.md /CLAUDE.md
# Direnv's directory
/.direnv
# clangd cache # clangd cache
/.cache /.cache

View File

@@ -20,7 +20,7 @@ repos:
args: [--assume-in-merge] args: [--assume-in-merge]
- repo: https://github.com/pre-commit/mirrors-clang-format - repo: https://github.com/pre-commit/mirrors-clang-format
rev: 75ca4ad908dc4a99f57921f29b7e6c1521e10b26 # frozen: v21.1.8 rev: cd481d7b0bfb5c7b3090c21846317f9a8262e891 # frozen: v22.1.0
hooks: hooks:
- id: clang-format - id: clang-format
args: [--style=file] args: [--style=file]
@@ -33,17 +33,17 @@ repos:
additional_dependencies: [PyYAML] additional_dependencies: [PyYAML]
- repo: https://github.com/rbubley/mirrors-prettier - repo: https://github.com/rbubley/mirrors-prettier
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2 rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
hooks: hooks:
- id: prettier - id: prettier
- repo: https://github.com/psf/black-pre-commit-mirror - repo: https://github.com/psf/black-pre-commit-mirror
rev: 831207fd435b47aeffdf6af853097e64322b4d44 # frozen: v25.12.0 rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0
hooks: hooks:
- id: black - id: black
- repo: https://github.com/streetsidesoftware/cspell-cli - repo: https://github.com/streetsidesoftware/cspell-cli
rev: 1cfa010f078c354f3ffb8413616280cc28f5ba21 # frozen: v9.4.0 rev: a42085ade523f591dca134379a595e7859986445 # frozen: v9.7.0
hooks: hooks:
- id: cspell # Spell check changed files - id: cspell # Spell check changed files
exclude: .config/cspell.config.yaml exclude: .config/cspell.config.yaml
@@ -57,6 +57,24 @@ repos:
- .git/COMMIT_EDITMSG - .git/COMMIT_EDITMSG
stages: [commit-msg] stages: [commit-msg]
- repo: local
hooks:
- id: nix-fmt
name: Format Nix files
entry: |
bash -c '
if command -v nix &> /dev/null || [ "$GITHUB_ACTIONS" = "true" ]; then
nix --extra-experimental-features "nix-command flakes" fmt "$@"
else
echo "Skipping nix-fmt: nix not installed and not in GitHub Actions"
exit 0
fi
' --
language: system
types:
- nix
pass_filenames: true
exclude: | exclude: |
(?x)^( (?x)^(
external/.*| external/.*|

View File

@@ -17,6 +17,7 @@ project(xrpl)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(CompilationEnv) include(CompilationEnv)
@@ -35,26 +36,6 @@ endif ()
# Enable ccache to speed up builds. # Enable ccache to speed up builds.
include(Ccache) include(Ccache)
# make GIT_COMMIT_HASH define available to all sources
find_package(Git)
if (Git_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git rev-parse HEAD
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE gch)
if (gch)
set(GIT_COMMIT_HASH "${gch}")
message(STATUS gch: ${GIT_COMMIT_HASH})
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
endif ()
execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git rev-parse --abbrev-ref HEAD
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE gb)
if (gb)
set(GIT_BRANCH "${gb}")
message(STATUS gb: ${GIT_BRANCH})
add_definitions(-DGIT_BRANCH="${GIT_BRANCH}")
endif ()
endif () # git
if (thread_safety_analysis) if (thread_safety_analysis)
add_compile_options(-Wthread-safety -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS add_compile_options(-Wthread-safety -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
-DXRPL_ENABLE_THREAD_SAFETY_ANNOTATIONS) -DXRPL_ENABLE_THREAD_SAFETY_ANNOTATIONS)
@@ -67,7 +48,8 @@ include(FetchContent)
include(ExternalProject) include(ExternalProject)
include(CMakeFuncs) # must come *after* ExternalProject b/c it overrides one function in EP include(CMakeFuncs) # must come *after* ExternalProject b/c it overrides one function in EP
if (target) if (target)
message(FATAL_ERROR "The target option has been removed - use native cmake options to control build") message(FATAL_ERROR "The target option has been removed - use native cmake options to control build"
)
endif () endif ()
include(XrplSanity) include(XrplSanity)
@@ -76,7 +58,8 @@ include(XrplSettings)
# this check has to remain in the top-level cmake because of the early return statement # this check has to remain in the top-level cmake because of the early return statement
if (packages_only) if (packages_only)
if (NOT TARGET rpm) if (NOT TARGET rpm)
message(FATAL_ERROR "packages_only requested, but targets were not created - is docker installed?") message(FATAL_ERROR "packages_only requested, but targets were not created - is docker installed?"
)
endif () endif ()
return() return()
endif () endif ()
@@ -118,7 +101,8 @@ target_link_libraries(
option(rocksdb "Enable RocksDB" ON) option(rocksdb "Enable RocksDB" ON)
if (rocksdb) if (rocksdb)
find_package(RocksDB REQUIRED) find_package(RocksDB REQUIRED)
set_target_properties(RocksDB::rocksdb PROPERTIES INTERFACE_COMPILE_DEFINITIONS XRPL_ROCKSDB_AVAILABLE=1) set_target_properties(RocksDB::rocksdb PROPERTIES INTERFACE_COMPILE_DEFINITIONS
XRPL_ROCKSDB_AVAILABLE=1)
target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb) target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb)
endif () endif ()

View File

@@ -251,6 +251,29 @@ pip3 install pre-commit
pre-commit install pre-commit install
``` ```
## Clang-tidy
All code must pass `clang-tidy` checks according to the settings in [`.clang-tidy`](./.clang-tidy).
There is a Continuous Integration job that runs clang-tidy on pull requests. The CI will check:
- All changed C++ files (`.cpp`, `.h`, `.ipp`) when only code files are modified
- **All files in the repository** when the `.clang-tidy` configuration file is changed
This ensures that configuration changes don't introduce new warnings across the codebase.
### Running clang-tidy locally
Before running clang-tidy, you must build the project to generate required files (particularly protobuf headers). Refer to [`BUILD.md`](./BUILD.md) for build instructions.
Then run clang-tidy on your local changes:
```
run-clang-tidy -p build src tests
```
This will check all source files in the `src` and `tests` directories using the compile commands from your `build` directory.
## Contracts and instrumentation ## Contracts and instrumentation
We are using [Antithesis](https://antithesis.com/) for continuous fuzzing, We are using [Antithesis](https://antithesis.com/) for continuous fuzzing,

View File

@@ -43,7 +43,8 @@ set(CMAKE_VS_GLOBALS "CLToolExe=cl.exe" "CLToolPath=${CMAKE_BINARY_DIR}" "TrackF
# By default Visual Studio generators will use /Zi to capture debug information, which is not compatible with ccache, so # By default Visual Studio generators will use /Zi to capture debug information, which is not compatible with ccache, so
# tell it to use /Z7 instead. # tell it to use /Z7 instead.
if (MSVC) if (MSVC)
foreach (var_ CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE) foreach (var_ CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE)
string(REPLACE "/Zi" "/Z7" ${var_} "${${var_}}") string(REPLACE "/Zi" "/Z7" ${var_} "${${var_}}")
endforeach () endforeach ()
endif () endif ()

View File

@@ -180,7 +180,8 @@ elseif (DEFINED ENV{CODE_COVERAGE_GCOV_TOOL})
set(GCOV_TOOL "$ENV{CODE_COVERAGE_GCOV_TOOL}") set(GCOV_TOOL "$ENV{CODE_COVERAGE_GCOV_TOOL}")
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if (APPLE) if (APPLE)
execute_process(COMMAND xcrun -f llvm-cov OUTPUT_VARIABLE LLVMCOV_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND xcrun -f llvm-cov OUTPUT_VARIABLE LLVMCOV_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE)
else () else ()
find_program(LLVMCOV_PATH llvm-cov) find_program(LLVMCOV_PATH llvm-cov)
endif () endif ()
@@ -199,8 +200,8 @@ foreach (LANG ${LANGUAGES})
if ("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3) if ("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
endif () endif ()
elseif (NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU" AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES elseif (NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU" AND NOT "${CMAKE_${LANG}_COMPILER_ID}"
"(LLVM)?[Ff]lang") MATCHES "(LLVM)?[Ff]lang")
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...") message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
endif () endif ()
endforeach () endforeach ()
@@ -321,14 +322,16 @@ function (setup_target_for_coverage_gcovr)
endif () endif ()
if ("--output" IN_LIST GCOVR_ADDITIONAL_ARGS) if ("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting...") message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting..."
)
else () else ()
if ((Coverage_FORMAT STREQUAL "html-details") OR (Coverage_FORMAT STREQUAL "html-nested")) 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_OUTPUT_FILE ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html)
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME}) set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
elseif (Coverage_FORMAT STREQUAL "html-single") elseif (Coverage_FORMAT STREQUAL "html-single")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html) set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
elseif ((Coverage_FORMAT STREQUAL "json-summary") OR (Coverage_FORMAT STREQUAL "json-details") elseif ((Coverage_FORMAT STREQUAL "json-summary") OR (Coverage_FORMAT STREQUAL
"json-details")
OR (Coverage_FORMAT STREQUAL "coveralls")) OR (Coverage_FORMAT STREQUAL "coveralls"))
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json) set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
elseif (Coverage_FORMAT STREQUAL "txt") elseif (Coverage_FORMAT STREQUAL "txt")
@@ -452,8 +455,10 @@ function (setup_target_for_coverage_gcovr)
COMMENT "Running gcovr to produce code coverage report.") COMMENT "Running gcovr to produce code coverage report.")
# Show info where to find the report # Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD COMMAND echo add_custom_command(
COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}") TARGET ${Coverage_NAME} POST_BUILD COMMAND echo
COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
)
endfunction () # setup_target_for_coverage_gcovr endfunction () # setup_target_for_coverage_gcovr
function (add_code_coverage_to_target name scope) function (add_code_coverage_to_target name scope)
@@ -463,8 +468,9 @@ function (add_code_coverage_to_target name scope)
separate_arguments(COVERAGE_C_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_C_LINKER_FLAGS}") separate_arguments(COVERAGE_C_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_C_LINKER_FLAGS}")
# Add compiler options to the target # Add compiler options to the target
target_compile_options(${name} ${scope} $<$<COMPILE_LANGUAGE:CXX>:${COVERAGE_CXX_COMPILER_FLAGS}> target_compile_options(
$<$<COMPILE_LANGUAGE:C>:${COVERAGE_C_COMPILER_FLAGS}>) ${name} ${scope} $<$<COMPILE_LANGUAGE:CXX>:${COVERAGE_CXX_COMPILER_FLAGS}>
$<$<COMPILE_LANGUAGE:C>:${COVERAGE_C_COMPILER_FLAGS}>)
target_link_libraries(${name} ${scope} $<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS}> target_link_libraries(${name} ${scope} $<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS}>
$<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS}>) $<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS}>)

21
cmake/GitInfo.cmake Normal file
View File

@@ -0,0 +1,21 @@
include_guard()
set(GIT_BUILD_BRANCH "")
set(GIT_COMMIT_HASH "")
find_package(Git)
if (NOT Git_FOUND)
message(WARNING "Git not found. Git branch and commit hash will be empty.")
return()
endif ()
set(GIT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.git)
execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${GIT_DIRECTORY} rev-parse --abbrev-ref HEAD
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE GIT_BUILD_BRANCH)
execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${GIT_DIRECTORY} rev-parse HEAD
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE GIT_COMMIT_HASH)
message(STATUS "Git branch: ${GIT_BUILD_BRANCH}")
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}")

View File

@@ -17,7 +17,8 @@ link_libraries(Xrpl::common)
if (NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE) if (NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif () endif ()
set_target_properties(common PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE}) set_target_properties(common PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE
${CMAKE_POSITION_INDEPENDENT_CODE})
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
target_compile_definitions( target_compile_definitions(
common common
@@ -37,7 +38,8 @@ if (MSVC)
# remove existing exception flag since we set it to -EHa # remove existing exception flag since we set it to -EHa
string(REGEX REPLACE "[-/]EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REGEX REPLACE "[-/]EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
foreach (var_ CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE) foreach (var_ CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE)
# also remove dynamic runtime # also remove dynamic runtime
string(REGEX REPLACE "[-/]MD[d]*" " " ${var_} "${${var_}}") string(REGEX REPLACE "[-/]MD[d]*" " " ${var_} "${${var_}}")
@@ -143,20 +145,23 @@ if (voidstar)
elseif (NOT is_linux) elseif (NOT is_linux)
message(FATAL_ERROR "Antithesis instrumentation requires Linux, aborting...") message(FATAL_ERROR "Antithesis instrumentation requires Linux, aborting...")
elseif (NOT (is_clang AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)) elseif (NOT (is_clang AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0))
message(FATAL_ERROR "Antithesis instrumentation requires Clang version 16 or later, aborting...") message(FATAL_ERROR "Antithesis instrumentation requires Clang version 16 or later, aborting..."
)
endif () endif ()
endif () endif ()
if (use_mold) if (use_mold)
# use mold linker if available # use mold linker if available
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=mold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=mold -Wl,--version ERROR_QUIET
OUTPUT_VARIABLE LD_VERSION)
if ("${LD_VERSION}" MATCHES "mold") if ("${LD_VERSION}" MATCHES "mold")
target_link_libraries(common INTERFACE -fuse-ld=mold) target_link_libraries(common INTERFACE -fuse-ld=mold)
endif () endif ()
unset(LD_VERSION) unset(LD_VERSION)
elseif (use_gold AND is_gcc) elseif (use_gold AND is_gcc)
# use gold linker if available # use gold linker if available
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET
OUTPUT_VARIABLE LD_VERSION)
#[=========================================================[ #[=========================================================[
NOTE: THE gold linker inserts -rpath as DT_RUNPATH by NOTE: THE gold linker inserts -rpath as DT_RUNPATH by
default instead of DT_RPATH, so you might have slightly default instead of DT_RPATH, so you might have slightly
@@ -186,7 +191,8 @@ elseif (use_gold AND is_gcc)
unset(LD_VERSION) unset(LD_VERSION)
elseif (use_lld) elseif (use_lld)
# use lld linker if available # use lld linker if available
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=lld -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=lld -Wl,--version ERROR_QUIET
OUTPUT_VARIABLE LD_VERSION)
if ("${LD_VERSION}" MATCHES "LLD") if ("${LD_VERSION}" MATCHES "LLD")
target_link_libraries(common INTERFACE -fuse-ld=lld) target_link_libraries(common INTERFACE -fuse-ld=lld)
endif () endif ()

View File

@@ -14,7 +14,8 @@ target_protobuf_sources(xrpl.libpb xrpl/proto LANGUAGE cpp IMPORT_DIRS include/x
PROTOS include/xrpl/proto/xrpl.proto) PROTOS include/xrpl/proto/xrpl.proto)
file(GLOB_RECURSE protos "include/xrpl/proto/org/*.proto") file(GLOB_RECURSE protos "include/xrpl/proto/org/*.proto")
target_protobuf_sources(xrpl.libpb xrpl/proto LANGUAGE cpp IMPORT_DIRS include/xrpl/proto PROTOS "${protos}") target_protobuf_sources(xrpl.libpb xrpl/proto LANGUAGE cpp IMPORT_DIRS include/xrpl/proto
PROTOS "${protos}")
target_protobuf_sources( target_protobuf_sources(
xrpl.libpb xrpl/proto xrpl.libpb xrpl/proto
LANGUAGE grpc LANGUAGE grpc
@@ -24,8 +25,9 @@ target_protobuf_sources(
GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc) GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc)
target_compile_options( target_compile_options(
xrpl.libpb PUBLIC $<$<BOOL:${is_msvc}>:-wd4996> $<$<BOOL:${is_xcode}>: --system-header-prefix="google/protobuf" xrpl.libpb
-Wno-deprecated-dynamic-exception-spec > PUBLIC $<$<BOOL:${is_msvc}>:-wd4996> $<$<BOOL:${is_xcode}>:
--system-header-prefix="google/protobuf" -Wno-deprecated-dynamic-exception-spec >
PRIVATE $<$<BOOL:${is_msvc}>:-wd4065> $<$<NOT:$<BOOL:${is_msvc}>>:-Wno-deprecated-declarations>) PRIVATE $<$<BOOL:${is_msvc}>:-wd4065> $<$<NOT:$<BOOL:${is_msvc}>>:-Wno-deprecated-declarations>)
target_link_libraries(xrpl.libpb PUBLIC protobuf::libprotobuf gRPC::grpc++) target_link_libraries(xrpl.libpb PUBLIC protobuf::libprotobuf gRPC::grpc++)
@@ -56,6 +58,12 @@ include(target_link_modules)
add_module(xrpl beast) add_module(xrpl beast)
target_link_libraries(xrpl.libxrpl.beast PUBLIC xrpl.imports.main) target_link_libraries(xrpl.libxrpl.beast PUBLIC xrpl.imports.main)
include(GitInfo)
add_module(xrpl git)
target_compile_definitions(xrpl.libxrpl.git PRIVATE GIT_COMMIT_HASH="${GIT_COMMIT_HASH}"
GIT_BUILD_BRANCH="${GIT_BUILD_BRANCH}")
target_link_libraries(xrpl.libxrpl.git PUBLIC xrpl.imports.main)
# Level 02 # Level 02
add_module(xrpl basics) add_module(xrpl basics)
target_link_libraries(xrpl.libxrpl.basics PUBLIC xrpl.libxrpl.beast) target_link_libraries(xrpl.libxrpl.basics PUBLIC xrpl.libxrpl.beast)
@@ -69,11 +77,13 @@ target_link_libraries(xrpl.libxrpl.crypto PUBLIC xrpl.libxrpl.basics)
# Level 04 # Level 04
add_module(xrpl protocol) add_module(xrpl protocol)
target_link_libraries(xrpl.libxrpl.protocol PUBLIC xrpl.libxrpl.crypto xrpl.libxrpl.json) target_link_libraries(xrpl.libxrpl.protocol PUBLIC xrpl.libxrpl.crypto xrpl.libxrpl.git
xrpl.libxrpl.json)
# Level 05 # Level 05
add_module(xrpl core) add_module(xrpl core)
target_link_libraries(xrpl.libxrpl.core PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol) target_link_libraries(xrpl.libxrpl.core PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json
xrpl.libxrpl.protocol)
# Level 06 # Level 06
add_module(xrpl resource) add_module(xrpl resource)
@@ -81,22 +91,23 @@ target_link_libraries(xrpl.libxrpl.resource PUBLIC xrpl.libxrpl.protocol)
# Level 07 # Level 07
add_module(xrpl net) add_module(xrpl net)
target_link_libraries(xrpl.libxrpl.net PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol target_link_libraries(xrpl.libxrpl.net PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json
xrpl.libxrpl.resource) xrpl.libxrpl.protocol xrpl.libxrpl.resource)
add_module(xrpl nodestore) add_module(xrpl nodestore)
target_link_libraries(xrpl.libxrpl.nodestore PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol) target_link_libraries(xrpl.libxrpl.nodestore PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json
xrpl.libxrpl.protocol)
add_module(xrpl shamap) add_module(xrpl shamap)
target_link_libraries(xrpl.libxrpl.shamap PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.crypto xrpl.libxrpl.protocol target_link_libraries(xrpl.libxrpl.shamap PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.crypto
xrpl.libxrpl.nodestore) xrpl.libxrpl.protocol xrpl.libxrpl.nodestore)
add_module(xrpl rdb) add_module(xrpl rdb)
target_link_libraries(xrpl.libxrpl.rdb PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.core) target_link_libraries(xrpl.libxrpl.rdb PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.core)
add_module(xrpl server) add_module(xrpl server)
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol xrpl.libxrpl.core xrpl.libxrpl.rdb target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol xrpl.libxrpl.core
xrpl.libxrpl.resource) xrpl.libxrpl.rdb xrpl.libxrpl.resource)
add_module(xrpl conditions) add_module(xrpl conditions)
target_link_libraries(xrpl.libxrpl.conditions PUBLIC xrpl.libxrpl.server) target_link_libraries(xrpl.libxrpl.conditions PUBLIC xrpl.libxrpl.server)
@@ -109,8 +120,12 @@ target_link_libraries(
xrpl.libxrpl.protocol xrpl.libxrpl.protocol
xrpl.libxrpl.rdb xrpl.libxrpl.rdb
xrpl.libxrpl.server xrpl.libxrpl.server
xrpl.libxrpl.shamap
xrpl.libxrpl.conditions) xrpl.libxrpl.conditions)
add_module(xrpl tx)
target_link_libraries(xrpl.libxrpl.tx PUBLIC xrpl.libxrpl.ledger)
add_library(xrpl.libxrpl) add_library(xrpl.libxrpl)
set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl) set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
@@ -127,6 +142,7 @@ target_link_modules(
conditions conditions
core core
crypto crypto
git
json json
ledger ledger
net net
@@ -135,7 +151,8 @@ target_link_modules(
rdb rdb
resource resource
server server
shamap) shamap
tx)
# All headers in libxrpl are in modules. # All headers in libxrpl are in modules.
# Uncomment this stanza if you have not yet moved new headers into a module. # Uncomment this stanza if you have not yet moved new headers into a module.

View File

@@ -65,8 +65,8 @@ add_custom_command(
OUTPUT "${doxygen_index_file}" OUTPUT "${doxygen_index_file}"
COMMAND "${CMAKE_COMMAND}" -E env "DOXYGEN_OUTPUT_DIRECTORY=${doxygen_output_directory}" COMMAND "${CMAKE_COMMAND}" -E env "DOXYGEN_OUTPUT_DIRECTORY=${doxygen_output_directory}"
"DOXYGEN_INCLUDE_PATH=${doxygen_include_path}" "DOXYGEN_TAGFILES=${doxygen_tagfiles}" "DOXYGEN_INCLUDE_PATH=${doxygen_include_path}" "DOXYGEN_TAGFILES=${doxygen_tagfiles}"
"DOXYGEN_PLANTUML_JAR_PATH=${doxygen_plantuml_jar_path}" "DOXYGEN_DOT_PATH=${doxygen_dot_path}" "DOXYGEN_PLANTUML_JAR_PATH=${doxygen_plantuml_jar_path}"
"${DOXYGEN_EXECUTABLE}" "${doxyfile}" "DOXYGEN_DOT_PATH=${doxygen_dot_path}" "${DOXYGEN_EXECUTABLE}" "${doxyfile}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS "${dependencies}" "${tagfile}") DEPENDS "${dependencies}" "${tagfile}")
add_custom_target(docs DEPENDS "${doxygen_index_file}" SOURCES "${dependencies}") add_custom_target(docs DEPENDS "${doxygen_index_file}" SOURCES "${dependencies}")

View File

@@ -23,6 +23,7 @@ install(TARGETS common
xrpl.libxrpl.conditions xrpl.libxrpl.conditions
xrpl.libxrpl.core xrpl.libxrpl.core
xrpl.libxrpl.crypto xrpl.libxrpl.crypto
xrpl.libxrpl.git
xrpl.libxrpl.json xrpl.libxrpl.json
xrpl.libxrpl.rdb xrpl.libxrpl.rdb
xrpl.libxrpl.ledger xrpl.libxrpl.ledger
@@ -32,6 +33,7 @@ install(TARGETS common
xrpl.libxrpl.resource xrpl.libxrpl.resource
xrpl.libxrpl.server xrpl.libxrpl.server
xrpl.libxrpl.shamap xrpl.libxrpl.shamap
xrpl.libxrpl.tx
antithesis-sdk-cpp antithesis-sdk-cpp
EXPORT XrplExports EXPORT XrplExports
LIBRARY DESTINATION lib LIBRARY DESTINATION lib
@@ -40,11 +42,13 @@ install(TARGETS common
INCLUDES INCLUDES
DESTINATION include) DESTINATION include)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(EXPORT XrplExports FILE XrplTargets.cmake NAMESPACE Xrpl:: DESTINATION lib/cmake/xrpl) install(EXPORT XrplExports FILE XrplTargets.cmake NAMESPACE Xrpl:: DESTINATION lib/cmake/xrpl)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
write_basic_package_version_file(XrplConfigVersion.cmake VERSION ${xrpld_version} COMPATIBILITY SameMajorVersion) write_basic_package_version_file(XrplConfigVersion.cmake VERSION ${xrpld_version}
COMPATIBILITY SameMajorVersion)
if (is_root_project AND TARGET xrpld) if (is_root_project AND TARGET xrpld)
install(TARGETS xrpld RUNTIME DESTINATION bin) install(TARGETS xrpld RUNTIME DESTINATION bin)
@@ -71,5 +75,5 @@ if (is_root_project AND TARGET xrpld)
") ")
endif () endif ()
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/XrplConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/XrplConfigVersion.cmake install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/XrplConfig.cmake
DESTINATION lib/cmake/xrpl) ${CMAKE_CURRENT_BINARY_DIR}/XrplConfigVersion.cmake DESTINATION lib/cmake/xrpl)

View File

@@ -33,10 +33,13 @@ target_compile_definitions(
target_compile_options( target_compile_options(
opts opts
INTERFACE $<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override> INTERFACE $<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
$<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized> $<$<BOOL:${perf}>:-fno-omit-frame-pointer> $<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized>
$<$<BOOL:${profile}>:-pg> $<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>) $<$<BOOL:${perf}>:-fno-omit-frame-pointer>
$<$<BOOL:${profile}>:-pg>
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
target_link_libraries(opts INTERFACE $<$<BOOL:${profile}>:-pg> $<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>) target_link_libraries(opts INTERFACE $<$<BOOL:${profile}>:-pg>
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
if (jemalloc) if (jemalloc)
find_package(jemalloc REQUIRED) find_package(jemalloc REQUIRED)

View File

@@ -19,7 +19,8 @@ if (NOT is_multiconfig)
endif () endif ()
if (is_clang) # both Clang and AppleClang if (is_clang) # both Clang and AppleClang
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS
16.0)
message(FATAL_ERROR "This project requires clang 16 or later") message(FATAL_ERROR "This project requires clang 16 or later")
endif () endif ()
elseif (is_gcc) elseif (is_gcc)
@@ -32,7 +33,8 @@ endif ()
if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "Builds (in-source) are not allowed in " message(FATAL_ERROR "Builds (in-source) are not allowed in "
"${CMAKE_CURRENT_SOURCE_DIR}. Please remove CMakeCache.txt and the CMakeFiles " "${CMAKE_CURRENT_SOURCE_DIR}. Please remove CMakeCache.txt and the CMakeFiles "
"directory from ${CMAKE_CURRENT_SOURCE_DIR} and try building in a separate directory.") "directory from ${CMAKE_CURRENT_SOURCE_DIR} and try building in a separate directory."
)
endif () endif ()
if (MSVC AND CMAKE_GENERATOR_PLATFORM STREQUAL "Win32") if (MSVC AND CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")

View File

@@ -70,7 +70,8 @@ if (is_linux AND NOT SANITIZER)
else () else ()
set(TRUNCATED_LOGS_DEFAULT OFF) set(TRUNCATED_LOGS_DEFAULT OFF)
endif () endif ()
option(TRUNCATED_THREAD_NAME_LOGS "Show warnings about truncated thread names on Linux." ${TRUNCATED_LOGS_DEFAULT}) option(TRUNCATED_THREAD_NAME_LOGS "Show warnings about truncated thread names on Linux."
${TRUNCATED_LOGS_DEFAULT})
if (TRUNCATED_THREAD_NAME_LOGS) if (TRUNCATED_THREAD_NAME_LOGS)
add_compile_definitions(TRUNCATED_THREAD_NAME_LOGS) add_compile_definitions(TRUNCATED_THREAD_NAME_LOGS)
endif () endif ()
@@ -92,11 +93,13 @@ endif ()
option(jemalloc "Enables jemalloc for heap profiling" OFF) option(jemalloc "Enables jemalloc for heap profiling" OFF)
option(werr "treat warnings as errors" OFF) option(werr "treat warnings as errors" OFF)
option(local_protobuf "Force a local build of protobuf instead of looking for an installed version." OFF) option(local_protobuf
"Force a local build of protobuf instead of looking for an installed version." OFF)
option(local_grpc "Force a local build of gRPC instead of looking for an installed version." OFF) option(local_grpc "Force a local build of gRPC instead of looking for an installed version." OFF)
# the remaining options are obscure and rarely used # the remaining options are obscure and rarely used
option(beast_no_unit_test_inline "Prevents unit test definitions from being inserted into global table" OFF) option(beast_no_unit_test_inline
"Prevents unit test definitions from being inserted into global table" OFF)
option(single_io_service_thread "Restricts the number of threads calling io_context::run to one. \ option(single_io_service_thread "Restricts the number of threads calling io_context::run to one. \
This can be useful when debugging." OFF) This can be useful when debugging." OFF)
option(boost_show_deprecated "Allow boost to fail on deprecated usage. Only useful if you're trying\ option(boost_show_deprecated "Allow boost to fail on deprecated usage. Only useful if you're trying\

View File

@@ -1,4 +1,6 @@
option(validator_keys "Enables building of validator-keys tool as a separate target (imported via FetchContent)" OFF) option(validator_keys
"Enables building of validator-keys tool as a separate target (imported via FetchContent)"
OFF)
if (validator_keys) if (validator_keys)
git_branch(current_branch) git_branch(current_branch)
@@ -8,8 +10,9 @@ if (validator_keys)
endif () endif ()
message(STATUS "Tracking ValidatorKeys branch: ${current_branch}") message(STATUS "Tracking ValidatorKeys branch: ${current_branch}")
FetchContent_Declare(validator_keys GIT_REPOSITORY https://github.com/ripple/validator-keys-tool.git FetchContent_Declare(
GIT_TAG "${current_branch}") validator_keys GIT_REPOSITORY https://github.com/ripple/validator-keys-tool.git
GIT_TAG "${current_branch}")
FetchContent_MakeAvailable(validator_keys) FetchContent_MakeAvailable(validator_keys)
set_target_properties(validator-keys PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") set_target_properties(validator-keys PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
install(TARGETS validator-keys RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS validator-keys RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

@@ -15,11 +15,12 @@ include(isolate_headers)
function (add_module parent name) function (add_module parent name)
set(target ${PROJECT_NAME}.lib${parent}.${name}) set(target ${PROJECT_NAME}.lib${parent}.${name})
add_library(${target} OBJECT) add_library(${target} OBJECT)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}/*.cpp") file(GLOB_RECURSE sources CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}/*.cpp")
target_sources(${target} PRIVATE ${sources}) target_sources(${target} PRIVATE ${sources})
target_include_directories(${target} PUBLIC "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>") target_include_directories(${target} PUBLIC "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/include" isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/include/${parent}/${name}" PUBLIC) "${CMAKE_CURRENT_SOURCE_DIR}/include/${parent}/${name}" PUBLIC)
isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}" isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/src"
PRIVATE) "${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}" PRIVATE)
endfunction () endfunction ()

View File

@@ -39,6 +39,7 @@ if (SANITIZERS_ENABLED AND is_clang)
endif () endif ()
message(STATUS "Adding [${Boost_INCLUDE_DIRS}] to sanitizer blacklist") message(STATUS "Adding [${Boost_INCLUDE_DIRS}] to sanitizer blacklist")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt "src:${Boost_INCLUDE_DIRS}/*") file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt "src:${Boost_INCLUDE_DIRS}/*")
target_compile_options(opts INTERFACE # ignore boost headers for sanitizing target_compile_options(
-fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt) opts INTERFACE # ignore boost headers for sanitizing
-fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt)
endif () endif ()

View File

@@ -6,6 +6,7 @@ ignorePaths:
- docs/**/*.puml - docs/**/*.puml
- cmake/** - cmake/**
- LICENSE.md - LICENSE.md
- .clang-tidy
language: en language: en
allowCompoundWords: true # TODO (#6334) allowCompoundWords: true # TODO (#6334)
ignoreRandomStrings: true ignoreRandomStrings: true
@@ -172,6 +173,11 @@ words:
- nftokens - nftokens
- nftpage - nftpage
- nikb - nikb
- nixfmt
- nixos
- nixpkgs
- NOLINT
- NOLINTNEXTLINE
- nonxrp - nonxrp
- noripple - noripple
- nudb - nudb

View File

@@ -3,6 +3,8 @@ environment complete with Git, Python, Conan, CMake, and a C++ compiler.
This document exists to help readers set one up on any of the Big Three This document exists to help readers set one up on any of the Big Three
platforms: Linux, macOS, or Windows. platforms: Linux, macOS, or Windows.
As an alternative to system packages, the Nix development shell can be used to provide a development environment. See [using nix development shell](./nix.md) for more details.
[BUILD.md]: ../../BUILD.md [BUILD.md]: ../../BUILD.md
## Linux ## Linux

95
docs/build/nix.md vendored Normal file
View File

@@ -0,0 +1,95 @@
# Using Nix Development Shell for xrpld Development
This guide explains how to use Nix to set up a reproducible development environment for xrpld. Using Nix eliminates the need to manually install utilities and ensures consistent tooling across different machines.
## Benefits of Using Nix
- **Reproducible environment**: Everyone gets the same versions of tools and compilers
- **No system pollution**: Dependencies are isolated and don't affect your system packages
- **Multiple compiler versions**: Easily switch between different GCC and Clang versions
- **Quick setup**: Get started with a single command
- **Works on Linux and macOS**: Consistent experience across platforms
## Install Nix
Please follow [the official installation instructions of nix package manager](https://nixos.org/download/) for your system.
## Entering the Development Shell
### Basic Usage
From the root of the xrpld repository, enter the default development shell:
```bash
nix --experimental-features 'nix-command flakes' develop
```
This will:
- Download and set up all required development tools (CMake, Ninja, Conan, etc.)
- Configure the appropriate compiler for your platform:
- **macOS**: Apple Clang (default system compiler)
- **Linux**: GCC 15
The first time you run this command, it will take a few minutes to download and build the environment. Subsequent runs will be much faster.
> [!TIP]
> To avoid typing `--experimental-features 'nix-command flakes'` every time, you can permanently enable flakes by creating `~/.config/nix/nix.conf`:
>
> ```bash
> mkdir -p ~/.config/nix
> echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
> ```
>
> After this, you can simply use `nix develop` instead.
> [!NOTE]
> The examples below assume you've enabled flakes in your config. If you haven't, add `--experimental-features 'nix-command flakes'` after each `nix` command.
### Choosing a different compiler
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#gcc15`.
Use `nix flake show` to see all the available development shells.
Use `nix develop .#no_compiler` to use the compiler from your system.
### Example Usage
```bash
# Use GCC 14
nix develop .#gcc14
# Use Clang 19
nix develop .#clang19
# Use default for your platform
nix develop
```
### Using a different shell
`nix develop` opens bash by default. If you want to use another shell this could be done by adding `-c` flag. For example:
```bash
nix develop -c zsh
```
## Building xrpld with Nix
Once inside the Nix development shell, follow the standard [build instructions](../../BUILD.md#steps). The Nix shell provides all necessary tools (CMake, Ninja, Conan, etc.).
## Automatic Activation with direnv
[direnv](https://direnv.net/) or [nix-direnv](https://github.com/nix-community/nix-direnv) can automatically activate the Nix development shell when you enter the repository directory.
## Conan and Prebuilt Packages
Please note that there is no guarantee that binaries from conan cache will work when using nix. If you encounter any errors, please use `--build '*'` to force conan to compile everything from source:
```bash
conan install .. --output-folder . --build '*' --settings build_type=Release
```
## Updating `flake.lock` file
To update `flake.lock` to the latest revision use `nix flake update` command.

26
flake.lock generated Normal file
View File

@@ -0,0 +1,26 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1769461804,
"narHash": "sha256-6h5sROT/3CTHvzPy9koKBmoCa2eJKh4fzQK8eYFEgl8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b579d443b37c9c5373044201ea77604e37e748c8",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

16
flake.nix Normal file
View File

@@ -0,0 +1,16 @@
{
description = "Nix related things for xrpld";
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
};
outputs =
{ nixpkgs, ... }:
let
forEachSystem = (import ./nix/utils.nix { inherit nixpkgs; }).forEachSystem;
in
{
devShells = forEachSystem (import ./nix/devshell.nix);
formatter = forEachSystem ({ pkgs, ... }: pkgs.nixfmt);
};
}

View File

@@ -84,7 +84,8 @@ public:
if (lines_.empty()) if (lines_.empty())
return ""; return "";
if (lines_.size() > 1) if (lines_.size() > 1)
Throw<std::runtime_error>("A legacy value must have exactly one line. Section: " + name_); Throw<std::runtime_error>(
"A legacy value must have exactly one line. Section: " + name_);
return lines_[0]; return lines_[0];
} }
@@ -268,7 +269,8 @@ public:
bool bool
had_trailing_comments() const had_trailing_comments() const
{ {
return std::any_of(map_.cbegin(), map_.cend(), [](auto s) { return s.second.had_trailing_comments(); }); return std::any_of(
map_.cbegin(), map_.cend(), [](auto s) { return s.second.had_trailing_comments(); });
} }
protected: protected:

View File

@@ -35,7 +35,10 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
auto compressed = bf(outCapacity); auto compressed = bf(outCapacity);
auto compressedSize = LZ4_compress_default( auto compressedSize = LZ4_compress_default(
reinterpret_cast<char const*>(in), reinterpret_cast<char*>(compressed), inSize, outCapacity); reinterpret_cast<char const*>(in),
reinterpret_cast<char*>(compressed),
inSize,
outCapacity);
if (compressedSize == 0) if (compressedSize == 0)
Throw<std::runtime_error>("lz4 compress: failed"); Throw<std::runtime_error>("lz4 compress: failed");
@@ -66,8 +69,10 @@ lz4Decompress(
Throw<std::runtime_error>("lz4Decompress: integer overflow (output)"); Throw<std::runtime_error>("lz4Decompress: integer overflow (output)");
if (LZ4_decompress_safe( if (LZ4_decompress_safe(
reinterpret_cast<char const*>(in), reinterpret_cast<char*>(decompressed), inSize, decompressedSize) != reinterpret_cast<char const*>(in),
decompressedSize) reinterpret_cast<char*>(decompressed),
inSize,
decompressedSize) != decompressedSize)
Throw<std::runtime_error>("lz4Decompress: failed"); Throw<std::runtime_error>("lz4Decompress: failed");
return decompressedSize; return decompressedSize;
@@ -83,7 +88,11 @@ lz4Decompress(
*/ */
template <typename InputStream> template <typename InputStream>
std::size_t std::size_t
lz4Decompress(InputStream& in, std::size_t inSize, std::uint8_t* decompressed, std::size_t decompressedSize) lz4Decompress(
InputStream& in,
std::size_t inSize,
std::uint8_t* decompressed,
std::size_t decompressedSize)
{ {
std::vector<std::uint8_t> compressed; std::vector<std::uint8_t> compressed;
std::uint8_t const* chunk = nullptr; std::uint8_t const* chunk = nullptr;

View File

@@ -55,7 +55,8 @@ private:
if (m_value != value_type()) if (m_value != value_type())
{ {
std::size_t elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - m_when).count(); std::size_t elapsed =
std::chrono::duration_cast<std::chrono::seconds>(now - m_when).count();
// A span larger than four times the window decays the // A span larger than four times the window decays the
// value to an insignificant amount so just reset it. // value to an insignificant amount so just reset it.

View File

@@ -120,7 +120,8 @@ public:
template <typename U> template <typename U>
requires std::convertible_to<U, E> && (!std::is_reference_v<U>) requires std::convertible_to<U, E> && (!std::is_reference_v<U>)
constexpr Expected(Unexpected<U> e) : Base(boost::outcome_v2::in_place_type_t<E>{}, std::move(e.value())) constexpr Expected(Unexpected<U> e)
: Base(boost::outcome_v2::in_place_type_t<E>{}, std::move(e.value()))
{ {
} }
@@ -191,7 +192,8 @@ public:
// Specialization of Expected<void, E>. Allows returning either success // Specialization of Expected<void, E>. Allows returning either success
// (without a value) or the reason for the failure. // (without a value) or the reason for the failure.
template <class E> template <class E>
class [[nodiscard]] Expected<void, E> : private boost::outcome_v2::result<void, E, detail::throw_policy> class [[nodiscard]]
Expected<void, E> : private boost::outcome_v2::result<void, E, detail::throw_policy>
{ {
using Base = boost::outcome_v2::result<void, E, detail::throw_policy>; using Base = boost::outcome_v2::result<void, E, detail::throw_policy>;

View File

@@ -14,6 +14,9 @@ getFileContents(
std::optional<std::size_t> maxSize = std::nullopt); std::optional<std::size_t> maxSize = std::nullopt);
void void
writeFileContents(boost::system::error_code& ec, boost::filesystem::path const& destPath, std::string const& contents); writeFileContents(
boost::system::error_code& ec,
boost::filesystem::path const& destPath,
std::string const& contents);
} // namespace xrpl } // namespace xrpl

View File

@@ -44,8 +44,8 @@ struct SharedIntrusiveAdoptNoIncrementTag
// //
template <class T> template <class T>
concept CAdoptTag = concept CAdoptTag = std::is_same_v<T, SharedIntrusiveAdoptIncrementStrongTag> ||
std::is_same_v<T, SharedIntrusiveAdoptIncrementStrongTag> || std::is_same_v<T, SharedIntrusiveAdoptNoIncrementTag>; std::is_same_v<T, SharedIntrusiveAdoptNoIncrementTag>;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -443,7 +443,8 @@ make_SharedIntrusive(Args&&... args)
auto p = new TT(std::forward<Args>(args)...); auto p = new TT(std::forward<Args>(args)...);
static_assert( static_assert(
noexcept(SharedIntrusive<TT>(std::declval<TT*>(), std::declval<SharedIntrusiveAdoptNoIncrementTag>())), noexcept(SharedIntrusive<TT>(
std::declval<TT*>(), std::declval<SharedIntrusiveAdoptNoIncrementTag>())),
"SharedIntrusive constructor should not throw or this can leak " "SharedIntrusive constructor should not throw or this can leak "
"memory"); "memory");

View File

@@ -184,7 +184,8 @@ private:
/** Mask that will zero out everything except the weak count. /** Mask that will zero out everything except the weak count.
*/ */
static constexpr FieldType weakMask = (((one << WeakCountNumBits) - 1) << StrongCountNumBits) & valueMask; static constexpr FieldType weakMask =
(((one << WeakCountNumBits) - 1) << StrongCountNumBits) & valueMask;
/** Unpack the count and tag fields from the packed atomic integer form. */ /** Unpack the count and tag fields from the packed atomic integer form. */
struct RefCountPair struct RefCountPair
@@ -209,8 +210,10 @@ private:
FieldType FieldType
combinedValue() const noexcept; combinedValue() const noexcept;
static constexpr CountType maxStrongValue = static_cast<CountType>((one << StrongCountNumBits) - 1); static constexpr CountType maxStrongValue =
static constexpr CountType maxWeakValue = static_cast<CountType>((one << WeakCountNumBits) - 1); static_cast<CountType>((one << StrongCountNumBits) - 1);
static constexpr CountType maxWeakValue =
static_cast<CountType>((one << WeakCountNumBits) - 1);
/** Put an extra margin to detect when running up against limits. /** Put an extra margin to detect when running up against limits.
This is only used in debug code, and is useful if we reduce the This is only used in debug code, and is useful if we reduce the
number of bits in the strong and weak counts (to 16 and 14 bits). number of bits in the strong and weak counts (to 16 and 14 bits).
@@ -395,7 +398,8 @@ inline IntrusiveRefCounts::~IntrusiveRefCounts() noexcept
{ {
#ifndef NDEBUG #ifndef NDEBUG
auto v = refCounts.load(std::memory_order_acquire); auto v = refCounts.load(std::memory_order_acquire);
XRPL_ASSERT((!(v & valueMask)), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero"); XRPL_ASSERT(
(!(v & valueMask)), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero");
auto t = v & tagMask; auto t = v & tagMask;
XRPL_ASSERT((!t || t == tagMask), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag"); XRPL_ASSERT((!t || t == tagMask), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag");
#endif #endif
@@ -433,8 +437,10 @@ IntrusiveRefCounts::RefCountPair::combinedValue() const noexcept
(strong < checkStrongMaxValue && weak < checkWeakMaxValue), (strong < checkStrongMaxValue && weak < checkWeakMaxValue),
"xrpl::IntrusiveRefCounts::RefCountPair::combinedValue : inputs " "xrpl::IntrusiveRefCounts::RefCountPair::combinedValue : inputs "
"inside range"); "inside range");
return (static_cast<IntrusiveRefCounts::FieldType>(weak) << IntrusiveRefCounts::StrongCountNumBits) | return (static_cast<IntrusiveRefCounts::FieldType>(weak)
static_cast<IntrusiveRefCounts::FieldType>(strong) | partialDestroyStartedBit | partialDestroyFinishedBit; << IntrusiveRefCounts::StrongCountNumBits) |
static_cast<IntrusiveRefCounts::FieldType>(strong) | partialDestroyStartedBit |
partialDestroyFinishedBit;
} }
template <class T> template <class T>
@@ -442,7 +448,8 @@ inline void
partialDestructorFinished(T** o) partialDestructorFinished(T** o)
{ {
T& self = **o; T& self = **o;
IntrusiveRefCounts::RefCountPair p = self.refCounts.fetch_or(IntrusiveRefCounts::partialDestroyFinishedMask); IntrusiveRefCounts::RefCountPair p =
self.refCounts.fetch_or(IntrusiveRefCounts::partialDestroyFinishedMask);
XRPL_ASSERT( XRPL_ASSERT(
(!p.partialDestroyFinishedBit && p.partialDestroyStartedBit && !p.strong), (!p.partialDestroyFinishedBit && p.partialDestroyStartedBit && !p.strong),
"xrpl::partialDestructorFinished : not a weak ref"); "xrpl::partialDestructorFinished : not a weak ref");

View File

@@ -103,6 +103,7 @@ LocalValue<T>::operator*()
} }
return *reinterpret_cast<T*>( return *reinterpret_cast<T*>(
lvs->values.emplace(this, std::make_unique<detail::LocalValues::Value<T>>(t_)).first->second->get()); lvs->values.emplace(this, std::make_unique<detail::LocalValues::Value<T>>(t_))
.first->second->get());
} }
} // namespace xrpl } // namespace xrpl

View File

@@ -170,7 +170,11 @@ public:
partition_severities() const; partition_severities() const;
void void
write(beast::severities::Severity level, std::string const& partition, std::string const& text, bool console); write(
beast::severities::Severity level,
std::string const& partition,
std::string const& text,
bool console);
std::string std::string
rotate(); rotate();

View File

@@ -0,0 +1,73 @@
#pragma once
#include <xrpl/beast/utility/Journal.h>
#include <chrono>
#include <cstdint>
#include <string_view>
namespace xrpl {
// cSpell:ignore ptmalloc
// -----------------------------------------------------------------------------
// Allocator interaction note:
// - This facility invokes glibc's malloc_trim(0) on Linux/glibc to request that
// ptmalloc return free heap pages to the OS.
// - If an alternative allocator (e.g. jemalloc or tcmalloc) is linked or
// preloaded (LD_PRELOAD), calling glibc's malloc_trim typically has no effect
// on the *active* heap. The call is harmless but may not reclaim memory
// because those allocators manage their own arenas.
// - Only glibc sbrk/arena space is eligible for trimming; large mmap-backed
// allocations are usually returned to the OS on free regardless of trimming.
// - Call at known reclamation points (e.g., after cache sweeps / online delete)
// and consider rate limiting to avoid churn.
// -----------------------------------------------------------------------------
struct MallocTrimReport
{
bool supported{false};
int trimResult{-1};
std::int64_t rssBeforeKB{-1};
std::int64_t rssAfterKB{-1};
std::chrono::microseconds durationUs{-1};
std::int64_t minfltDelta{-1};
std::int64_t majfltDelta{-1};
[[nodiscard]] std::int64_t
deltaKB() const noexcept
{
if (rssBeforeKB < 0 || rssAfterKB < 0)
return 0;
return rssAfterKB - rssBeforeKB;
}
};
/**
* @brief Attempt to return freed memory to the operating system.
*
* On Linux with glibc malloc, this issues ::malloc_trim(0), which may release
* free space from ptmalloc arenas back to the kernel. On other platforms, or if
* a different allocator is in use, this function is a no-op and the report will
* indicate that trimming is unsupported or had no effect.
*
* @param tag Identifier for logging/debugging purposes.
* @param journal Journal for diagnostic logging.
* @return Report containing before/after metrics and the trim result.
*
* @note If an alternative allocator (jemalloc/tcmalloc) is linked or preloaded,
* calling glibc's malloc_trim may have no effect on the active heap. The
* call is harmless but typically does not reclaim memory under those
* allocators.
*
* @note Only memory served from glibc's sbrk/arena heaps is eligible for trim.
* Large allocations satisfied via mmap are usually returned on free
* independently of trimming.
*
* @note Intended for use after operations that free significant memory (e.g.,
* cache sweeps, ledger cleanup, online delete). Consider rate limiting.
*/
MallocTrimReport
mallocTrim(std::string_view tag, beast::Journal journal);
} // namespace xrpl

View File

@@ -240,7 +240,11 @@ public:
Number(rep mantissa); Number(rep mantissa);
explicit Number(rep mantissa, int exponent); explicit Number(rep mantissa, int exponent);
explicit constexpr Number(bool negative, internalrep mantissa, int exponent, unchecked) noexcept; explicit constexpr Number(
bool negative,
internalrep mantissa,
int exponent,
unchecked) noexcept;
// Assume unsigned values are... unsigned. i.e. positive // Assume unsigned values are... unsigned. i.e. positive
explicit constexpr Number(internalrep mantissa, int exponent, unchecked) noexcept; explicit constexpr Number(internalrep mantissa, int exponent, unchecked) noexcept;
// Only unit tests are expected to use this ctor // Only unit tests are expected to use this ctor
@@ -294,7 +298,8 @@ public:
friend constexpr bool friend constexpr bool
operator==(Number const& x, Number const& y) noexcept operator==(Number const& x, Number const& y) noexcept
{ {
return x.negative_ == y.negative_ && x.mantissa_ == y.mantissa_ && x.exponent_ == y.exponent_; return x.negative_ == y.negative_ && x.mantissa_ == y.mantissa_ &&
x.exponent_ == y.exponent_;
} }
friend constexpr bool friend constexpr bool
@@ -502,7 +507,11 @@ private:
class Guard; class Guard;
}; };
inline constexpr Number::Number(bool negative, internalrep mantissa, int exponent, unchecked) noexcept inline constexpr Number::Number(
bool negative,
internalrep mantissa,
int exponent,
unchecked) noexcept
: negative_(negative), mantissa_{mantissa}, exponent_{exponent} : negative_(negative), mantissa_{mantissa}, exponent_{exponent}
{ {
} }
@@ -520,7 +529,8 @@ inline Number::Number(bool negative, internalrep mantissa, int exponent, normali
normalize(); normalize();
} }
inline Number::Number(internalrep mantissa, int exponent, normalized) : Number(false, mantissa, exponent, normalized{}) inline Number::Number(internalrep mantissa, int exponent, normalized)
: Number(false, mantissa, exponent, normalized{})
{ {
} }
@@ -682,8 +692,8 @@ Number::isnormal() const noexcept
MantissaRange const& range = range_; MantissaRange const& range = range_;
auto const abs_m = mantissa_; auto const abs_m = mantissa_;
return *this == Number{} || return *this == Number{} ||
(range.min <= abs_m && abs_m <= range.max && (abs_m <= maxRep || abs_m % 10 == 0) && minExponent <= exponent_ && (range.min <= abs_m && abs_m <= range.max && (abs_m <= maxRep || abs_m % 10 == 0) &&
exponent_ <= maxExponent); minExponent <= exponent_ && exponent_ <= maxExponent);
} }
template <Integral64 T> template <Integral64 T>
@@ -695,7 +705,10 @@ Number::normalizeToRange(T minMantissa, T maxMantissa) const
int exponent = exponent_; int exponent = exponent_;
if constexpr (std::is_unsigned_v<T>) if constexpr (std::is_unsigned_v<T>)
XRPL_ASSERT_PARTS(!negative, "xrpl::Number::normalizeToRange", "Number is non-negative for unsigned range."); XRPL_ASSERT_PARTS(
!negative,
"xrpl::Number::normalizeToRange",
"Number is non-negative for unsigned range.");
Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa); Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa);
auto const sign = negative ? -1 : 1; auto const sign = negative ? -1 : 1;
@@ -781,7 +794,8 @@ class NumberRoundModeGuard
saveNumberRoundMode saved_; saveNumberRoundMode saved_;
public: public:
explicit NumberRoundModeGuard(Number::rounding_mode mode) noexcept : saved_{Number::setround(mode)} explicit NumberRoundModeGuard(Number::rounding_mode mode) noexcept
: saved_{Number::setround(mode)}
{ {
} }
@@ -801,7 +815,8 @@ class NumberMantissaScaleGuard
MantissaRange::mantissa_scale const saved_; MantissaRange::mantissa_scale const saved_;
public: public:
explicit NumberMantissaScaleGuard(MantissaRange::mantissa_scale scale) noexcept : saved_{Number::getMantissaScale()} explicit NumberMantissaScaleGuard(MantissaRange::mantissa_scale scale) noexcept
: saved_{Number::getMantissaScale()}
{ {
Number::setMantissaScale(scale); Number::setMantissaScale(scale);
} }

View File

@@ -19,7 +19,8 @@ SharedWeakCachePointer<T>::SharedWeakCachePointer(SharedWeakCachePointer&& rhs)
template <class T> template <class T>
template <class TT> template <class TT>
requires std::convertible_to<TT*, T*> requires std::convertible_to<TT*, T*>
SharedWeakCachePointer<T>::SharedWeakCachePointer(std::shared_ptr<TT>&& rhs) : combo_{std::move(rhs)} SharedWeakCachePointer<T>::SharedWeakCachePointer(std::shared_ptr<TT>&& rhs)
: combo_{std::move(rhs)}
{ {
} }

View File

@@ -155,13 +155,17 @@ public:
contexts (e.g. when minimal memory usage is needed) and contexts (e.g. when minimal memory usage is needed) and
allows for graceful failure. allows for graceful failure.
*/ */
constexpr explicit SlabAllocator(std::size_t extra, std::size_t alloc = 0, std::size_t align = 0) constexpr explicit SlabAllocator(
std::size_t extra,
std::size_t alloc = 0,
std::size_t align = 0)
: itemAlignment_(align ? align : alignof(Type)) : itemAlignment_(align ? align : alignof(Type))
, itemSize_(boost::alignment::align_up(sizeof(Type) + extra, itemAlignment_)) , itemSize_(boost::alignment::align_up(sizeof(Type) + extra, itemAlignment_))
, slabSize_(alloc) , slabSize_(alloc)
{ {
XRPL_ASSERT( XRPL_ASSERT(
(itemAlignment_ & (itemAlignment_ - 1)) == 0, "xrpl::SlabAllocator::SlabAllocator : valid alignment"); (itemAlignment_ & (itemAlignment_ - 1)) == 0,
"xrpl::SlabAllocator::SlabAllocator : valid alignment");
} }
SlabAllocator(SlabAllocator const& other) = delete; SlabAllocator(SlabAllocator const& other) = delete;
@@ -228,7 +232,8 @@ public:
// We need to carve out a bit of memory for the slab header // We need to carve out a bit of memory for the slab header
// and then align the rest appropriately: // and then align the rest appropriately:
auto slabData = reinterpret_cast<void*>(reinterpret_cast<std::uint8_t*>(buf) + sizeof(SlabBlock)); auto slabData =
reinterpret_cast<void*>(reinterpret_cast<std::uint8_t*>(buf) + sizeof(SlabBlock));
auto slabSize = size - sizeof(SlabBlock); auto slabSize = size - sizeof(SlabBlock);
// This operation is essentially guaranteed not to fail but // This operation is essentially guaranteed not to fail but
@@ -239,10 +244,12 @@ public:
return nullptr; return nullptr;
} }
slab = new (buf) SlabBlock(slabs_.load(), reinterpret_cast<std::uint8_t*>(slabData), slabSize, itemSize_); slab = new (buf) SlabBlock(
slabs_.load(), reinterpret_cast<std::uint8_t*>(slabData), slabSize, itemSize_);
// Link the new slab // Link the new slab
while (!slabs_.compare_exchange_weak(slab->next_, slab, std::memory_order_release, std::memory_order_relaxed)) while (!slabs_.compare_exchange_weak(
slab->next_, slab, std::memory_order_release, std::memory_order_relaxed))
{ {
; // Nothing to do ; // Nothing to do
} }
@@ -299,7 +306,10 @@ public:
std::size_t align; std::size_t align;
public: public:
constexpr SlabConfig(std::size_t extra_, std::size_t alloc_ = 0, std::size_t align_ = alignof(Type)) constexpr SlabConfig(
std::size_t extra_,
std::size_t alloc_ = 0,
std::size_t align_ = alignof(Type))
: extra(extra_), alloc(alloc_), align(align_) : extra(extra_), alloc(alloc_), align(align_)
{ {
} }
@@ -309,15 +319,18 @@ public:
{ {
// Ensure that the specified allocators are sorted from smallest to // Ensure that the specified allocators are sorted from smallest to
// largest by size: // largest by size:
std::sort( std::sort(std::begin(cfg), std::end(cfg), [](SlabConfig const& a, SlabConfig const& b) {
std::begin(cfg), std::end(cfg), [](SlabConfig const& a, SlabConfig const& b) { return a.extra < b.extra; }); return a.extra < b.extra;
});
// We should never have two slabs of the same size // We should never have two slabs of the same size
if (std::adjacent_find(std::begin(cfg), std::end(cfg), [](SlabConfig const& a, SlabConfig const& b) { if (std::adjacent_find(
return a.extra == b.extra; std::begin(cfg), std::end(cfg), [](SlabConfig const& a, SlabConfig const& b) {
}) != cfg.end()) return a.extra == b.extra;
}) != cfg.end())
{ {
throw std::runtime_error("SlabAllocatorSet<" + beast::type_name<Type>() + ">: duplicate slab size"); throw std::runtime_error(
"SlabAllocatorSet<" + beast::type_name<Type>() + ">: duplicate slab size");
} }
for (auto const& c : cfg) for (auto const& c : cfg)

View File

@@ -40,7 +40,8 @@ public:
operator=(Slice const&) noexcept = default; operator=(Slice const&) noexcept = default;
/** Create a slice pointing to existing memory. */ /** Create a slice pointing to existing memory. */
Slice(void const* data, std::size_t size) noexcept : data_(reinterpret_cast<std::uint8_t const*>(data)), size_(size) Slice(void const* data, std::size_t size) noexcept
: data_(reinterpret_cast<std::uint8_t const*>(data)), size_(size)
{ {
} }
@@ -197,7 +198,8 @@ operator!=(Slice const& lhs, Slice const& rhs) noexcept
inline bool inline bool
operator<(Slice const& lhs, Slice const& rhs) noexcept operator<(Slice const& lhs, Slice const& rhs) noexcept
{ {
return std::lexicographical_compare(lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size()); return std::lexicographical_compare(
lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size());
} }
template <class Stream> template <class Stream>

View File

@@ -108,7 +108,8 @@ struct parsedURL
bool bool
operator==(parsedURL const& other) const operator==(parsedURL const& other) const
{ {
return scheme == other.scheme && domain == other.domain && port == other.port && path == other.path; return scheme == other.scheme && domain == other.domain && port == other.port &&
path == other.path;
} }
}; };

View File

@@ -175,7 +175,10 @@ private:
struct Stats struct Stats
{ {
template <class Handler> template <class Handler>
Stats(std::string const& prefix, Handler const& handler, beast::insight::Collector::ptr const& collector) Stats(
std::string const& prefix,
Handler const& handler,
beast::insight::Collector::ptr const& collector)
: hook(collector->make_hook(handler)) : hook(collector->make_hook(handler))
, size(collector->make_gauge(prefix, "size")) , size(collector->make_gauge(prefix, "size"))
, hit_rate(collector->make_gauge(prefix, "hit_rate")) , hit_rate(collector->make_gauge(prefix, "hit_rate"))
@@ -197,7 +200,8 @@ private:
public: public:
clock_type::time_point last_access; clock_type::time_point last_access;
explicit KeyOnlyEntry(clock_type::time_point const& last_access_) : last_access(last_access_) explicit KeyOnlyEntry(clock_type::time_point const& last_access_)
: last_access(last_access_)
{ {
} }

View File

@@ -14,13 +14,22 @@ template <
class Hash, class Hash,
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::TaggedCache( inline TaggedCache<
std::string const& name, Key,
int size, T,
clock_type::duration expiration, IsKeyCache,
clock_type& clock, SharedWeakUnionPointer,
beast::Journal journal, SharedPointerType,
beast::insight::Collector::ptr const& collector) Hash,
KeyEqual,
Mutex>::
TaggedCache(
std::string const& name,
int size,
clock_type::duration expiration,
clock_type& clock,
beast::Journal journal,
beast::insight::Collector::ptr const& collector)
: m_journal(journal) : m_journal(journal)
, m_clock(clock) , m_clock(clock)
, m_stats(name, std::bind(&TaggedCache::collect_metrics, this), collector) , m_stats(name, std::bind(&TaggedCache::collect_metrics, this), collector)
@@ -43,8 +52,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline auto inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::clock() TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
-> clock_type& clock() -> clock_type&
{ {
return m_clock; return m_clock;
} }
@@ -59,7 +68,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline std::size_t inline std::size_t
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::size() const TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
size() const
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
return m_cache.size(); return m_cache.size();
@@ -75,7 +85,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline int inline int
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::getCacheSize() const TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
getCacheSize() const
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
return m_cache_count; return m_cache_count;
@@ -91,7 +102,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline int inline int
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::getTrackSize() const TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
getTrackSize() const
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
return m_cache.size(); return m_cache.size();
@@ -107,7 +119,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline float inline float
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::getHitRate() TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
getHitRate()
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
auto const total = static_cast<float>(m_hits + m_misses); auto const total = static_cast<float>(m_hits + m_misses);
@@ -124,7 +137,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline void inline void
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::clear() TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
clear()
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
m_cache.clear(); m_cache.clear();
@@ -141,7 +155,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline void inline void
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::reset() TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
reset()
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
m_cache.clear(); m_cache.clear();
@@ -161,8 +176,8 @@ template <
class Mutex> class Mutex>
template <class KeyComparable> template <class KeyComparable>
inline bool inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::touch_if_exists( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
KeyComparable const& key) touch_if_exists(KeyComparable const& key)
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
auto const iter(m_cache.find(key)); auto const iter(m_cache.find(key));
@@ -186,7 +201,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline void inline void
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::sweep() TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
sweep()
{ {
// Keep references to all the stuff we sweep // Keep references to all the stuff we sweep
// For performance, each worker thread should exit before the swept data // For performance, each worker thread should exit before the swept data
@@ -212,8 +228,9 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (when_expire > (now - minimumAge)) if (when_expire > (now - minimumAge))
when_expire = now - minimumAge; when_expire = now - minimumAge;
JLOG(m_journal.trace()) << m_name << " is growing fast " << m_cache.size() << " of " << m_target_size JLOG(m_journal.trace())
<< " aging at " << (now - when_expire).count() << " of " << m_target_age.count(); << m_name << " is growing fast " << m_cache.size() << " of " << m_target_size
<< " aging at " << (now - when_expire).count() << " of " << m_target_age.count();
} }
std::vector<std::thread> workers; std::vector<std::thread> workers;
@@ -222,7 +239,8 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
for (std::size_t p = 0; p < m_cache.partitions(); ++p) for (std::size_t p = 0; p < m_cache.partitions(); ++p)
{ {
workers.push_back(sweepHelper(when_expire, now, m_cache.map()[p], allStuffToSweep[p], allRemovals, lock)); workers.push_back(sweepHelper(
when_expire, now, m_cache.map()[p], allStuffToSweep[p], allRemovals, lock));
} }
for (std::thread& worker : workers) for (std::thread& worker : workers)
worker.join(); worker.join();
@@ -231,10 +249,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
} }
// At this point allStuffToSweep will go out of scope outside the lock // At this point allStuffToSweep will go out of scope outside the lock
// and decrement the reference count on each strong pointer. // and decrement the reference count on each strong pointer.
JLOG(m_journal.debug()) JLOG(m_journal.debug()) << m_name << " TaggedCache sweep lock duration "
<< m_name << " TaggedCache sweep lock duration " << std::chrono::duration_cast<std::chrono::milliseconds>(
<< std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count() std::chrono::steady_clock::now() - start)
<< "ms"; .count()
<< "ms";
} }
template < template <
@@ -247,9 +266,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline bool inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::del( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
key_type const& key, del(key_type const& key, bool valid)
bool valid)
{ {
// Remove from cache, if !valid, remove from map too. Returns true if // Remove from cache, if !valid, remove from map too. Returns true if
// removed from cache // removed from cache
@@ -288,10 +306,8 @@ template <
class Mutex> class Mutex>
template <class R> template <class R>
inline bool inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::canonicalize( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
key_type const& key, canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback)
SharedPointerType& data,
R&& replaceCallback)
{ {
// Return canonical value, store if needed, refresh in cache // Return canonical value, store if needed, refresh in cache
// Return values: true=we had the data already // Return values: true=we had the data already
@@ -302,7 +318,9 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (cit == m_cache.end()) if (cit == m_cache.end())
{ {
m_cache.emplace( m_cache.emplace(
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(m_clock.now(), data)); std::piecewise_construct,
std::forward_as_tuple(key),
std::forward_as_tuple(m_clock.now(), data));
++m_cache_count; ++m_cache_count;
return false; return false;
} }
@@ -404,8 +422,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline SharedPointerType inline SharedPointerType
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::fetch( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
key_type const& key) fetch(key_type const& key)
{ {
std::lock_guard<mutex_type> l(m_mutex); std::lock_guard<mutex_type> l(m_mutex);
auto ret = initialFetch(key, l); auto ret = initialFetch(key, l);
@@ -425,9 +443,8 @@ template <
class Mutex> class Mutex>
template <class ReturnType> template <class ReturnType>
inline auto inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::insert( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
key_type const& key, insert(key_type const& key, T const& value) -> std::enable_if_t<!IsKeyCache, ReturnType>
T const& value) -> std::enable_if_t<!IsKeyCache, ReturnType>
{ {
static_assert( static_assert(
std::is_same_v<std::shared_ptr<T>, SharedPointerType> || std::is_same_v<std::shared_ptr<T>, SharedPointerType> ||
@@ -456,13 +473,13 @@ template <
class Mutex> class Mutex>
template <class ReturnType> template <class ReturnType>
inline auto inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::insert( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
key_type const& key) -> std::enable_if_t<IsKeyCache, ReturnType> insert(key_type const& key) -> std::enable_if_t<IsKeyCache, ReturnType>
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
clock_type::time_point const now(m_clock.now()); clock_type::time_point const now(m_clock.now());
auto [it, inserted] = auto [it, inserted] = m_cache.emplace(
m_cache.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(now)); std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(now));
if (!inserted) if (!inserted)
it->second.last_access = now; it->second.last_access = now;
return inserted; return inserted;
@@ -478,9 +495,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline bool inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::retrieve( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
key_type const& key, retrieve(key_type const& key, T& data)
T& data)
{ {
// retrieve the value of the stored data // retrieve the value of the stored data
auto entry = fetch(key); auto entry = fetch(key);
@@ -502,8 +518,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline auto inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::peekMutex() TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
-> mutex_type& peekMutex() -> mutex_type&
{ {
return m_mutex; return m_mutex;
} }
@@ -518,8 +534,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline auto inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::getKeys() const TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
-> std::vector<key_type> getKeys() const -> std::vector<key_type>
{ {
std::vector<key_type> v; std::vector<key_type> v;
@@ -543,7 +559,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline double inline double
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::rate() const TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
rate() const
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
auto const tot = m_hits + m_misses; auto const tot = m_hits + m_misses;
@@ -563,9 +580,8 @@ template <
class Mutex> class Mutex>
template <class Handler> template <class Handler>
inline SharedPointerType inline SharedPointerType
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::fetch( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
key_type const& digest, fetch(key_type const& digest, Handler const& h)
Handler const& h)
{ {
{ {
std::lock_guard l(m_mutex); std::lock_guard l(m_mutex);
@@ -596,9 +612,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline SharedPointerType inline SharedPointerType
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::initialFetch( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
key_type const& key, initialFetch(key_type const& key, std::lock_guard<mutex_type> const& l)
std::lock_guard<mutex_type> const& l)
{ {
auto cit = m_cache.find(key); auto cit = m_cache.find(key);
if (cit == m_cache.end()) if (cit == m_cache.end())
@@ -634,7 +649,8 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline void inline void
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::collect_metrics() TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
collect_metrics()
{ {
m_stats.size.set(getCacheSize()); m_stats.size.set(getCacheSize());
@@ -660,13 +676,14 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline std::thread inline std::thread
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::sweepHelper( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
clock_type::time_point const& when_expire, sweepHelper(
[[maybe_unused]] clock_type::time_point const& now, clock_type::time_point const& when_expire,
typename KeyValueCacheType::map_type& partition, [[maybe_unused]] clock_type::time_point const& now,
SweptPointersVector& stuffToSweep, typename KeyValueCacheType::map_type& partition,
std::atomic<int>& allRemovals, SweptPointersVector& stuffToSweep,
std::lock_guard<std::recursive_mutex> const&) std::atomic<int>& allRemovals,
std::lock_guard<std::recursive_mutex> const&)
{ {
return std::thread([&, this]() { return std::thread([&, this]() {
int cacheRemovals = 0; int cacheRemovals = 0;
@@ -720,8 +737,9 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (mapRemovals || cacheRemovals) if (mapRemovals || cacheRemovals)
{ {
JLOG(m_journal.debug()) << "TaggedCache partition sweep " << m_name << ": cache = " << partition.size() JLOG(m_journal.debug())
<< "-" << cacheRemovals << ", map-=" << mapRemovals; << "TaggedCache partition sweep " << m_name << ": cache = " << partition.size()
<< "-" << cacheRemovals << ", map-=" << mapRemovals;
} }
allRemovals += cacheRemovals; allRemovals += cacheRemovals;
@@ -738,13 +756,14 @@ template <
class KeyEqual, class KeyEqual,
class Mutex> class Mutex>
inline std::thread inline std::thread
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::sweepHelper( TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
clock_type::time_point const& when_expire, sweepHelper(
clock_type::time_point const& now, clock_type::time_point const& when_expire,
typename KeyOnlyCacheType::map_type& partition, clock_type::time_point const& now,
SweptPointersVector&, typename KeyOnlyCacheType::map_type& partition,
std::atomic<int>& allRemovals, SweptPointersVector&,
std::lock_guard<std::recursive_mutex> const&) std::atomic<int>& allRemovals,
std::lock_guard<std::recursive_mutex> const&)
{ {
return std::thread([&, this]() { return std::thread([&, this]() {
int cacheRemovals = 0; int cacheRemovals = 0;
@@ -774,8 +793,9 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (mapRemovals || cacheRemovals) if (mapRemovals || cacheRemovals)
{ {
JLOG(m_journal.debug()) << "TaggedCache partition sweep " << m_name << ": cache = " << partition.size() JLOG(m_journal.debug())
<< "-" << cacheRemovals << ", map-=" << mapRemovals; << "TaggedCache partition sweep " << m_name << ": cache = " << partition.size()
<< "-" << cacheRemovals << ", map-=" << mapRemovals;
} }
allRemovals += cacheRemovals; allRemovals += cacheRemovals;

View File

@@ -51,7 +51,13 @@ generalized_set_intersection(
// std::set_intersection. // std::set_intersection.
template <class FwdIter1, class InputIter2, class Pred, class Comp> template <class FwdIter1, class InputIter2, class Pred, class Comp>
FwdIter1 FwdIter1
remove_if_intersect_or_match(FwdIter1 first1, FwdIter1 last1, InputIter2 first2, InputIter2 last2, Pred pred, Comp comp) remove_if_intersect_or_match(
FwdIter1 first1,
FwdIter1 last1,
InputIter2 first2,
InputIter2 last2,
Pred pred,
Comp comp)
{ {
// [original-first1, current-first1) is the set of elements to be preserved. // [original-first1, current-first1) is the set of elements to be preserved.
// [current-first1, i) is the set of elements that have been removed. // [current-first1, i) is the set of elements that have been removed.

View File

@@ -214,7 +214,8 @@ private:
std::uint32_t accum = {}; std::uint32_t accum = {};
for (std::uint32_t shift : {4u, 0u, 12u, 8u, 20u, 16u, 28u, 24u}) for (std::uint32_t shift : {4u, 0u, 12u, 8u, 20u, 16u, 28u, 24u})
{ {
if (auto const result = hexCharToUInt(*in++, shift, accum); result != ParseResult::okay) if (auto const result = hexCharToUInt(*in++, shift, accum);
result != ParseResult::okay)
return Unexpected(result); return Unexpected(result);
} }
ret[i++] = accum; ret[i++] = accum;
@@ -253,7 +254,8 @@ public:
// This constructor is intended to be used at compile time since it might // This constructor is intended to be used at compile time since it might
// throw at runtime. Consider declaring this constructor consteval once // throw at runtime. Consider declaring this constructor consteval once
// we get to C++23. // we get to C++23.
explicit constexpr base_uint(std::string_view sv) noexcept(false) : data_(parseFromStringViewThrows(sv)) explicit constexpr base_uint(std::string_view sv) noexcept(false)
: data_(parseFromStringViewThrows(sv))
{ {
} }
@@ -442,7 +444,8 @@ public:
for (int i = WIDTH; i--;) for (int i = WIDTH; i--;)
{ {
std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) + boost::endian::big_to_native(b.data_[i]); std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) +
boost::endian::big_to_native(b.data_[i]);
data_[i] = boost::endian::native_to_big(static_cast<std::uint32_t>(n)); data_[i] = boost::endian::native_to_big(static_cast<std::uint32_t>(n));
carry = n >> 32; carry = n >> 32;

View File

@@ -15,7 +15,8 @@ namespace xrpl {
// A few handy aliases // A few handy aliases
using days = std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>>; using days =
std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>>;
using weeks = std::chrono::duration<int, std::ratio_multiply<days::period, std::ratio<7>>>; using weeks = std::chrono::duration<int, std::ratio_multiply<days::period, std::ratio<7>>>;

View File

@@ -35,7 +35,9 @@ template <class E, class... Args>
[[noreturn]] inline void [[noreturn]] inline void
Throw(Args&&... args) Throw(Args&&... args)
{ {
static_assert(std::is_convertible<E*, std::exception*>::value, "Exception must derive from std::exception."); static_assert(
std::is_convertible<E*, std::exception*>::value,
"Exception must derive from std::exception.");
E e(std::forward<Args>(args)...); E e(std::forward<Args>(args)...);
LogThrow(std::string("Throwing exception of type " + beast::type_name<E>() + ": ") + e.what()); LogThrow(std::string("Throwing exception of type " + beast::type_name<E>() + ": ") + e.what());

View File

@@ -23,7 +23,8 @@ public:
Collection const& collection; Collection const& collection;
std::string const delimiter; std::string const delimiter;
explicit CollectionAndDelimiter(Collection const& c, std::string delim) : collection(c), delimiter(std::move(delim)) explicit CollectionAndDelimiter(Collection const& c, std::string delim)
: collection(c), delimiter(std::move(delim))
{ {
} }
@@ -63,7 +64,8 @@ public:
char const* collection; char const* collection;
std::string const delimiter; std::string const delimiter;
explicit CollectionAndDelimiter(char const c[N], std::string delim) : collection(c), delimiter(std::move(delim)) explicit CollectionAndDelimiter(char const c[N], std::string delim)
: collection(c), delimiter(std::move(delim))
{ {
} }

View File

@@ -330,8 +330,8 @@ public:
auto const& key = std::get<0>(keyTuple); auto const& key = std::get<0>(keyTuple);
iterator it(&map_); iterator it(&map_);
it.ait_ = it.map_->begin() + partitioner(key); it.ait_ = it.map_->begin() + partitioner(key);
auto [eit, inserted] = auto [eit, inserted] = it.ait_->emplace(
it.ait_->emplace(std::piecewise_construct, std::forward<T>(keyTuple), std::forward<U>(valueTuple)); std::piecewise_construct, std::forward<T>(keyTuple), std::forward<U>(valueTuple));
it.mit_ = eit; it.mit_ = eit;
return {it, inserted}; return {it, inserted};
} }

View File

@@ -19,7 +19,8 @@ static_assert(
"The Ripple default PRNG engine must return an unsigned integral type."); "The Ripple default PRNG engine must return an unsigned integral type.");
static_assert( static_assert(
std::numeric_limits<beast::xor_shift_engine::result_type>::max() >= std::numeric_limits<std::uint64_t>::max(), std::numeric_limits<beast::xor_shift_engine::result_type>::max() >=
std::numeric_limits<std::uint64_t>::max(),
"The Ripple default PRNG engine return must be at least 64 bits wide."); "The Ripple default PRNG engine return must be at least 64 bits wide.");
#endif #endif
@@ -144,12 +145,14 @@ std::enable_if_t<
Byte> Byte>
rand_byte(Engine& engine) rand_byte(Engine& engine)
{ {
return static_cast<Byte>( return static_cast<Byte>(rand_int<Engine, std::uint32_t>(
rand_int<Engine, std::uint32_t>(engine, std::numeric_limits<Byte>::min(), std::numeric_limits<Byte>::max())); engine, std::numeric_limits<Byte>::min(), std::numeric_limits<Byte>::max()));
} }
template <class Byte = std::uint8_t> template <class Byte = std::uint8_t>
std::enable_if_t<(std::is_same<Byte, unsigned char>::value || std::is_same<Byte, std::uint8_t>::value), Byte> std::enable_if_t<
(std::is_same<Byte, unsigned char>::value || std::is_same<Byte, std::uint8_t>::value),
Byte>
rand_byte() rand_byte()
{ {
return rand_byte<Byte>(default_prng()); return rand_byte<Byte>(default_prng());

View File

@@ -18,9 +18,12 @@ template <class Dest, class Src>
inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest> inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
safe_cast(Src s) noexcept safe_cast(Src s) noexcept
{ {
static_assert(std::is_signed_v<Dest> || std::is_unsigned_v<Src>, "Cannot cast signed to unsigned"); static_assert(
std::is_signed_v<Dest> || std::is_unsigned_v<Src>, "Cannot cast signed to unsigned");
constexpr unsigned not_same = std::is_signed_v<Dest> != std::is_signed_v<Src>; constexpr unsigned not_same = std::is_signed_v<Dest> != std::is_signed_v<Src>;
static_assert(sizeof(Dest) >= sizeof(Src) + not_same, "Destination is too small to hold all values of source"); static_assert(
sizeof(Dest) >= sizeof(Src) + not_same,
"Destination is too small to hold all values of source");
return static_cast<Dest>(s); return static_cast<Dest>(s);
} }

View File

@@ -36,7 +36,8 @@ public:
scope_exit(scope_exit&& rhs) noexcept( scope_exit(scope_exit&& rhs) noexcept(
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>) std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
: exit_function_{std::forward<EF>(rhs.exit_function_)}, execute_on_destruction_{rhs.execute_on_destruction_} : exit_function_{std::forward<EF>(rhs.exit_function_)}
, execute_on_destruction_{rhs.execute_on_destruction_}
{ {
rhs.release(); rhs.release();
} }
@@ -47,8 +48,9 @@ public:
template <class EFP> template <class EFP>
explicit scope_exit( explicit scope_exit(
EFP&& f, EFP&& f,
std::enable_if_t<!std::is_same_v<std::remove_cv_t<EFP>, scope_exit> && std::is_constructible_v<EF, EFP>>* = std::enable_if_t<
0) noexcept !std::is_same_v<std::remove_cv_t<EFP>, scope_exit> &&
std::is_constructible_v<EF, EFP>>* = 0) noexcept
: exit_function_{std::forward<EFP>(f)} : exit_function_{std::forward<EFP>(f)}
{ {
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>); static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
@@ -93,8 +95,9 @@ public:
template <class EFP> template <class EFP>
explicit scope_fail( explicit scope_fail(
EFP&& f, EFP&& f,
std::enable_if_t<!std::is_same_v<std::remove_cv_t<EFP>, scope_fail> && std::is_constructible_v<EF, EFP>>* = std::enable_if_t<
0) noexcept !std::is_same_v<std::remove_cv_t<EFP>, scope_fail> &&
std::is_constructible_v<EF, EFP>>* = 0) noexcept
: exit_function_{std::forward<EFP>(f)} : exit_function_{std::forward<EFP>(f)}
{ {
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>); static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
@@ -139,7 +142,9 @@ public:
template <class EFP> template <class EFP>
explicit scope_success( explicit scope_success(
EFP&& f, EFP&& f,
std::enable_if_t<!std::is_same_v<std::remove_cv_t<EFP>, scope_success> && std::is_constructible_v<EF, EFP>>* = std::enable_if_t<
!std::is_same_v<std::remove_cv_t<EFP>, scope_success> &&
std::is_constructible_v<EF, EFP>>* =
0) noexcept(std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>) 0) noexcept(std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
: exit_function_{std::forward<EFP>(f)} : exit_function_{std::forward<EFP>(f)}
{ {

View File

@@ -99,9 +99,12 @@ public:
@note For performance reasons, you should strive to have `lock` be @note For performance reasons, you should strive to have `lock` be
on a cacheline by itself. on a cacheline by itself.
*/ */
packed_spinlock(std::atomic<T>& lock, int index) : bits_(lock), mask_(static_cast<T>(1) << index) packed_spinlock(std::atomic<T>& lock, int index)
: bits_(lock), mask_(static_cast<T>(1) << index)
{ {
XRPL_ASSERT(index >= 0 && (mask_ != 0), "xrpl::packed_spinlock::packed_spinlock : valid index and mask"); XRPL_ASSERT(
index >= 0 && (mask_ != 0),
"xrpl::packed_spinlock::packed_spinlock : valid index and mask");
} }
[[nodiscard]] bool [[nodiscard]] bool
@@ -174,7 +177,10 @@ public:
T expected = 0; T expected = 0;
return lock_.compare_exchange_weak( return lock_.compare_exchange_weak(
expected, std::numeric_limits<T>::max(), std::memory_order_acquire, std::memory_order_relaxed); expected,
std::numeric_limits<T>::max(),
std::memory_order_acquire,
std::memory_order_relaxed);
} }
void void

View File

@@ -10,7 +10,9 @@ std::string
strHex(FwdIt begin, FwdIt end) strHex(FwdIt begin, FwdIt end)
{ {
static_assert( static_assert(
std::is_convertible<typename std::iterator_traits<FwdIt>::iterator_category, std::forward_iterator_tag>::value, std::is_convertible<
typename std::iterator_traits<FwdIt>::iterator_category,
std::forward_iterator_tag>::value,
"FwdIt must be a forward iterator"); "FwdIt must be a forward iterator");
std::string result; std::string result;
result.reserve(2 * std::distance(begin, end)); result.reserve(2 * std::distance(begin, end));

View File

@@ -23,14 +23,15 @@ namespace xrpl {
allowed arithmetic operations. allowed arithmetic operations.
*/ */
template <class Int, class Tag> template <class Int, class Tag>
class tagged_integer class tagged_integer : boost::totally_ordered<
: boost::totally_ordered< tagged_integer<Int, Tag>,
tagged_integer<Int, Tag>, boost::integer_arithmetic<
boost::integer_arithmetic< tagged_integer<Int, Tag>,
tagged_integer<Int, Tag>, boost::bitwise<
boost::bitwise< tagged_integer<Int, Tag>,
tagged_integer<Int, Tag>, boost::unit_steppable<
boost::unit_steppable<tagged_integer<Int, Tag>, boost::shiftable<tagged_integer<Int, Tag>>>>>> tagged_integer<Int, Tag>,
boost::shiftable<tagged_integer<Int, Tag>>>>>>
{ {
private: private:
Int m_value; Int m_value;
@@ -43,7 +44,8 @@ public:
template < template <
class OtherInt, class OtherInt,
class = typename std::enable_if<std::is_integral<OtherInt>::value && sizeof(OtherInt) <= sizeof(Int)>::type> class = typename std::enable_if<
std::is_integral<OtherInt>::value && sizeof(OtherInt) <= sizeof(Int)>::type>
explicit constexpr tagged_integer(OtherInt value) noexcept : m_value(value) explicit constexpr tagged_integer(OtherInt value) noexcept : m_value(value)
{ {
static_assert(sizeof(tagged_integer) == sizeof(Int), "tagged_integer is adding padding"); static_assert(sizeof(tagged_integer) == sizeof(Int), "tagged_integer is adding padding");

View File

@@ -86,7 +86,8 @@ public:
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
if (m_cancel) if (m_cancel)
throw std::logic_error("io_latency_probe is canceled"); throw std::logic_error("io_latency_probe is canceled");
boost::asio::post(m_ios, sample_op<Handler>(std::forward<Handler>(handler), Clock::now(), false, this)); boost::asio::post(
m_ios, sample_op<Handler>(std::forward<Handler>(handler), Clock::now(), false, this));
} }
/** Initiate continuous i/o latency sampling. /** Initiate continuous i/o latency sampling.
@@ -100,7 +101,8 @@ public:
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
if (m_cancel) if (m_cancel)
throw std::logic_error("io_latency_probe is canceled"); throw std::logic_error("io_latency_probe is canceled");
boost::asio::post(m_ios, sample_op<Handler>(std::forward<Handler>(handler), Clock::now(), true, this)); boost::asio::post(
m_ios, sample_op<Handler>(std::forward<Handler>(handler), Clock::now(), true, this));
} }
private: private:
@@ -140,7 +142,11 @@ private:
bool m_repeat; bool m_repeat;
io_latency_probe* m_probe; io_latency_probe* m_probe;
sample_op(Handler const& handler, time_point const& start, bool repeat, io_latency_probe* probe) sample_op(
Handler const& handler,
time_point const& start,
bool repeat,
io_latency_probe* probe)
: m_handler(handler), m_start(start), m_repeat(repeat), m_probe(probe) : m_handler(handler), m_start(start), m_repeat(repeat), m_probe(probe)
{ {
XRPL_ASSERT( XRPL_ASSERT(
@@ -203,12 +209,14 @@ private:
// The latency is too high to maintain the desired // The latency is too high to maintain the desired
// period so don't bother with a timer. // period so don't bother with a timer.
// //
boost::asio::post(m_probe->m_ios, sample_op<Handler>(m_handler, now, m_repeat, m_probe)); boost::asio::post(
m_probe->m_ios, sample_op<Handler>(m_handler, now, m_repeat, m_probe));
} }
else else
{ {
m_probe->m_timer.expires_after(when - now); m_probe->m_timer.expires_after(when - now);
m_probe->m_timer.async_wait(sample_op<Handler>(m_handler, now, m_repeat, m_probe)); m_probe->m_timer.async_wait(
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
} }
} }
} }
@@ -219,7 +227,8 @@ private:
if (!m_probe) if (!m_probe)
return; return;
typename Clock::time_point const now(Clock::now()); typename Clock::time_point const now(Clock::now());
boost::asio::post(m_probe->m_ios, sample_op<Handler>(m_handler, now, m_repeat, m_probe)); boost::asio::post(
m_probe->m_ios, sample_op<Handler>(m_handler, now, m_repeat, m_probe));
} }
}; };
}; };

View File

@@ -42,7 +42,9 @@ public:
void void
set(time_point const& when) set(time_point const& when)
{ {
XRPL_ASSERT(!Clock::is_steady || when >= now_, "beast::manual_clock::set(time_point) : forward input"); XRPL_ASSERT(
!Clock::is_steady || when >= now_,
"beast::manual_clock::set(time_point) : forward input");
now_ = when; now_ = when;
} }
@@ -60,7 +62,8 @@ public:
advance(std::chrono::duration<Rep, Period> const& elapsed) advance(std::chrono::duration<Rep, Period> const& elapsed)
{ {
XRPL_ASSERT( XRPL_ASSERT(
!Clock::is_steady || (now_ + elapsed) >= now_, "beast::manual_clock::advance(duration) : forward input"); !Clock::is_steady || (now_ + elapsed) >= now_,
"beast::manual_clock::advance(duration) : forward input");
now_ += elapsed; now_ += elapsed;
} }

View File

@@ -14,7 +14,8 @@ expire(AgedContainer& c, std::chrono::duration<Rep, Period> const& age)
{ {
std::size_t n(0); std::size_t n(0);
auto const expired(c.clock().now() - age); auto const expired(c.clock().now() - age);
for (auto iter(c.chronological.cbegin()); iter != c.chronological.cend() && iter.when() <= expired;) for (auto iter(c.chronological.cbegin());
iter != c.chronological.cend() && iter.when() <= expired;)
{ {
iter = c.erase(iter); iter = c.erase(iter);
++n; ++n;

View File

@@ -13,6 +13,6 @@ template <
class Clock = std::chrono::steady_clock, class Clock = std::chrono::steady_clock,
class Compare = std::less<Key>, class Compare = std::less<Key>,
class Allocator = std::allocator<Key>> class Allocator = std::allocator<Key>>
using aged_multiset = detail::aged_ordered_container<true, false, Key, void, Clock, Compare, Allocator>; using aged_multiset =
detail::aged_ordered_container<true, false, Key, void, Clock, Compare, Allocator>;
} }

View File

@@ -15,6 +15,6 @@ template <
class Hash = std::hash<Key>, class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>, class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T>>> class Allocator = std::allocator<std::pair<Key const, T>>>
using aged_unordered_map = detail::aged_unordered_container<false, true, Key, T, Clock, Hash, KeyEqual, Allocator>; using aged_unordered_map =
detail::aged_unordered_container<false, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
} }

View File

@@ -15,6 +15,6 @@ template <
class Hash = std::hash<Key>, class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>, class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T>>> class Allocator = std::allocator<std::pair<Key const, T>>>
using aged_unordered_multimap = detail::aged_unordered_container<true, true, Key, T, Clock, Hash, KeyEqual, Allocator>; using aged_unordered_multimap =
detail::aged_unordered_container<true, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
} }

View File

@@ -14,6 +14,6 @@ template <
class Hash = std::hash<Key>, class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>, class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key>> class Allocator = std::allocator<Key>>
using aged_unordered_set = detail::aged_unordered_container<false, false, Key, void, Clock, Hash, KeyEqual, Allocator>; using aged_unordered_set =
detail::aged_unordered_container<false, false, Key, void, Clock, Hash, KeyEqual, Allocator>;
} }

View File

@@ -35,22 +35,26 @@ public:
class = typename std::enable_if< class = typename std::enable_if<
(other_is_const == false || is_const == true) && (other_is_const == false || is_const == true) &&
std::is_same<Iterator, OtherIterator>::value == false>::type> std::is_same<Iterator, OtherIterator>::value == false>::type>
explicit aged_container_iterator(aged_container_iterator<other_is_const, OtherIterator> const& other) explicit aged_container_iterator(
aged_container_iterator<other_is_const, OtherIterator> const& other)
: m_iter(other.m_iter) : m_iter(other.m_iter)
{ {
} }
// Disable constructing a const_iterator from a non-const_iterator. // Disable constructing a const_iterator from a non-const_iterator.
template <bool other_is_const, class = typename std::enable_if<other_is_const == false || is_const == true>::type> template <
aged_container_iterator(aged_container_iterator<other_is_const, Iterator> const& other) : m_iter(other.m_iter) bool other_is_const,
class = typename std::enable_if<other_is_const == false || is_const == true>::type>
aged_container_iterator(aged_container_iterator<other_is_const, Iterator> const& other)
: m_iter(other.m_iter)
{ {
} }
// Disable assigning a const_iterator to a non-const iterator // Disable assigning a const_iterator to a non-const iterator
template <bool other_is_const, class OtherIterator> template <bool other_is_const, class OtherIterator>
auto auto
operator=(aged_container_iterator<other_is_const, OtherIterator> const& other) -> operator=(aged_container_iterator<other_is_const, OtherIterator> const& other) -> typename std::
typename std::enable_if<other_is_const == false || is_const == true, aged_container_iterator&>::type enable_if<other_is_const == false || is_const == true, aged_container_iterator&>::type
{ {
m_iter = other.m_iter; m_iter = other.m_iter;
return *this; return *this;

View File

@@ -57,7 +57,8 @@ template <
class T, class T,
class Clock = std::chrono::steady_clock, class Clock = std::chrono::steady_clock,
class Compare = std::less<Key>, class Compare = std::less<Key>,
class Allocator = std::allocator<typename std::conditional<IsMap, std::pair<Key const, T>, Key>::type>> class Allocator =
std::allocator<typename std::conditional<IsMap, std::pair<Key const, T>, Key>::type>>
class aged_ordered_container class aged_ordered_container
{ {
public: public:
@@ -83,8 +84,10 @@ private:
} }
// VFALCO TODO hoist to remove template argument dependencies // VFALCO TODO hoist to remove template argument dependencies
struct element : boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>, struct element : boost::intrusive::set_base_hook<
boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> boost::intrusive::link_mode<boost::intrusive::normal_link>>,
boost::intrusive::list_base_hook<
boost::intrusive::link_mode<boost::intrusive::normal_link>>
{ {
// Stash types here so the iterator doesn't // Stash types here so the iterator doesn't
// need to see the container declaration. // need to see the container declaration.
@@ -100,14 +103,17 @@ private:
{ {
} }
element(time_point const& when_, value_type&& value_) : value(std::move(value_)), when(when_) element(time_point const& when_, value_type&& value_)
: value(std::move(value_)), when(when_)
{ {
} }
template < template <
class... Args, class... Args,
class = typename std::enable_if<std::is_constructible<value_type, Args...>::value>::type> class =
element(time_point const& when_, Args&&... args) : value(std::forward<Args>(args)...), when(when_) typename std::enable_if<std::is_constructible<value_type, Args...>::value>::type>
element(time_point const& when_, Args&&... args)
: value(std::forward<Args>(args)...), when(when_)
{ {
} }
@@ -191,7 +197,8 @@ private:
} }
}; };
using list_type = typename boost::intrusive::make_list<element, boost::intrusive::constant_time_size<false>>::type; using list_type = typename boost::intrusive::
make_list<element, boost::intrusive::constant_time_size<false>>::type;
using cont_type = typename std::conditional< using cont_type = typename std::conditional<
IsMulti, IsMulti,
@@ -199,15 +206,18 @@ private:
element, element,
boost::intrusive::constant_time_size<true>, boost::intrusive::constant_time_size<true>,
boost::intrusive::compare<KeyValueCompare>>::type, boost::intrusive::compare<KeyValueCompare>>::type,
typename boost::intrusive:: typename boost::intrusive::make_set<
make_set<element, boost::intrusive::constant_time_size<true>, boost::intrusive::compare<KeyValueCompare>>:: element,
type>::type; boost::intrusive::constant_time_size<true>,
boost::intrusive::compare<KeyValueCompare>>::type>::type;
using ElementAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<element>; using ElementAllocator =
typename std::allocator_traits<Allocator>::template rebind_alloc<element>;
using ElementAllocatorTraits = std::allocator_traits<ElementAllocator>; using ElementAllocatorTraits = std::allocator_traits<ElementAllocator>;
class config_t : private KeyValueCompare, public beast::detail::empty_base_optimization<ElementAllocator> class config_t : private KeyValueCompare,
public beast::detail::empty_base_optimization<ElementAllocator>
{ {
public: public:
explicit config_t(clock_type& clock_) : clock(clock_) explicit config_t(clock_type& clock_) : clock(clock_)
@@ -224,7 +234,9 @@ private:
} }
config_t(clock_type& clock_, Compare const& comp, Allocator const& alloc_) config_t(clock_type& clock_, Compare const& comp, Allocator const& alloc_)
: KeyValueCompare(comp), beast::detail::empty_base_optimization<ElementAllocator>(alloc_), clock(clock_) : KeyValueCompare(comp)
, beast::detail::empty_base_optimization<ElementAllocator>(alloc_)
, clock(clock_)
{ {
} }
@@ -337,7 +349,8 @@ private:
std::unique_ptr<element, Deleter> p( std::unique_ptr<element, Deleter> p(
ElementAllocatorTraits::allocate(m_config.alloc(), 1), Deleter(m_config.alloc())); ElementAllocatorTraits::allocate(m_config.alloc(), 1), Deleter(m_config.alloc()));
ElementAllocatorTraits::construct(m_config.alloc(), p.get(), clock().now(), std::forward<Args>(args)...); ElementAllocatorTraits::construct(
m_config.alloc(), p.get(), clock().now(), std::forward<Args>(args)...);
return p.release(); return p.release();
} }
@@ -368,9 +381,12 @@ public:
// A set iterator (IsMap==false) is always const // A set iterator (IsMap==false) is always const
// because the elements of a set are immutable. // because the elements of a set are immutable.
using iterator = beast::detail::aged_container_iterator<!IsMap, typename cont_type::iterator>; using iterator = beast::detail::aged_container_iterator<!IsMap, typename cont_type::iterator>;
using const_iterator = beast::detail::aged_container_iterator<true, typename cont_type::iterator>; using const_iterator =
using reverse_iterator = beast::detail::aged_container_iterator<!IsMap, typename cont_type::reverse_iterator>; beast::detail::aged_container_iterator<true, typename cont_type::iterator>;
using const_reverse_iterator = beast::detail::aged_container_iterator<true, typename cont_type::reverse_iterator>; using reverse_iterator =
beast::detail::aged_container_iterator<!IsMap, typename cont_type::reverse_iterator>;
using const_reverse_iterator =
beast::detail::aged_container_iterator<true, typename cont_type::reverse_iterator>;
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// //
@@ -386,9 +402,12 @@ public:
public: public:
// A set iterator (IsMap==false) is always const // A set iterator (IsMap==false) is always const
// because the elements of a set are immutable. // because the elements of a set are immutable.
using iterator = beast::detail::aged_container_iterator<!IsMap, typename list_type::iterator>; using iterator =
using const_iterator = beast::detail::aged_container_iterator<true, typename list_type::iterator>; beast::detail::aged_container_iterator<!IsMap, typename list_type::iterator>;
using reverse_iterator = beast::detail::aged_container_iterator<!IsMap, typename list_type::reverse_iterator>; using const_iterator =
beast::detail::aged_container_iterator<true, typename list_type::iterator>;
using reverse_iterator =
beast::detail::aged_container_iterator<!IsMap, typename list_type::reverse_iterator>;
using const_reverse_iterator = using const_reverse_iterator =
beast::detail::aged_container_iterator<true, typename list_type::reverse_iterator>; beast::detail::aged_container_iterator<true, typename list_type::reverse_iterator>;
@@ -469,7 +488,8 @@ public:
{ {
static_assert(std::is_standard_layout<element>::value, "must be standard layout"); static_assert(std::is_standard_layout<element>::value, "must be standard layout");
return list.iterator_to(*reinterpret_cast<element*>( return list.iterator_to(*reinterpret_cast<element*>(
reinterpret_cast<uint8_t*>(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); reinterpret_cast<uint8_t*>(&value) -
((std::size_t)std::addressof(((element*)0)->member))));
} }
const_iterator const_iterator
@@ -477,7 +497,8 @@ public:
{ {
static_assert(std::is_standard_layout<element>::value, "must be standard layout"); static_assert(std::is_standard_layout<element>::value, "must be standard layout");
return list.iterator_to(*reinterpret_cast<element const*>( return list.iterator_to(*reinterpret_cast<element const*>(
reinterpret_cast<uint8_t const*>(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); reinterpret_cast<uint8_t const*>(&value) -
((std::size_t)std::addressof(((element*)0)->member))));
} }
private: private:
@@ -518,7 +539,12 @@ public:
aged_ordered_container(InputIt first, InputIt last, clock_type& clock, Allocator const& alloc); aged_ordered_container(InputIt first, InputIt last, clock_type& clock, Allocator const& alloc);
template <class InputIt> template <class InputIt>
aged_ordered_container(InputIt first, InputIt last, clock_type& clock, Compare const& comp, Allocator const& alloc); aged_ordered_container(
InputIt first,
InputIt last,
clock_type& clock,
Compare const& comp,
Allocator const& alloc);
aged_ordered_container(aged_ordered_container const& other); aged_ordered_container(aged_ordered_container const& other);
@@ -530,9 +556,15 @@ public:
aged_ordered_container(std::initializer_list<value_type> init, clock_type& clock); aged_ordered_container(std::initializer_list<value_type> init, clock_type& clock);
aged_ordered_container(std::initializer_list<value_type> init, clock_type& clock, Compare const& comp); aged_ordered_container(
std::initializer_list<value_type> init,
clock_type& clock,
Compare const& comp);
aged_ordered_container(std::initializer_list<value_type> init, clock_type& clock, Allocator const& alloc); aged_ordered_container(
std::initializer_list<value_type> init,
clock_type& clock,
Allocator const& alloc);
aged_ordered_container( aged_ordered_container(
std::initializer_list<value_type> init, std::initializer_list<value_type> init,
@@ -688,7 +720,8 @@ public:
{ {
static_assert(std::is_standard_layout<element>::value, "must be standard layout"); static_assert(std::is_standard_layout<element>::value, "must be standard layout");
return m_cont.iterator_to(*reinterpret_cast<element*>( return m_cont.iterator_to(*reinterpret_cast<element*>(
reinterpret_cast<uint8_t*>(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); reinterpret_cast<uint8_t*>(&value) -
((std::size_t)std::addressof(((element*)0)->member))));
} }
const_iterator const_iterator
@@ -696,7 +729,8 @@ public:
{ {
static_assert(std::is_standard_layout<element>::value, "must be standard layout"); static_assert(std::is_standard_layout<element>::value, "must be standard layout");
return m_cont.iterator_to(*reinterpret_cast<element const*>( return m_cont.iterator_to(*reinterpret_cast<element const*>(
reinterpret_cast<uint8_t const*>(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); reinterpret_cast<uint8_t const*>(&value) -
((std::size_t)std::addressof(((element*)0)->member))));
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@@ -735,7 +769,8 @@ public:
// map, set // map, set
template <bool maybe_multi = IsMulti> template <bool maybe_multi = IsMulti>
auto auto
insert(value_type const& value) -> typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type; insert(value_type const& value) ->
typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type;
// multimap, multiset // multimap, multiset
template <bool maybe_multi = IsMulti> template <bool maybe_multi = IsMulti>
@@ -745,19 +780,22 @@ public:
// set // set
template <bool maybe_multi = IsMulti, bool maybe_map = IsMap> template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
auto auto
insert(value_type&& value) -> typename std::enable_if<!maybe_multi && !maybe_map, std::pair<iterator, bool>>::type; insert(value_type&& value) ->
typename std::enable_if<!maybe_multi && !maybe_map, std::pair<iterator, bool>>::type;
// multiset // multiset
template <bool maybe_multi = IsMulti, bool maybe_map = IsMap> template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
auto auto
insert(value_type&& value) -> typename std::enable_if<maybe_multi && !maybe_map, iterator>::type; insert(value_type&& value) ->
typename std::enable_if<maybe_multi && !maybe_map, iterator>::type;
//--- //---
// map, set // map, set
template <bool maybe_multi = IsMulti> template <bool maybe_multi = IsMulti>
auto auto
insert(const_iterator hint, value_type const& value) -> typename std::enable_if<!maybe_multi, iterator>::type; insert(const_iterator hint, value_type const& value) ->
typename std::enable_if<!maybe_multi, iterator>::type;
// multimap, multiset // multimap, multiset
template <bool maybe_multi = IsMulti> template <bool maybe_multi = IsMulti>
@@ -771,7 +809,8 @@ public:
// map, set // map, set
template <bool maybe_multi = IsMulti> template <bool maybe_multi = IsMulti>
auto auto
insert(const_iterator hint, value_type&& value) -> typename std::enable_if<!maybe_multi, iterator>::type; insert(const_iterator hint, value_type&& value) ->
typename std::enable_if<!maybe_multi, iterator>::type;
// multimap, multiset // multimap, multiset
template <bool maybe_multi = IsMulti> template <bool maybe_multi = IsMulti>
@@ -819,7 +858,8 @@ public:
// map, set // map, set
template <bool maybe_multi = IsMulti, class... Args> template <bool maybe_multi = IsMulti, class... Args>
auto auto
emplace(Args&&... args) -> typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type; emplace(Args&&... args) ->
typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type;
// multiset, multimap // multiset, multimap
template <bool maybe_multi = IsMulti, class... Args> template <bool maybe_multi = IsMulti, class... Args>
@@ -842,13 +882,19 @@ public:
} }
// enable_if prevents erase (reverse_iterator pos) from compiling // enable_if prevents erase (reverse_iterator pos) from compiling
template <bool is_const, class Iterator, class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>> template <
bool is_const,
class Iterator,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
beast::detail::aged_container_iterator<false, Iterator> beast::detail::aged_container_iterator<false, Iterator>
erase(beast::detail::aged_container_iterator<is_const, Iterator> pos); erase(beast::detail::aged_container_iterator<is_const, Iterator> pos);
// enable_if prevents erase (reverse_iterator first, reverse_iterator last) // enable_if prevents erase (reverse_iterator first, reverse_iterator last)
// from compiling // from compiling
template <bool is_const, class Iterator, class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>> template <
bool is_const,
class Iterator,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
beast::detail::aged_container_iterator<false, Iterator> beast::detail::aged_container_iterator<false, Iterator>
erase( erase(
beast::detail::aged_container_iterator<is_const, Iterator> first, beast::detail::aged_container_iterator<is_const, Iterator> first,
@@ -864,7 +910,10 @@ public:
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// enable_if prevents touch (reverse_iterator pos) from compiling // enable_if prevents touch (reverse_iterator pos) from compiling
template <bool is_const, class Iterator, class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>> template <
bool is_const,
class Iterator,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
void void
touch(beast::detail::aged_container_iterator<is_const, Iterator> pos) touch(beast::detail::aged_container_iterator<is_const, Iterator> pos)
{ {
@@ -984,69 +1033,136 @@ public:
// is only done on the key portion of the value type, ignoring // is only done on the key portion of the value type, ignoring
// the mapped type. // the mapped type.
// //
template <bool OtherIsMulti, bool OtherIsMap, class OtherT, class OtherDuration, class OtherAllocator> template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherT,
class OtherDuration,
class OtherAllocator>
bool bool
operator==( operator==(aged_ordered_container<
aged_ordered_container<OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator> const& OtherIsMulti,
other) const; OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator> const& other) const;
template <bool OtherIsMulti, bool OtherIsMap, class OtherT, class OtherDuration, class OtherAllocator> template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherT,
class OtherDuration,
class OtherAllocator>
bool bool
operator!=( operator!=(aged_ordered_container<
aged_ordered_container<OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator> const& OtherIsMulti,
other) const OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator> const& other) const
{ {
return !(this->operator==(other)); return !(this->operator==(other));
} }
template <bool OtherIsMulti, bool OtherIsMap, class OtherT, class OtherDuration, class OtherAllocator> template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherT,
class OtherDuration,
class OtherAllocator>
bool bool
operator<( operator<(aged_ordered_container<
aged_ordered_container<OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator> const& OtherIsMulti,
other) const OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator> const& other) const
{ {
value_compare const comp(value_comp()); value_compare const comp(value_comp());
return std::lexicographical_compare(cbegin(), cend(), other.cbegin(), other.cend(), comp); return std::lexicographical_compare(cbegin(), cend(), other.cbegin(), other.cend(), comp);
} }
template <bool OtherIsMulti, bool OtherIsMap, class OtherT, class OtherDuration, class OtherAllocator> template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherT,
class OtherDuration,
class OtherAllocator>
bool bool
operator<=( operator<=(aged_ordered_container<
aged_ordered_container<OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator> const& OtherIsMulti,
other) const OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator> const& other) const
{ {
return !(other < *this); return !(other < *this);
} }
template <bool OtherIsMulti, bool OtherIsMap, class OtherT, class OtherDuration, class OtherAllocator> template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherT,
class OtherDuration,
class OtherAllocator>
bool bool
operator>( operator>(aged_ordered_container<
aged_ordered_container<OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator> const& OtherIsMulti,
other) const OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator> const& other) const
{ {
return other < *this; return other < *this;
} }
template <bool OtherIsMulti, bool OtherIsMap, class OtherT, class OtherDuration, class OtherAllocator> template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherT,
class OtherDuration,
class OtherAllocator>
bool bool
operator>=( operator>=(aged_ordered_container<
aged_ordered_container<OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator> const& OtherIsMulti,
other) const OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator> const& other) const
{ {
return !(*this < other); return !(*this < other);
} }
private: private:
// enable_if prevents erase (reverse_iterator pos, now) from compiling // enable_if prevents erase (reverse_iterator pos, now) from compiling
template <bool is_const, class Iterator, class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>> template <
bool is_const,
class Iterator,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
void void
touch(beast::detail::aged_container_iterator<is_const, Iterator> pos, typename clock_type::time_point const& now); touch(
beast::detail::aged_container_iterator<is_const, Iterator> pos,
typename clock_type::time_point const& now);
template <bool maybe_propagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value> template <
bool maybe_propagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
typename std::enable_if<maybe_propagate>::type typename std::enable_if<maybe_propagate>::type
swap_data(aged_ordered_container& other) noexcept; swap_data(aged_ordered_container& other) noexcept;
template <bool maybe_propagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value> template <
bool maybe_propagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
typename std::enable_if<!maybe_propagate>::type typename std::enable_if<!maybe_propagate>::type
swap_data(aged_ordered_container& other) noexcept; swap_data(aged_ordered_container& other) noexcept;
@@ -1058,7 +1174,8 @@ private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::aged_ordered_container(clock_type& clock) aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::aged_ordered_container(
clock_type& clock)
: m_config(clock) : m_config(clock)
{ {
} }
@@ -1249,8 +1366,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::opera
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
auto auto
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator=(aged_ordered_container&& other) aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator=(
-> aged_ordered_container& aged_ordered_container&& other) -> aged_ordered_container&
{ {
clear(); clear();
this->m_config = std::move(other.m_config); this->m_config = std::move(other.m_config);
@@ -1296,13 +1413,15 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool maybe_multi, bool maybe_map, class> template <bool maybe_multi, bool maybe_map, class>
typename std::conditional<IsMap, T, void*>::type& typename std::conditional<IsMap, T, void*>::type&
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](Key const& key) aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](
Key const& key)
{ {
typename cont_type::insert_commit_data d; typename cont_type::insert_commit_data d;
auto const result(m_cont.insert_check(key, std::cref(m_config.key_compare()), d)); auto const result(m_cont.insert_check(key, std::cref(m_config.key_compare()), d));
if (result.second) if (result.second)
{ {
element* const p(new_element(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple())); element* const p(new_element(
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple()));
m_cont.insert_commit(*p, d); m_cont.insert_commit(*p, d);
chronological.list.push_back(*p); chronological.list.push_back(*p);
return p->value.second; return p->value.second;
@@ -1319,8 +1438,10 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::opera
auto const result(m_cont.insert_check(key, std::cref(m_config.key_compare()), d)); auto const result(m_cont.insert_check(key, std::cref(m_config.key_compare()), d));
if (result.second) if (result.second)
{ {
element* const p( element* const p(new_element(
new_element(std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::forward_as_tuple())); std::piecewise_construct,
std::forward_as_tuple(std::move(key)),
std::forward_as_tuple()));
m_cont.insert_commit(*p, d); m_cont.insert_commit(*p, d);
chronological.list.push_back(*p); chronological.list.push_back(*p);
return p->value.second; return p->value.second;
@@ -1344,7 +1465,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::clear
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool maybe_multi> template <bool maybe_multi>
auto auto
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type const& value) -> aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
value_type const& value) ->
typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type
{ {
typename cont_type::insert_commit_data d; typename cont_type::insert_commit_data d;
@@ -1363,8 +1485,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::inser
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool maybe_multi> template <bool maybe_multi>
auto auto
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type const& value) -> aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
typename std::enable_if<maybe_multi, iterator>::type value_type const& value) -> typename std::enable_if<maybe_multi, iterator>::type
{ {
auto const before(m_cont.upper_bound(extract(value), std::cref(m_config.key_compare()))); auto const before(m_cont.upper_bound(extract(value), std::cref(m_config.key_compare())));
element* const p(new_element(value)); element* const p(new_element(value));
@@ -1377,7 +1499,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::inser
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool maybe_multi, bool maybe_map> template <bool maybe_multi, bool maybe_map>
auto auto
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type&& value) -> aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
value_type&& value) ->
typename std::enable_if<!maybe_multi && !maybe_map, std::pair<iterator, bool>>::type typename std::enable_if<!maybe_multi && !maybe_map, std::pair<iterator, bool>>::type
{ {
typename cont_type::insert_commit_data d; typename cont_type::insert_commit_data d;
@@ -1396,8 +1519,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::inser
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool maybe_multi, bool maybe_map> template <bool maybe_multi, bool maybe_map>
auto auto
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type&& value) -> aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
typename std::enable_if<maybe_multi && !maybe_map, iterator>::type value_type&& value) -> typename std::enable_if<maybe_multi && !maybe_map, iterator>::type
{ {
auto const before(m_cont.upper_bound(extract(value), std::cref(m_config.key_compare()))); auto const before(m_cont.upper_bound(extract(value), std::cref(m_config.key_compare())));
element* const p(new_element(std::move(value))); element* const p(new_element(std::move(value)));
@@ -1417,7 +1540,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::inser
value_type const& value) -> typename std::enable_if<!maybe_multi, iterator>::type value_type const& value) -> typename std::enable_if<!maybe_multi, iterator>::type
{ {
typename cont_type::insert_commit_data d; typename cont_type::insert_commit_data d;
auto const result(m_cont.insert_check(hint.iterator(), extract(value), std::cref(m_config.key_compare()), d)); auto const result(
m_cont.insert_check(hint.iterator(), extract(value), std::cref(m_config.key_compare()), d));
if (result.second) if (result.second)
{ {
element* const p(new_element(value)); element* const p(new_element(value));
@@ -1437,7 +1561,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::inser
value_type&& value) -> typename std::enable_if<!maybe_multi, iterator>::type value_type&& value) -> typename std::enable_if<!maybe_multi, iterator>::type
{ {
typename cont_type::insert_commit_data d; typename cont_type::insert_commit_data d;
auto const result(m_cont.insert_check(hint.iterator(), extract(value), std::cref(m_config.key_compare()), d)); auto const result(
m_cont.insert_check(hint.iterator(), extract(value), std::cref(m_config.key_compare()), d));
if (result.second) if (result.second)
{ {
element* const p(new_element(std::move(value))); element* const p(new_element(std::move(value)));
@@ -1452,8 +1577,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::inser
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool maybe_multi, class... Args> template <bool maybe_multi, class... Args>
auto auto
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args) -> aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args)
typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type -> typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type
{ {
// VFALCO NOTE Its unfortunate that we need to // VFALCO NOTE Its unfortunate that we need to
// construct element here // construct element here
@@ -1474,8 +1599,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::empla
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool maybe_multi, class... Args> template <bool maybe_multi, class... Args>
auto auto
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args) -> aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args)
typename std::enable_if<maybe_multi, iterator>::type -> typename std::enable_if<maybe_multi, iterator>::type
{ {
element* const p(new_element(std::forward<Args>(args)...)); element* const p(new_element(std::forward<Args>(args)...));
auto const before(m_cont.upper_bound(extract(p->value), std::cref(m_config.key_compare()))); auto const before(m_cont.upper_bound(extract(p->value), std::cref(m_config.key_compare())));
@@ -1496,7 +1621,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::empla
// construct element here // construct element here
element* const p(new_element(std::forward<Args>(args)...)); element* const p(new_element(std::forward<Args>(args)...));
typename cont_type::insert_commit_data d; typename cont_type::insert_commit_data d;
auto const result(m_cont.insert_check(hint.iterator(), extract(p->value), std::cref(m_config.key_compare()), d)); auto const result(m_cont.insert_check(
hint.iterator(), extract(p->value), std::cref(m_config.key_compare()), d));
if (result.second) if (result.second)
{ {
auto const iter(m_cont.insert_commit(*p, d)); auto const iter(m_cont.insert_commit(*p, d));
@@ -1533,7 +1659,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <class K> template <class K>
auto auto
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(K const& k) -> size_type aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(K const& k)
-> size_type
{ {
auto iter(m_cont.find(k, std::cref(m_config.key_compare()))); auto iter(m_cont.find(k, std::cref(m_config.key_compare())));
if (iter == m_cont.end()) if (iter == m_cont.end())
@@ -1553,7 +1680,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
void void
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swap(aged_ordered_container& other) noexcept aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swap(
aged_ordered_container& other) noexcept
{ {
swap_data(other); swap_data(other);
std::swap(chronological, other.chronological); std::swap(chronological, other.chronological);
@@ -1565,7 +1693,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swap(
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <class K> template <class K>
auto auto
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(K const& k) -> size_type aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(K const& k)
-> size_type
{ {
auto const now(clock().now()); auto const now(clock().now());
size_type n(0); size_type n(0);
@@ -1581,13 +1710,31 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <bool OtherIsMulti, bool OtherIsMap, class OtherT, class OtherDuration, class OtherAllocator> template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherT,
class OtherDuration,
class OtherAllocator>
bool bool
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator==( aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator==(
aged_ordered_container<OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator> const& other) aged_ordered_container<
const OtherIsMulti,
OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator> const& other) const
{ {
using Other = aged_ordered_container<OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator>; using Other = aged_ordered_container<
OtherIsMulti,
OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator>;
if (size() != other.size()) if (size() != other.size())
return false; return false;
std::equal_to<void> eq; std::equal_to<void> eq;
@@ -1642,7 +1789,8 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swap_
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator> template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
struct is_aged_container<beast::detail::aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>> struct is_aged_container<
beast::detail::aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>>
: std::true_type : std::true_type
{ {
explicit is_aged_container() = default; explicit is_aged_container() = default;
@@ -1654,7 +1802,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
void void
swap( swap(
beast::detail::aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>& lhs, beast::detail::aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>& lhs,
beast::detail::aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>& rhs) noexcept beast::detail::aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>&
rhs) noexcept
{ {
lhs.swap(rhs); lhs.swap(rhs);
} }
@@ -1677,7 +1826,8 @@ expire(
{ {
std::size_t n(0); std::size_t n(0);
auto const expired(c.clock().now() - age); auto const expired(c.clock().now() - age);
for (auto iter(c.chronological.cbegin()); iter != c.chronological.cend() && iter.when() <= expired;) for (auto iter(c.chronological.cbegin());
iter != c.chronological.cend() && iter.when() <= expired;)
{ {
iter = c.erase(iter); iter = c.erase(iter);
++n; ++n;

File diff suppressed because it is too large Load Diff

View File

@@ -50,7 +50,9 @@ struct LexicalCast<Out, std::string_view>
{ {
explicit LexicalCast() = default; explicit LexicalCast() = default;
static_assert(std::is_integral_v<Out>, "beast::LexicalCast can only be used with integral types"); static_assert(
std::is_integral_v<Out>,
"beast::LexicalCast can only be used with integral types");
template <class Integral = Out> template <class Integral = Out>
std::enable_if_t<std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>, bool> std::enable_if_t<std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>, bool>

View File

@@ -19,10 +19,12 @@ public:
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
using value_type = typename Container::value_type; using value_type = typename Container::value_type;
using difference_type = typename Container::difference_type; using difference_type = typename Container::difference_type;
using pointer = using pointer = typename std::
typename std::conditional<IsConst, typename Container::const_pointer, typename Container::pointer>::type; conditional<IsConst, typename Container::const_pointer, typename Container::pointer>::type;
using reference = using reference = typename std::conditional<
typename std::conditional<IsConst, typename Container::const_reference, typename Container::reference>::type; IsConst,
typename Container::const_reference,
typename Container::reference>::type;
LockFreeStackIterator() : m_node() LockFreeStackIterator() : m_node()
{ {
@@ -33,7 +35,8 @@ public:
} }
template <bool OtherIsConst> template <bool OtherIsConst>
explicit LockFreeStackIterator(LockFreeStackIterator<Container, OtherIsConst> const& other) : m_node(other.m_node) explicit LockFreeStackIterator(LockFreeStackIterator<Container, OtherIsConst> const& other)
: m_node(other.m_node)
{ {
} }
@@ -190,7 +193,8 @@ public:
{ {
first = (old_head == &m_end); first = (old_head == &m_end);
node->m_next = old_head; node->m_next = old_head;
} while (!m_head.compare_exchange_strong(old_head, node, std::memory_order_release, std::memory_order_relaxed)); } while (!m_head.compare_exchange_strong(
old_head, node, std::memory_order_release, std::memory_order_relaxed));
return first; return first;
} }
@@ -213,7 +217,8 @@ public:
if (node == &m_end) if (node == &m_end)
return nullptr; return nullptr;
new_head = node->m_next.load(); new_head = node->m_next.load();
} while (!m_head.compare_exchange_strong(node, new_head, std::memory_order_release, std::memory_order_relaxed)); } while (!m_head.compare_exchange_strong(
node, new_head, std::memory_order_release, std::memory_order_relaxed));
return static_cast<Element*>(node); return static_cast<Element*>(node);
} }

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
namespace beast { namespace beast {
@@ -26,14 +27,14 @@ public:
SemanticVersion(); SemanticVersion();
SemanticVersion(std::string const& version); SemanticVersion(std::string_view version);
/** Parse a semantic version string. /** Parse a semantic version string.
The parsing is as strict as possible. The parsing is as strict as possible.
@return `true` if the string was parsed. @return `true` if the string was parsed.
*/ */
bool bool
parse(std::string const& input); parse(std::string_view input);
/** Produce a string from semantic version components. */ /** Produce a string from semantic version components. */
std::string std::string

View File

@@ -26,7 +26,8 @@ template <class T>
inline void inline void
reverse_bytes(T& t) reverse_bytes(T& t)
{ {
unsigned char* bytes = static_cast<unsigned char*>(std::memmove(std::addressof(t), std::addressof(t), sizeof(T))); unsigned char* bytes =
static_cast<unsigned char*>(std::memmove(std::addressof(t), std::addressof(t), sizeof(T)));
for (unsigned i = 0; i < sizeof(T) / 2; ++i) for (unsigned i = 0; i < sizeof(T) / 2; ++i)
std::swap(bytes[i], bytes[sizeof(T) - 1 - i]); std::swap(bytes[i], bytes[sizeof(T) - 1 - i]);
} }
@@ -51,7 +52,8 @@ template <class T, class Hasher>
inline void inline void
maybe_reverse_bytes(T& t, Hasher&) maybe_reverse_bytes(T& t, Hasher&)
{ {
maybe_reverse_bytes(t, std::integral_constant<bool, Hasher::endian != boost::endian::order::native>{}); maybe_reverse_bytes(
t, std::integral_constant<bool, Hasher::endian != boost::endian::order::native>{});
} }
} // namespace detail } // namespace detail
@@ -65,8 +67,9 @@ maybe_reverse_bytes(T& t, Hasher&)
template <class T> template <class T>
struct is_uniquely_represented struct is_uniquely_represented
: public std:: : public std::integral_constant<
integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value || std::is_pointer<T>::value> bool,
std::is_integral<T>::value || std::is_enum<T>::value || std::is_pointer<T>::value>
{ {
explicit is_uniquely_represented() = default; explicit is_uniquely_represented() = default;
}; };
@@ -107,7 +110,8 @@ template <class... T>
struct is_uniquely_represented<std::tuple<T...>> struct is_uniquely_represented<std::tuple<T...>>
: public std::integral_constant< : public std::integral_constant<
bool, bool,
std::conjunction_v<is_uniquely_represented<T>...> && sizeof(std::tuple<T...>) == (sizeof(T) + ...)> std::conjunction_v<is_uniquely_represented<T>...> &&
sizeof(std::tuple<T...>) == (sizeof(T) + ...)>
{ {
explicit is_uniquely_represented() = default; explicit is_uniquely_represented() = default;
}; };
@@ -124,8 +128,9 @@ struct is_uniquely_represented<T[N]> : public is_uniquely_represented<T>
template <class T, std::size_t N> template <class T, std::size_t N>
struct is_uniquely_represented<std::array<T, N>> struct is_uniquely_represented<std::array<T, N>>
: public std:: : public std::integral_constant<
integral_constant<bool, is_uniquely_represented<T>::value && sizeof(T) * N == sizeof(std::array<T, N>)> bool,
is_uniquely_represented<T>::value && sizeof(T) * N == sizeof(std::array<T, N>)>
{ {
explicit is_uniquely_represented() = default; explicit is_uniquely_represented() = default;
}; };
@@ -145,10 +150,11 @@ struct is_uniquely_represented<std::array<T, N>>
*/ */
/** @{ */ /** @{ */
template <class T, class HashAlgorithm> template <class T, class HashAlgorithm>
struct is_contiguously_hashable : public std::integral_constant< struct is_contiguously_hashable
bool, : public std::integral_constant<
is_uniquely_represented<T>::value && bool,
(sizeof(T) == 1 || HashAlgorithm::endian == boost::endian::order::native)> is_uniquely_represented<T>::value &&
(sizeof(T) == 1 || HashAlgorithm::endian == boost::endian::order::native)>
{ {
explicit is_contiguously_hashable() = default; explicit is_contiguously_hashable() = default;
}; };

View File

@@ -25,7 +25,8 @@ struct ci_equal_pred
operator()(char c1, char c2) operator()(char c1, char c2)
{ {
// VFALCO TODO Use a table lookup here // VFALCO TODO Use a table lookup here
return std::tolower(static_cast<unsigned char>(c1)) == std::tolower(static_cast<unsigned char>(c2)); return std::tolower(static_cast<unsigned char>(c1)) ==
std::tolower(static_cast<unsigned char>(c2));
} }
}; };
@@ -169,7 +170,9 @@ split(FwdIt first, FwdIt last, Char delim)
return result; return result;
} }
template <class FwdIt, class Result = std::vector<std::basic_string<typename std::iterator_traits<FwdIt>::value_type>>> template <
class FwdIt,
class Result = std::vector<std::basic_string<typename std::iterator_traits<FwdIt>::value_type>>>
Result Result
split_commas(FwdIt first, FwdIt last) split_commas(FwdIt first, FwdIt last)
{ {
@@ -356,8 +359,10 @@ bool
is_keep_alive(boost::beast::http::message<isRequest, Body, Fields> const& m) is_keep_alive(boost::beast::http::message<isRequest, Body, Fields> const& m)
{ {
if (m.version() <= 10) if (m.version() <= 10)
return boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists("keep-alive"); return boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists(
return !boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists("close"); "keep-alive");
return !boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists(
"close");
} }
} // namespace rfc2616 } // namespace rfc2616

View File

@@ -40,7 +40,8 @@ public:
/// The type of yield context passed to functions. /// The type of yield context passed to functions.
using yield_context = boost::asio::yield_context; using yield_context = boost::asio::yield_context;
explicit enable_yield_to(std::size_t concurrency = 1) : work_(boost::asio::make_work_guard(ios_)) explicit enable_yield_to(std::size_t concurrency = 1)
: work_(boost::asio::make_work_guard(ios_))
{ {
threads_.reserve(concurrency); threads_.reserve(concurrency);
while (concurrency--) while (concurrency--)

View File

@@ -22,7 +22,12 @@ global_suites()
template <class Suite> template <class Suite>
struct insert_suite struct insert_suite
{ {
insert_suite(char const* name, char const* module, char const* library, bool manual, int priority) insert_suite(
char const* name,
char const* module,
char const* library,
bool manual,
int priority)
{ {
global_suites().insert<Suite>(name, module, library, manual, priority); global_suites().insert<Suite>(name, module, library, manual, priority);
} }

View File

@@ -139,7 +139,10 @@ reporter<_>::results::add(suite_results const& r)
if (elapsed >= std::chrono::seconds{1}) if (elapsed >= std::chrono::seconds{1})
{ {
auto const iter = std::lower_bound( auto const iter = std::lower_bound(
top.begin(), top.end(), elapsed, [](run_time const& t1, typename clock_type::duration const& t2) { top.begin(),
top.end(),
elapsed,
[](run_time const& t1, typename clock_type::duration const& t2) {
return t1.second > t2; return t1.second > t2;
}); });
if (iter != top.end()) if (iter != top.end())
@@ -172,8 +175,9 @@ reporter<_>::~reporter()
os_ << std::setw(8) << fmtdur(i.second) << " " << i.first << '\n'; os_ << std::setw(8) << fmtdur(i.second) << " " << i.first << '\n';
} }
auto const elapsed = clock_type::now() - results_.start; auto const elapsed = clock_type::now() - results_.start;
os_ << fmtdur(elapsed) << ", " << amount{results_.suites, "suite"} << ", " << amount{results_.cases, "case"} << ", " os_ << fmtdur(elapsed) << ", " << amount{results_.suites, "suite"} << ", "
<< amount{results_.total, "test"} << " total, " << amount{results_.failed, "failure"} << std::endl; << amount{results_.cases, "case"} << ", " << amount{results_.total, "test"} << " total, "
<< amount{results_.failed, "failure"} << std::endl;
} }
template <class _> template <class _>
@@ -208,7 +212,8 @@ void
reporter<_>::on_case_begin(std::string const& name) reporter<_>::on_case_begin(std::string const& name)
{ {
case_results_ = case_results(name); case_results_ = case_results(name);
os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name)) << std::endl; os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name))
<< std::endl;
} }
template <class _> template <class _>
@@ -231,7 +236,8 @@ reporter<_>::on_fail(std::string const& reason)
{ {
++case_results_.failed; ++case_results_.failed;
++case_results_.total; ++case_results_.total;
os_ << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") << reason << std::endl; os_ << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") << reason
<< std::endl;
} }
template <class _> template <class _>

View File

@@ -91,7 +91,10 @@ private:
} }
}; };
template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>> template <
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>>
class log_os : public std::basic_ostream<CharT, Traits> class log_os : public std::basic_ostream<CharT, Traits>
{ {
log_buf<CharT, Traits, Allocator> buf_; log_buf<CharT, Traits, Allocator> buf_;
@@ -562,7 +565,8 @@ suite::run(runner& r)
If the condition is false, the file and line number are reported. If the condition is false, the file and line number are reported.
*/ */
#define BEAST_EXPECTS(cond, reason) ((cond) ? (pass(), true) : (fail((reason), __FILE__, __LINE__), false)) #define BEAST_EXPECTS(cond, reason) \
((cond) ? (pass(), true) : (fail((reason), __FILE__, __LINE__), false))
#endif #endif
} // namespace unit_test } // namespace unit_test
@@ -572,9 +576,9 @@ suite::run(runner& r)
// detail: // detail:
// This inserts the suite with the given manual flag // This inserts the suite with the given manual flag
#define BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, manual, priority) \ #define BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, manual, priority) \
static beast::unit_test::detail::insert_suite<Class##_test> Library##Module##Class##_test_instance( \ static beast::unit_test::detail::insert_suite<Class##_test> \
#Class, #Module, #Library, manual, priority) Library##Module##Class##_test_instance(#Class, #Module, #Library, manual, priority)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -629,7 +633,8 @@ suite::run(runner& r)
#else #else
#include <xrpl/beast/unit_test/global_suites.h> #include <xrpl/beast/unit_test/global_suites.h>
#define BEAST_DEFINE_TESTSUITE(Class, Module, Library) BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, false, 0) #define BEAST_DEFINE_TESTSUITE(Class, Module, Library) \
BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, false, 0)
#define BEAST_DEFINE_TESTSUITE_MANUAL(Class, Module, Library) \ #define BEAST_DEFINE_TESTSUITE_MANUAL(Class, Module, Library) \
BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, true, 0) BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, true, 0)
#define BEAST_DEFINE_TESTSUITE_PRIO(Class, Module, Library, Priority) \ #define BEAST_DEFINE_TESTSUITE_PRIO(Class, Module, Library, Priority) \

View File

@@ -27,7 +27,13 @@ class suite_info
run_type run_; run_type run_;
public: public:
suite_info(std::string name, std::string module, std::string library, bool manual, int priority, run_type run) suite_info(
std::string name,
std::string module,
std::string library,
bool manual,
int priority,
run_type run)
: name_(std::move(name)) : name_(std::move(name))
, module_(std::move(module)) , module_(std::move(module))
, library_(std::move(library)) , library_(std::move(library))
@@ -91,10 +97,17 @@ public:
/// Convenience for producing suite_info for a given test type. /// Convenience for producing suite_info for a given test type.
template <class Suite> template <class Suite>
suite_info suite_info
make_suite_info(std::string name, std::string module, std::string library, bool manual, int priority) make_suite_info(
std::string name,
std::string module,
std::string library,
bool manual,
int priority)
{ {
return suite_info( return suite_info(
std::move(name), std::move(module), std::move(library), manual, priority, [](runner& r) { Suite{}(r); }); std::move(name), std::move(module), std::move(library), manual, priority, [](runner& r) {
Suite{}(r);
});
} }
} // namespace unit_test } // namespace unit_test

View File

@@ -39,7 +39,12 @@ public:
template <class Suite> template <class Suite>
void void
suite_list::insert(char const* name, char const* module, char const* library, bool manual, int priority) suite_list::insert(
char const* name,
char const* module,
char const* library,
bool manual,
int priority)
{ {
#ifndef NDEBUG #ifndef NDEBUG
{ {

View File

@@ -190,7 +190,8 @@ public:
*/ */
Stream(Sink& sink, Severity level) : m_sink(sink), m_level(level) Stream(Sink& sink, Severity level) : m_sink(sink), m_level(level)
{ {
XRPL_ASSERT(m_level < severities::kDisabled, "beast::Journal::Stream::Stream : maximum level"); XRPL_ASSERT(
m_level < severities::kDisabled, "beast::Journal::Stream::Stream : maximum level");
} }
/** Construct or copy another Stream. */ /** Construct or copy another Stream. */
@@ -421,7 +422,8 @@ class basic_logstream : public std::basic_ostream<CharT, Traits>
detail::logstream_buf<CharT, Traits> buf_; detail::logstream_buf<CharT, Traits> buf_;
public: public:
explicit basic_logstream(beast::Journal::Stream const& strm) : std::basic_ostream<CharT, Traits>(&buf_), buf_(strm) explicit basic_logstream(beast::Journal::Stream const& strm)
: std::basic_ostream<CharT, Traits>(&buf_), buf_(strm)
{ {
} }
}; };

View File

@@ -19,7 +19,8 @@
#endif #endif
#define XRPL_ASSERT ALWAYS_OR_UNREACHABLE #define XRPL_ASSERT ALWAYS_OR_UNREACHABLE
#define XRPL_ASSERT_PARTS(cond, function, description, ...) XRPL_ASSERT(cond, function " : " description) #define XRPL_ASSERT_PARTS(cond, function, description, ...) \
XRPL_ASSERT(cond, function " : " description)
// How to use the instrumentation macros: // How to use the instrumentation macros:
// //

View File

@@ -9,8 +9,10 @@ template <bool IsConst, class T>
struct maybe_const struct maybe_const
{ {
explicit maybe_const() = default; explicit maybe_const() = default;
using type = typename std:: using type = typename std::conditional<
conditional<IsConst, typename std::remove_const<T>::type const, typename std::remove_const<T>::type>::type; IsConst,
typename std::remove_const<T>::type const,
typename std::remove_const<T>::type>::type;
}; };
/** Alias for omitting `typename`. */ /** Alias for omitting `typename`. */

View File

@@ -35,7 +35,10 @@ rngfill(void* const buffer, std::size_t const bytes, Generator& g)
} }
} }
template <class Generator, std::size_t N, class = std::enable_if_t<N % sizeof(typename Generator::result_type) == 0>> template <
class Generator,
std::size_t N,
class = std::enable_if_t<N % sizeof(typename Generator::result_type) == 0>>
void void
rngfill(std::array<std::uint8_t, N>& a, Generator& g) rngfill(std::array<std::uint8_t, N>& a, Generator& g)
{ {

View File

@@ -76,7 +76,8 @@ inline bool
operator==(Fulfillment const& lhs, Fulfillment const& rhs) operator==(Fulfillment const& lhs, Fulfillment const& rhs)
{ {
// FIXME: for compound conditions, need to also check subtypes // FIXME: for compound conditions, need to also check subtypes
return lhs.type() == rhs.type() && lhs.cost() == rhs.cost() && lhs.fingerprint() == rhs.fingerprint(); return lhs.type() == rhs.type() && lhs.cost() == rhs.cost() &&
lhs.fingerprint() == rhs.fingerprint();
} }
inline bool inline bool

View File

@@ -11,7 +11,8 @@ JobQueue::Coro::Coro(Coro_create_t, JobQueue& jq, JobType type, std::string cons
, name_(name) , name_(name)
, running_(false) , running_(false)
, coro_( , coro_(
[this, fn = std::forward<F>(f)](boost::coroutines::asymmetric_coroutine<void>::push_type& do_yield) { [this, fn = std::forward<F>(f)](
boost::coroutines::asymmetric_coroutine<void>::push_type& do_yield) {
yield_ = &do_yield; yield_ = &do_yield;
yield(); yield();
fn(shared_from_this()); fn(shared_from_this());

View File

@@ -210,7 +210,11 @@ public:
// Add a peer suppression and return whether the entry should be processed // Add a peer suppression and return whether the entry should be processed
bool bool
shouldProcess(uint256 const& key, PeerShortID peer, HashRouterFlags& flags, std::chrono::seconds tx_interval); shouldProcess(
uint256 const& key,
PeerShortID peer,
HashRouterFlags& flags,
std::chrono::seconds tx_interval);
/** Set the flags on a hash. /** Set the flags on a hash.
@@ -248,7 +252,8 @@ private:
Setup const setup_; Setup const setup_;
// Stores all suppressed hashes and their expiration time // Stores all suppressed hashes and their expiration time
beast::aged_unordered_map<uint256, Entry, Stopwatch::clock_type, hardened_hash<strong_hash>> suppressionMap_; beast::aged_unordered_map<uint256, Entry, Stopwatch::clock_type, hardened_hash<strong_hash>>
suppressionMap_;
}; };
} // namespace xrpl } // namespace xrpl

View File

@@ -92,7 +92,11 @@ public:
Job(JobType type, std::uint64_t index); Job(JobType type, std::uint64_t index);
// VFALCO TODO try to remove the dependency on LoadMonitor. // VFALCO TODO try to remove the dependency on LoadMonitor.
Job(JobType type, std::string const& name, std::uint64_t index, LoadMonitor& lm, std::function<void()> const& job); Job(JobType type,
std::string const& name,
std::uint64_t index,
LoadMonitor& lm,
std::function<void()> const& job);
JobType JobType
getType() const; getType() const;

View File

@@ -140,7 +140,8 @@ public:
*/ */
template < template <
typename JobHandler, typename JobHandler,
typename = std::enable_if_t<std::is_same<decltype(std::declval<JobHandler&&>()()), void>::value>> typename =
std::enable_if_t<std::is_same<decltype(std::declval<JobHandler&&>()()), void>::value>>
bool bool
addJob(JobType type, std::string const& name, JobHandler&& jobHandler) addJob(JobType type, std::string const& name, JobHandler&& jobHandler)
{ {

View File

@@ -31,8 +31,16 @@ public:
beast::insight::Event dequeue; beast::insight::Event dequeue;
beast::insight::Event execute; beast::insight::Event execute;
JobTypeData(JobTypeInfo const& info_, beast::insight::Collector::ptr const& collector, Logs& logs) noexcept JobTypeData(
: m_load(logs.journal("LoadMonitor")), m_collector(collector), info(info_), waiting(0), running(0), deferred(0) JobTypeInfo const& info_,
beast::insight::Collector::ptr const& collector,
Logs& logs) noexcept
: m_load(logs.journal("LoadMonitor"))
, m_collector(collector)
, info(info_)
, waiting(0)
, running(0)
, deferred(0)
{ {
m_load.setTargetLatency(info.getAverageLatency(), info.getPeakLatency()); m_load.setTargetLatency(info.getAverageLatency(), info.getPeakLatency());

View File

@@ -32,7 +32,11 @@ public:
int limit, int limit,
std::chrono::milliseconds avgLatency, std::chrono::milliseconds avgLatency,
std::chrono::milliseconds peakLatency) std::chrono::milliseconds peakLatency)
: m_type(type), m_name(std::move(name)), m_limit(limit), m_avgLatency(avgLatency), m_peakLatency(peakLatency) : m_type(type)
, m_name(std::move(name))
, m_limit(limit)
, m_avgLatency(avgLatency)
, m_peakLatency(peakLatency)
{ {
} }

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