mirror of
				https://github.com/XRPLF/clio.git
				synced 2025-11-04 11:55:51 +00:00 
			
		
		
		
	Compare commits
	
		
			207 Commits
		
	
	
		
			2.5.0
			...
			d6ab2cc1e4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d6ab2cc1e4 | ||
| 
						 | 
					13baa42993 | ||
| 
						 | 
					b485fdc18d | ||
| 
						 | 
					7e4e12385f | ||
| 
						 | 
					c117f470f2 | ||
| 
						 | 
					30e88fe72c | ||
| 
						 | 
					cecf082952 | ||
| 
						 | 
					d5b95c2e61 | ||
| 
						 | 
					8375eb1766 | ||
| 
						 | 
					be6aaffa7a | ||
| 
						 | 
					104ef6a9dc | ||
| 
						 | 
					eed757e0c4 | ||
| 
						 | 
					3b61a85ba0 | ||
| 
						 | 
					7c8152d76f | ||
| 
						 | 
					0425d34b55 | ||
| 
						 | 
					8c8a7ff3b8 | ||
| 
						 | 
					16493abd0d | ||
| 
						 | 
					3dd72d94e1 | ||
| 
						 | 
					5e914abf29 | ||
| 
						 | 
					9603968808 | ||
| 
						 | 
					0124c06a53 | ||
| 
						 | 
					1bfdd0dd89 | ||
| 
						 | 
					f41d574204 | ||
| 
						 | 
					d0ec60381b | ||
| 
						 | 
					0b19a42a96 | ||
| 
						 | 
					030f4f1b22 | ||
| 
						 | 
					2de49b4d33 | ||
| 
						 | 
					3de2bf2910 | ||
| 
						 | 
					7538efb01e | ||
| 
						 | 
					685f611434 | ||
| 
						 | 
					2528dee6b6 | ||
| 
						 | 
					b2be4b51d1 | ||
| 
						 | 
					b4e40558c9 | ||
| 
						 | 
					b361e3a108 | ||
| 
						 | 
					a4b47da57a | ||
| 
						 | 
					2ed1a45ef1 | ||
| 
						 | 
					dabaa5bf80 | ||
| 
						 | 
					b4fb3e42b8 | ||
| 
						 | 
					aa64bb7b6b | ||
| 
						 | 
					dc5f8b9c23 | ||
| 
						 | 
					7300529484 | ||
| 
						 | 
					33802f475f | ||
| 
						 | 
					213752862c | ||
| 
						 | 
					a189eeb952 | ||
| 
						 | 
					3c1811233a | ||
| 
						 | 
					693ed2061c | ||
| 
						 | 
					1e2f4b5ca2 | ||
| 
						 | 
					1da8464d75 | ||
| 
						 | 
					d48fb168c6 | ||
| 
						 | 
					92595f95a0 | ||
| 
						 | 
					fc9de87136 | ||
| 
						 | 
					67f5ca445f | ||
| 
						 | 
					897c255b8c | ||
| 
						 | 
					aa9eea0d99 | ||
| 
						 | 
					1cfa06c9aa | ||
| 
						 | 
					2b937bf098 | ||
| 
						 | 
					c6f2197878 | ||
| 
						 | 
					48855633b5 | ||
| 
						 | 
					c26df5e1fb | ||
| 
						 | 
					9fb26d77ed | ||
| 
						 | 
					c3c8b2d796 | ||
| 
						 | 
					2f3e9498dc | ||
| 
						 | 
					d2de240389 | ||
| 
						 | 
					245a808e4b | ||
| 
						 | 
					586a2116a4 | ||
| 
						 | 
					93919ab8b7 | ||
| 
						 | 
					e92a63f4e5 | ||
| 
						 | 
					5e5dd649cf | ||
| 
						 | 
					fb1cdcbde5 | ||
| 
						 | 
					b66d13bc74 | ||
| 
						 | 
					e78ff5c442 | ||
| 
						 | 
					c499f9d679 | ||
| 
						 | 
					420b99cfa1 | ||
| 
						 | 
					3f2ada3439 | ||
| 
						 | 
					e996f2b7ab | ||
| 
						 | 
					26112d17f8 | ||
| 
						 | 
					e4abec4b98 | ||
| 
						 | 
					503e23055b | ||
| 
						 | 
					97480ce626 | ||
| 
						 | 
					bd966e636e | ||
| 
						 | 
					91b248e3b2 | ||
| 
						 | 
					140ac78e15 | ||
| 
						 | 
					f1bf423f69 | ||
| 
						 | 
					dcf369e4ec | ||
| 
						 | 
					56f4dc591c | ||
| 
						 | 
					c40cd8154f | ||
| 
						 | 
					989a0c8468 | ||
| 
						 | 
					1adbed7913 | ||
| 
						 | 
					490ec41083 | ||
| 
						 | 
					384e79cd32 | ||
| 
						 | 
					9edc26a2a3 | ||
| 
						 | 
					08bb619964 | ||
| 
						 | 
					26ef25f864 | ||
| 
						 | 
					a62084a4f0 | ||
| 
						 | 
					b8c298b734 | ||
| 
						 | 
					cf4d5d649a | ||
| 
						 | 
					eb2778ccad | ||
| 
						 | 
					790402bcfb | ||
| 
						 | 
					7c68770787 | ||
| 
						 | 
					d9faf7a833 | ||
| 
						 | 
					90ac03cae7 | ||
| 
						 | 
					3a667f558c | ||
| 
						 | 
					0a2930d861 | ||
| 
						 | 
					e86178b523 | ||
| 
						 | 
					10e15b524f | ||
| 
						 | 
					402ab29a73 | ||
| 
						 | 
					3df28f42ec | ||
| 
						 | 
					0e8896ad06 | ||
| 
						 | 
					ffd18049eb | ||
| 
						 | 
					7413e02a05 | ||
| 
						 | 
					0403248a8f | ||
| 
						 | 
					e6b2f9cde7 | ||
| 
						 | 
					2512a9c8e7 | ||
| 
						 | 
					5e7f6bb5bd | ||
| 
						 | 
					ae15bbd7b5 | ||
| 
						 | 
					33c0737933 | ||
| 
						 | 
					b26fcae690 | ||
| 
						 | 
					60baaf921f | ||
| 
						 | 
					f41e06061f | ||
| 
						 | 
					c170c56a84 | ||
| 
						 | 
					c9c392679d | ||
| 
						 | 
					47f5ae5f12 | ||
| 
						 | 
					6c34458d6c | ||
| 
						 | 
					ec40cc93ff | ||
| 
						 | 
					3681ef4e41 | ||
| 
						 | 
					e2fbf56277 | ||
| 
						 | 
					2d48de372b | ||
| 
						 | 
					c780ef8a0b | ||
| 
						 | 
					d833d36896 | ||
| 
						 | 
					7a2090bc00 | ||
| 
						 | 
					b5892dd139 | ||
| 
						 | 
					a172d0b7ea | ||
| 
						 | 
					e9ab081ab7 | ||
| 
						 | 
					caedb51f00 | ||
| 
						 | 
					e6abdda0a7 | ||
| 
						 | 
					46c96654ee | ||
| 
						 | 
					57ac234657 | ||
| 
						 | 
					4232359dce | ||
| 
						 | 
					8b1cab46e7 | ||
| 
						 | 
					e05505aa4f | ||
| 
						 | 
					73bc85864b | ||
| 
						 | 
					373430924b | ||
| 
						 | 
					8ad111655c | ||
| 
						 | 
					0a8470758d | ||
| 
						 | 
					1ec906addc | ||
| 
						 | 
					afc0a358d9 | ||
| 
						 | 
					af284dda37 | ||
| 
						 | 
					7558348d14 | ||
| 
						 | 
					0d262e74bc | ||
| 
						 | 
					312e7be2b4 | ||
| 
						 | 
					de9b79adf0 | ||
| 
						 | 
					6c68360234 | ||
| 
						 | 
					7e42507b9a | ||
| 
						 | 
					36bfcc7543 | ||
| 
						 | 
					4a5278a915 | ||
| 
						 | 
					333b73e882 | ||
| 
						 | 
					9420c506ca | ||
| 
						 | 
					707427c63a | ||
| 
						 | 
					5eea26d9ac | ||
| 
						 | 
					226d386be2 | ||
| 
						 | 
					c95d8f2f89 | ||
| 
						 | 
					ed5dfc6c0e | ||
| 
						 | 
					2600198bd5 | ||
| 
						 | 
					c83be63b9c | ||
| 
						 | 
					4aa2ca94de | ||
| 
						 | 
					87565b685a | ||
| 
						 | 
					e4d0c1ca48 | ||
| 
						 | 
					498232baf8 | ||
| 
						 | 
					43f4828a61 | ||
| 
						 | 
					1a298dedd2 | ||
| 
						 | 
					6c9c88e3fc | ||
| 
						 | 
					156b858db7 | ||
| 
						 | 
					cfffbfba9d | ||
| 
						 | 
					97a938a2a9 | ||
| 
						 | 
					63d664b9fb | ||
| 
						 | 
					40824812d6 | ||
| 
						 | 
					288ffb8fef | ||
| 
						 | 
					a9cf781ca5 | ||
| 
						 | 
					a446d85297 | ||
| 
						 | 
					dc18aefb33 | ||
| 
						 | 
					e312354016 | ||
| 
						 | 
					ba905e38ae | ||
| 
						 | 
					f35e5ac784 | ||
| 
						 | 
					a9b02fb292 | ||
| 
						 | 
					bc8a2c19aa | ||
| 
						 | 
					46b86a5d61 | ||
| 
						 | 
					3defcaecac | ||
| 
						 | 
					d7888d5556 | ||
| 
						 | 
					f518936e69 | ||
| 
						 | 
					9e35f16be1 | ||
| 
						 | 
					d048641242 | ||
| 
						 | 
					f347a732a6 | ||
| 
						 | 
					0e2ba4a64e | ||
| 
						 | 
					4a4f8842bd | ||
| 
						 | 
					a63805d631 | ||
| 
						 | 
					b3beb50e8f | ||
| 
						 | 
					0be712c363 | ||
| 
						 | 
					ad5f0642ba | ||
| 
						 | 
					4948882545 | ||
| 
						 | 
					5778363689 | ||
| 
						 | 
					d6fec5b5ff | ||
| 
						 | 
					e380214496 | ||
| 
						 | 
					1463b0e3e5 | ||
| 
						 | 
					60bbe1eb72 | ||
| 
						 | 
					b29e2e4c88 | ||
| 
						 | 
					bcaa5f3392 | ||
| 
						 | 
					3f0f20a542 | 
@@ -16,6 +16,7 @@ coverage:
 | 
			
		||||
#
 | 
			
		||||
# More info: https://github.com/XRPLF/clio/pull/2066
 | 
			
		||||
ignore:
 | 
			
		||||
  - "benchmarks"
 | 
			
		||||
  - "tests"
 | 
			
		||||
  - "src/data/cassandra/"
 | 
			
		||||
  - "src/data/CassandraBackend.hpp"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										31
									
								
								.github/actions/build-clio/action.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								.github/actions/build-clio/action.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
name: Build clio
 | 
			
		||||
description: Build clio in build directory
 | 
			
		||||
 | 
			
		||||
inputs:
 | 
			
		||||
  targets:
 | 
			
		||||
    description: Space-separated build target names
 | 
			
		||||
    default: all
 | 
			
		||||
  nproc_subtract:
 | 
			
		||||
    description: The number of processors to subtract when calculating parallelism.
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "0"
 | 
			
		||||
 | 
			
		||||
runs:
 | 
			
		||||
  using: composite
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Get number of processors
 | 
			
		||||
      uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
 | 
			
		||||
      id: nproc
 | 
			
		||||
      with:
 | 
			
		||||
        subtract: ${{ inputs.nproc_subtract }}
 | 
			
		||||
 | 
			
		||||
    - name: Build targets
 | 
			
		||||
      shell: bash
 | 
			
		||||
      env:
 | 
			
		||||
        CMAKE_TARGETS: ${{ inputs.targets }}
 | 
			
		||||
      run: |
 | 
			
		||||
        cd build
 | 
			
		||||
        cmake \
 | 
			
		||||
          --build . \
 | 
			
		||||
          --parallel "${{ steps.nproc.outputs.nproc }}" \
 | 
			
		||||
          --target ${CMAKE_TARGETS}
 | 
			
		||||
@@ -24,6 +24,7 @@ inputs:
 | 
			
		||||
  dockerhub_repo:
 | 
			
		||||
    description: DockerHub repository name
 | 
			
		||||
    required: false
 | 
			
		||||
    default: ""
 | 
			
		||||
  dockerhub_description:
 | 
			
		||||
    description: Short description of the image
 | 
			
		||||
    required: false
 | 
			
		||||
@@ -33,14 +34,14 @@ runs:
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Login to DockerHub
 | 
			
		||||
      if: ${{ inputs.push_image == 'true' && inputs.dockerhub_repo != '' }}
 | 
			
		||||
      uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
 | 
			
		||||
      uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
 | 
			
		||||
      with:
 | 
			
		||||
        username: ${{ env.DOCKERHUB_USER }}
 | 
			
		||||
        password: ${{ env.DOCKERHUB_PW }}
 | 
			
		||||
 | 
			
		||||
    - name: Login to GitHub Container Registry
 | 
			
		||||
      if: ${{ inputs.push_image == 'true' }}
 | 
			
		||||
      uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
 | 
			
		||||
      uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
 | 
			
		||||
      with:
 | 
			
		||||
        registry: ghcr.io
 | 
			
		||||
        username: ${{ github.repository_owner }}
 | 
			
		||||
@@ -51,7 +52,7 @@ runs:
 | 
			
		||||
        cache-image: false
 | 
			
		||||
    - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
 | 
			
		||||
 | 
			
		||||
    - uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
 | 
			
		||||
    - uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
 | 
			
		||||
      id: meta
 | 
			
		||||
      with:
 | 
			
		||||
        images: ${{ inputs.images }}
 | 
			
		||||
							
								
								
									
										29
									
								
								.github/actions/build_clio/action.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								.github/actions/build_clio/action.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,29 +0,0 @@
 | 
			
		||||
name: Build clio
 | 
			
		||||
description: Build clio in build directory
 | 
			
		||||
 | 
			
		||||
inputs:
 | 
			
		||||
  targets:
 | 
			
		||||
    description: Space-separated build target names
 | 
			
		||||
    default: all
 | 
			
		||||
  subtract_threads:
 | 
			
		||||
    description: An option for the action get_number_of_threads. See get_number_of_threads
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "0"
 | 
			
		||||
 | 
			
		||||
runs:
 | 
			
		||||
  using: composite
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Get number of threads
 | 
			
		||||
      uses: ./.github/actions/get_number_of_threads
 | 
			
		||||
      id: number_of_threads
 | 
			
		||||
      with:
 | 
			
		||||
        subtract_threads: ${{ inputs.subtract_threads }}
 | 
			
		||||
 | 
			
		||||
    - name: Build targets
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: |
 | 
			
		||||
        cd build
 | 
			
		||||
        cmake \
 | 
			
		||||
          --build . \
 | 
			
		||||
          --parallel "${{ steps.number_of_threads.outputs.threads_number }}" \
 | 
			
		||||
          --target ${{ inputs.targets }}
 | 
			
		||||
							
								
								
									
										73
									
								
								.github/actions/cmake/action.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								.github/actions/cmake/action.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
name: Run CMake
 | 
			
		||||
description: Run CMake to generate build files
 | 
			
		||||
 | 
			
		||||
inputs:
 | 
			
		||||
  build_dir:
 | 
			
		||||
    description: Build directory
 | 
			
		||||
    required: false
 | 
			
		||||
    default: "build"
 | 
			
		||||
  conan_profile:
 | 
			
		||||
    description: Conan profile name
 | 
			
		||||
    required: true
 | 
			
		||||
  build_type:
 | 
			
		||||
    description: Build type for third-party libraries and clio. Could be 'Release', 'Debug'
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "Release"
 | 
			
		||||
  integration_tests:
 | 
			
		||||
    description: Whether to generate target integration tests
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "true"
 | 
			
		||||
  benchmark:
 | 
			
		||||
    description: Whether to generate targets for benchmarks
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "true"
 | 
			
		||||
  code_coverage:
 | 
			
		||||
    description: Whether to enable code coverage
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "false"
 | 
			
		||||
  static:
 | 
			
		||||
    description: Whether Clio is to be statically linked
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "false"
 | 
			
		||||
  time_trace:
 | 
			
		||||
    description: Whether to enable compiler trace reports
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "false"
 | 
			
		||||
  package:
 | 
			
		||||
    description: Whether to generate Debian package
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "false"
 | 
			
		||||
 | 
			
		||||
runs:
 | 
			
		||||
  using: composite
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Run cmake
 | 
			
		||||
      shell: bash
 | 
			
		||||
      env:
 | 
			
		||||
        BUILD_TYPE: "${{ inputs.build_type }}"
 | 
			
		||||
        SANITIZER_OPTION: |-
 | 
			
		||||
          ${{ endsWith(inputs.conan_profile, '.asan') && '-Dsan=address' ||
 | 
			
		||||
              endsWith(inputs.conan_profile, '.tsan') && '-Dsan=thread' ||
 | 
			
		||||
              endsWith(inputs.conan_profile, '.ubsan') && '-Dsan=undefined' ||
 | 
			
		||||
              '' }}
 | 
			
		||||
        INTEGRATION_TESTS: "${{ inputs.integration_tests == 'true' && 'ON' || 'OFF' }}"
 | 
			
		||||
        BENCHMARK: "${{ inputs.benchmark == 'true' && 'ON' || 'OFF' }}"
 | 
			
		||||
        COVERAGE: "${{ inputs.code_coverage == 'true' && 'ON' || 'OFF' }}"
 | 
			
		||||
        STATIC: "${{ inputs.static == 'true' && 'ON' || 'OFF' }}"
 | 
			
		||||
        TIME_TRACE: "${{ inputs.time_trace == 'true' && 'ON' || 'OFF' }}"
 | 
			
		||||
        PACKAGE: "${{ inputs.package == 'true' && 'ON' || 'OFF' }}"
 | 
			
		||||
      run: |
 | 
			
		||||
        cmake \
 | 
			
		||||
          -B ${{inputs.build_dir}} \
 | 
			
		||||
          -S . \
 | 
			
		||||
          -G Ninja \
 | 
			
		||||
          -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
 | 
			
		||||
          -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
 | 
			
		||||
          "${SANITIZER_OPTION}" \
 | 
			
		||||
          -Dtests=ON \
 | 
			
		||||
          -Dintegration_tests="${INTEGRATION_TESTS}" \
 | 
			
		||||
          -Dbenchmark="${BENCHMARK}" \
 | 
			
		||||
          -Dcoverage="${COVERAGE}" \
 | 
			
		||||
          -Dstatic="${STATIC}" \
 | 
			
		||||
          -Dtime_trace="${TIME_TRACE}" \
 | 
			
		||||
          -Dpackage="${PACKAGE}"
 | 
			
		||||
@@ -15,6 +15,7 @@ runs:
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: |
 | 
			
		||||
        gcovr \
 | 
			
		||||
          -e benchmarks \
 | 
			
		||||
          -e tests \
 | 
			
		||||
          -e src/data/cassandra \
 | 
			
		||||
          -e src/data/CassandraBackend.hpp \
 | 
			
		||||
@@ -23,7 +24,7 @@ runs:
 | 
			
		||||
          -j8 --exclude-throw-branches
 | 
			
		||||
 | 
			
		||||
    - name: Archive coverage report
 | 
			
		||||
      uses: actions/upload-artifact@v4
 | 
			
		||||
      uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
 | 
			
		||||
      with:
 | 
			
		||||
        name: coverage-report.xml
 | 
			
		||||
        path: build/coverage_report.xml
 | 
			
		||||
							
								
								
									
										38
									
								
								.github/actions/conan/action.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								.github/actions/conan/action.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
name: Run Conan
 | 
			
		||||
description: Run conan to install dependencies
 | 
			
		||||
 | 
			
		||||
inputs:
 | 
			
		||||
  build_dir:
 | 
			
		||||
    description: Build directory
 | 
			
		||||
    required: false
 | 
			
		||||
    default: "build"
 | 
			
		||||
  conan_profile:
 | 
			
		||||
    description: Conan profile name
 | 
			
		||||
    required: true
 | 
			
		||||
  force_conan_source_build:
 | 
			
		||||
    description: Whether conan should build all dependencies from source
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "false"
 | 
			
		||||
  build_type:
 | 
			
		||||
    description: Build type for third-party libraries and clio. Could be 'Release', 'Debug'
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "Release"
 | 
			
		||||
 | 
			
		||||
runs:
 | 
			
		||||
  using: composite
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Create build directory
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: mkdir -p "${{ inputs.build_dir }}"
 | 
			
		||||
 | 
			
		||||
    - name: Run conan
 | 
			
		||||
      shell: bash
 | 
			
		||||
      env:
 | 
			
		||||
        CONAN_BUILD_OPTION: "${{ inputs.force_conan_source_build == 'true' && '*' || 'missing' }}"
 | 
			
		||||
      run: |
 | 
			
		||||
        conan \
 | 
			
		||||
          install . \
 | 
			
		||||
          -of build \
 | 
			
		||||
          -b "$CONAN_BUILD_OPTION" \
 | 
			
		||||
          -s "build_type=${{ inputs.build_type }}" \
 | 
			
		||||
          --profile:all "${{ inputs.conan_profile }}"
 | 
			
		||||
@@ -28,12 +28,17 @@ runs:
 | 
			
		||||
    - name: Create an issue
 | 
			
		||||
      id: create_issue
 | 
			
		||||
      shell: bash
 | 
			
		||||
      env:
 | 
			
		||||
        ISSUE_BODY: ${{ inputs.body }}
 | 
			
		||||
        ISSUE_ASSIGNEES: ${{ inputs.assignees }}
 | 
			
		||||
        ISSUE_LABELS: ${{ inputs.labels }}
 | 
			
		||||
        ISSUE_TITLE: ${{ inputs.title }}
 | 
			
		||||
      run: |
 | 
			
		||||
        echo -e '${{ inputs.body }}' > issue.md
 | 
			
		||||
        echo -e "${ISSUE_BODY}" > issue.md
 | 
			
		||||
        gh issue create \
 | 
			
		||||
          --assignee '${{ inputs.assignees }}' \
 | 
			
		||||
          --label '${{ inputs.labels }}' \
 | 
			
		||||
          --title '${{ inputs.title }}' \
 | 
			
		||||
          --assignee "${ISSUE_ASSIGNEES}" \
 | 
			
		||||
          --label "${ISSUE_LABELS}" \
 | 
			
		||||
          --title "${ISSUE_TITLE}" \
 | 
			
		||||
          --body-file ./issue.md \
 | 
			
		||||
          > create_issue.log
 | 
			
		||||
        created_issue="$(sed 's|.*/||' create_issue.log)"
 | 
			
		||||
							
								
								
									
										79
									
								
								.github/actions/generate/action.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										79
									
								
								.github/actions/generate/action.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,79 +0,0 @@
 | 
			
		||||
name: Run conan and cmake
 | 
			
		||||
description: Run conan and cmake
 | 
			
		||||
 | 
			
		||||
inputs:
 | 
			
		||||
  conan_profile:
 | 
			
		||||
    description: Conan profile name
 | 
			
		||||
    required: true
 | 
			
		||||
  force_conan_source_build:
 | 
			
		||||
    description: Whether conan should build all dependencies from source
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "false"
 | 
			
		||||
  build_type:
 | 
			
		||||
    description: Build type for third-party libraries and clio. Could be 'Release', 'Debug'
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "Release"
 | 
			
		||||
  build_integration_tests:
 | 
			
		||||
    description: Whether to build integration tests
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "true"
 | 
			
		||||
  code_coverage:
 | 
			
		||||
    description: Whether conan's coverage option should be on or not
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "false"
 | 
			
		||||
  static:
 | 
			
		||||
    description: Whether Clio is to be statically linked
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "false"
 | 
			
		||||
  time_trace:
 | 
			
		||||
    description: Whether to enable compiler trace reports
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "false"
 | 
			
		||||
 | 
			
		||||
runs:
 | 
			
		||||
  using: composite
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Create build directory
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: mkdir -p build
 | 
			
		||||
 | 
			
		||||
    - name: Run conan
 | 
			
		||||
      shell: bash
 | 
			
		||||
      env:
 | 
			
		||||
        CONAN_BUILD_OPTION: "${{ inputs.force_conan_source_build == 'true' && '*' || 'missing' }}"
 | 
			
		||||
        CODE_COVERAGE: "${{ inputs.code_coverage == 'true' && 'True' || 'False' }}"
 | 
			
		||||
        STATIC_OPTION: "${{ inputs.static == 'true' && 'True' || 'False' }}"
 | 
			
		||||
        INTEGRATION_TESTS_OPTION: "${{ inputs.build_integration_tests == 'true' && 'True' || 'False' }}"
 | 
			
		||||
        TIME_TRACE: "${{ inputs.time_trace == 'true' && 'True' || 'False' }}"
 | 
			
		||||
      run: |
 | 
			
		||||
        cd build
 | 
			
		||||
        conan \
 | 
			
		||||
          install .. \
 | 
			
		||||
          -of . \
 | 
			
		||||
          -b "$CONAN_BUILD_OPTION" \
 | 
			
		||||
          -s "build_type=${{ inputs.build_type }}" \
 | 
			
		||||
          -o "&:static=${STATIC_OPTION}" \
 | 
			
		||||
          -o "&:tests=True" \
 | 
			
		||||
          -o "&:integration_tests=${INTEGRATION_TESTS_OPTION}" \
 | 
			
		||||
          -o "&:lint=False" \
 | 
			
		||||
          -o "&:coverage=${CODE_COVERAGE}" \
 | 
			
		||||
          -o "&:time_trace=${TIME_TRACE}" \
 | 
			
		||||
          --profile:all "${{ inputs.conan_profile }}"
 | 
			
		||||
 | 
			
		||||
    - name: Run cmake
 | 
			
		||||
      shell: bash
 | 
			
		||||
      env:
 | 
			
		||||
        BUILD_TYPE: "${{ inputs.build_type }}"
 | 
			
		||||
        SANITIZER_OPTION: |-
 | 
			
		||||
          ${{ endsWith(inputs.conan_profile, '.asan') && '-Dsan=address' ||
 | 
			
		||||
              endsWith(inputs.conan_profile, '.tsan') && '-Dsan=thread' ||
 | 
			
		||||
              endsWith(inputs.conan_profile, '.ubsan') && '-Dsan=undefined' ||
 | 
			
		||||
              '' }}
 | 
			
		||||
      run: |
 | 
			
		||||
        cd build
 | 
			
		||||
        cmake \
 | 
			
		||||
          -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
 | 
			
		||||
          -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
 | 
			
		||||
          "${SANITIZER_OPTION}" \
 | 
			
		||||
          .. \
 | 
			
		||||
          -G Ninja
 | 
			
		||||
							
								
								
									
										36
									
								
								.github/actions/get_number_of_threads/action.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								.github/actions/get_number_of_threads/action.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,36 +0,0 @@
 | 
			
		||||
name: Get number of threads
 | 
			
		||||
description: Determines number of threads to use on macOS and Linux
 | 
			
		||||
 | 
			
		||||
inputs:
 | 
			
		||||
  subtract_threads:
 | 
			
		||||
    description: How many threads to subtract from the calculated number
 | 
			
		||||
    required: true
 | 
			
		||||
    default: "0"
 | 
			
		||||
outputs:
 | 
			
		||||
  threads_number:
 | 
			
		||||
    description: Number of threads to use
 | 
			
		||||
    value: ${{ steps.number_of_threads_export.outputs.num }}
 | 
			
		||||
 | 
			
		||||
runs:
 | 
			
		||||
  using: composite
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Get number of threads on mac
 | 
			
		||||
      id: mac_threads
 | 
			
		||||
      if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: echo "num=$(($(sysctl -n hw.logicalcpu) - 2))" >> $GITHUB_OUTPUT
 | 
			
		||||
 | 
			
		||||
    - name: Get number of threads on Linux
 | 
			
		||||
      id: linux_threads
 | 
			
		||||
      if: ${{ runner.os == 'Linux' }}
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: echo "num=$(($(nproc) - 2))" >> $GITHUB_OUTPUT
 | 
			
		||||
 | 
			
		||||
    - name: Shift and export number of threads
 | 
			
		||||
      id: number_of_threads_export
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: |
 | 
			
		||||
        num_of_threads="${{ steps.mac_threads.outputs.num || steps.linux_threads.outputs.num }}"
 | 
			
		||||
        shift_by="${{ inputs.subtract_threads }}"
 | 
			
		||||
        shifted="$((num_of_threads - shift_by))"
 | 
			
		||||
        echo "num=$(( shifted > 1 ? shifted : 1 ))" >> $GITHUB_OUTPUT
 | 
			
		||||
							
								
								
									
										77
									
								
								.github/actions/prepare_runner/action.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										77
									
								
								.github/actions/prepare_runner/action.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,77 +0,0 @@
 | 
			
		||||
name: Prepare runner
 | 
			
		||||
description: Install packages, set environment variables, create directories
 | 
			
		||||
 | 
			
		||||
inputs:
 | 
			
		||||
  disable_ccache:
 | 
			
		||||
    description: Whether ccache should be disabled
 | 
			
		||||
    required: true
 | 
			
		||||
 | 
			
		||||
runs:
 | 
			
		||||
  using: composite
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Install packages on mac
 | 
			
		||||
      if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: |
 | 
			
		||||
        brew install --quiet \
 | 
			
		||||
          bison \
 | 
			
		||||
          ca-certificates \
 | 
			
		||||
          ccache \
 | 
			
		||||
          clang-build-analyzer \
 | 
			
		||||
          conan \
 | 
			
		||||
          gh \
 | 
			
		||||
          jq \
 | 
			
		||||
          llvm@14 \
 | 
			
		||||
          ninja \
 | 
			
		||||
          pkg-config
 | 
			
		||||
        echo "/opt/homebrew/opt/conan@2/bin" >> $GITHUB_PATH
 | 
			
		||||
 | 
			
		||||
    - name: Install CMake 3.31.6 on mac
 | 
			
		||||
      if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: |
 | 
			
		||||
        # Uninstall any existing cmake
 | 
			
		||||
        brew uninstall --formula cmake --ignore-dependencies || true
 | 
			
		||||
 | 
			
		||||
        # Download specific cmake formula
 | 
			
		||||
        FORMULA_URL="https://raw.githubusercontent.com/Homebrew/homebrew-core/b4e46db74e74a8c1650b38b1da222284ce1ec5ce/Formula/c/cmake.rb"
 | 
			
		||||
        FORMULA_EXPECTED_SHA256="c7ec95d86f0657638835441871e77541165e0a2581b53b3dd657cf13ad4228d4"
 | 
			
		||||
 | 
			
		||||
        mkdir -p /tmp/homebrew-formula
 | 
			
		||||
        curl -s -L "$FORMULA_URL" -o /tmp/homebrew-formula/cmake.rb
 | 
			
		||||
 | 
			
		||||
        echo "$FORMULA_EXPECTED_SHA256  /tmp/homebrew-formula/cmake.rb" | shasum -a 256 -c
 | 
			
		||||
 | 
			
		||||
        # Install cmake from the specific formula with force flag
 | 
			
		||||
        brew install --formula --quiet --force /tmp/homebrew-formula/cmake.rb
 | 
			
		||||
 | 
			
		||||
    - name: Fix git permissions on Linux
 | 
			
		||||
      if: ${{ runner.os == 'Linux' }}
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: git config --global --add safe.directory "$PWD"
 | 
			
		||||
 | 
			
		||||
    - name: Set env variables for macOS
 | 
			
		||||
      if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: |
 | 
			
		||||
        echo "CCACHE_DIR=${{ github.workspace }}/.ccache" >> $GITHUB_ENV
 | 
			
		||||
        echo "CONAN_HOME=${{ github.workspace }}/.conan2" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
    - name: Set env variables for Linux
 | 
			
		||||
      if: ${{ runner.os == 'Linux' }}
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: |
 | 
			
		||||
        echo "CCACHE_DIR=/root/.ccache" >> $GITHUB_ENV
 | 
			
		||||
        echo "CONAN_HOME=/root/.conan2" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
    - name: Set CCACHE_DISABLE=1
 | 
			
		||||
      if: ${{ inputs.disable_ccache == 'true' }}
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: |
 | 
			
		||||
        echo "CCACHE_DISABLE=1" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
    - name: Create directories
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: |
 | 
			
		||||
        mkdir -p "$CCACHE_DIR"
 | 
			
		||||
        mkdir -p "$CONAN_HOME"
 | 
			
		||||
@@ -27,10 +27,10 @@ runs:
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Find common commit
 | 
			
		||||
      id: git_common_ancestor
 | 
			
		||||
      uses: ./.github/actions/git_common_ancestor
 | 
			
		||||
      uses: ./.github/actions/git-common-ancestor
 | 
			
		||||
 | 
			
		||||
    - name: Restore ccache cache
 | 
			
		||||
      uses: actions/cache/restore@v4
 | 
			
		||||
      uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
 | 
			
		||||
      id: ccache_cache
 | 
			
		||||
      if: ${{ env.CCACHE_DISABLE != '1' }}
 | 
			
		||||
      with:
 | 
			
		||||
@@ -28,11 +28,11 @@ runs:
 | 
			
		||||
  steps:
 | 
			
		||||
    - name: Find common commit
 | 
			
		||||
      id: git_common_ancestor
 | 
			
		||||
      uses: ./.github/actions/git_common_ancestor
 | 
			
		||||
      uses: ./.github/actions/git-common-ancestor
 | 
			
		||||
 | 
			
		||||
    - name: Save ccache cache
 | 
			
		||||
      if: ${{ inputs.ccache_cache_hit != 'true' || inputs.ccache_cache_miss_rate == '100.0' }}
 | 
			
		||||
      uses: actions/cache/save@v4
 | 
			
		||||
      uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
 | 
			
		||||
      with:
 | 
			
		||||
        path: ${{ inputs.ccache_dir }}
 | 
			
		||||
        key: clio-ccache-${{ runner.os }}-${{ inputs.build_type }}${{ inputs.code_coverage == 'true' && '-code_coverage' || '' }}-${{ inputs.conan_profile }}-develop-${{ steps.git_common_ancestor.outputs.commit }}
 | 
			
		||||
							
								
								
									
										31
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							@@ -14,7 +14,7 @@ updates:
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/build_clio/
 | 
			
		||||
    directory: .github/actions/build-clio/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
@@ -27,7 +27,7 @@ updates:
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/build_docker_image/
 | 
			
		||||
    directory: .github/actions/build-docker-image/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
@@ -40,7 +40,7 @@ updates:
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/code_coverage/
 | 
			
		||||
    directory: .github/actions/cmake/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
@@ -53,7 +53,7 @@ updates:
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/create_issue/
 | 
			
		||||
    directory: .github/actions/code-coverage/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
@@ -66,7 +66,7 @@ updates:
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/generate/
 | 
			
		||||
    directory: .github/actions/conan/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
@@ -79,7 +79,7 @@ updates:
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/get_number_of_threads/
 | 
			
		||||
    directory: .github/actions/create-issue/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
@@ -92,7 +92,7 @@ updates:
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/git_common_ancestor/
 | 
			
		||||
    directory: .github/actions/git-common-ancestor/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
@@ -105,7 +105,7 @@ updates:
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/prepare_runner/
 | 
			
		||||
    directory: .github/actions/restore-cache/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
@@ -118,20 +118,7 @@ updates:
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/restore_cache/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
      time: "04:00"
 | 
			
		||||
      timezone: Etc/GMT
 | 
			
		||||
    reviewers:
 | 
			
		||||
      - XRPLF/clio-dev-team
 | 
			
		||||
    commit-message:
 | 
			
		||||
      prefix: "ci: [DEPENDABOT] "
 | 
			
		||||
    target-branch: develop
 | 
			
		||||
 | 
			
		||||
  - package-ecosystem: github-actions
 | 
			
		||||
    directory: .github/actions/save_cache/
 | 
			
		||||
    directory: .github/actions/save-cache/
 | 
			
		||||
    schedule:
 | 
			
		||||
      interval: weekly
 | 
			
		||||
      day: monday
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								.github/scripts/conan/apple-clang-ci.profile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/scripts/conan/apple-clang-ci.profile
									
									
									
									
										vendored
									
									
								
							@@ -1,8 +0,0 @@
 | 
			
		||||
[settings]
 | 
			
		||||
arch={{detect_api.detect_arch()}}
 | 
			
		||||
build_type=Release
 | 
			
		||||
compiler=apple-clang
 | 
			
		||||
compiler.cppstd=20
 | 
			
		||||
compiler.libcxx=libc++
 | 
			
		||||
compiler.version=16
 | 
			
		||||
os=Macos
 | 
			
		||||
							
								
								
									
										4
									
								
								.github/scripts/conan/generate_matrix.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/scripts/conan/generate_matrix.py
									
									
									
									
										vendored
									
									
								
							@@ -3,7 +3,9 @@ import itertools
 | 
			
		||||
import json
 | 
			
		||||
 | 
			
		||||
LINUX_OS = ["heavy", "heavy-arm64"]
 | 
			
		||||
LINUX_CONTAINERS = ['{ "image": "ghcr.io/xrplf/clio-ci:latest" }']
 | 
			
		||||
LINUX_CONTAINERS = [
 | 
			
		||||
    '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
]
 | 
			
		||||
LINUX_COMPILERS = ["gcc", "clang"]
 | 
			
		||||
 | 
			
		||||
MACOS_OS = ["macos15"]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								.github/scripts/conan/init.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.github/scripts/conan/init.sh
									
									
									
									
										vendored
									
									
								
							@@ -8,10 +8,11 @@ REPO_DIR="$(cd "$CURRENT_DIR/../../../" && pwd)"
 | 
			
		||||
CONAN_DIR="${CONAN_HOME:-$HOME/.conan2}"
 | 
			
		||||
PROFILES_DIR="$CONAN_DIR/profiles"
 | 
			
		||||
 | 
			
		||||
# When developers' compilers are updated, these profiles might be different
 | 
			
		||||
if [[ -z "$CI" ]]; then
 | 
			
		||||
    APPLE_CLANG_PROFILE="$CURRENT_DIR/apple-clang-local.profile"
 | 
			
		||||
    APPLE_CLANG_PROFILE="$CURRENT_DIR/apple-clang-17.profile"
 | 
			
		||||
else
 | 
			
		||||
    APPLE_CLANG_PROFILE="$CURRENT_DIR/apple-clang-ci.profile"
 | 
			
		||||
    APPLE_CLANG_PROFILE="$CURRENT_DIR/apple-clang-17.profile"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
GCC_PROFILE="$REPO_DIR/docker/ci/conan/gcc.profile"
 | 
			
		||||
@@ -21,7 +22,7 @@ SANITIZER_TEMPLATE_FILE="$REPO_DIR/docker/ci/conan/sanitizer_template.profile"
 | 
			
		||||
 | 
			
		||||
rm -rf "$CONAN_DIR"
 | 
			
		||||
 | 
			
		||||
conan remote add --index 0 ripple http://18.143.149.228:8081/artifactory/api/conan/dev
 | 
			
		||||
conan remote add --index 0 xrplf https://conan.ripplex.io
 | 
			
		||||
 | 
			
		||||
cp "$REPO_DIR/docker/ci/conan/global.conf" "$CONAN_DIR/global.conf"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -31,15 +31,16 @@ TESTS=$($TEST_BINARY --gtest_list_tests | awk '/^  / {print suite $1} !/^  / {su
 | 
			
		||||
OUTPUT_DIR="./.sanitizer-report"
 | 
			
		||||
mkdir -p "$OUTPUT_DIR"
 | 
			
		||||
 | 
			
		||||
export TSAN_OPTIONS="die_after_fork=0"
 | 
			
		||||
export MallocNanoZone='0' # for MacOSX
 | 
			
		||||
 | 
			
		||||
for TEST in $TESTS; do
 | 
			
		||||
  OUTPUT_FILE="$OUTPUT_DIR/${TEST//\//_}"
 | 
			
		||||
  export TSAN_OPTIONS="log_path=\"$OUTPUT_FILE\" die_after_fork=0"
 | 
			
		||||
  export ASAN_OPTIONS="log_path=\"$OUTPUT_FILE\""
 | 
			
		||||
  export UBSAN_OPTIONS="log_path=\"$OUTPUT_FILE\""
 | 
			
		||||
  export MallocNanoZone='0' # for MacOSX
 | 
			
		||||
  $TEST_BINARY --gtest_filter="$TEST" > /dev/null 2>&1
 | 
			
		||||
  OUTPUT_FILE="$OUTPUT_DIR/${TEST//\//_}.log"
 | 
			
		||||
  $TEST_BINARY --gtest_filter="$TEST" > "$OUTPUT_FILE" 2>&1
 | 
			
		||||
 | 
			
		||||
  if [ $? -ne 0 ]; then
 | 
			
		||||
    echo "'$TEST' failed a sanitizer check."
 | 
			
		||||
  else
 | 
			
		||||
    rm "$OUTPUT_FILE"
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
@@ -44,11 +44,11 @@ jobs:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Download Clio binary from artifact
 | 
			
		||||
        if: ${{ inputs.artifact_name != null }}
 | 
			
		||||
        uses: actions/download-artifact@v4
 | 
			
		||||
        uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: ${{ inputs.artifact_name }}
 | 
			
		||||
          path: ./docker/clio/artifact/
 | 
			
		||||
@@ -56,9 +56,12 @@ jobs:
 | 
			
		||||
      - name: Download Clio binary from url
 | 
			
		||||
        if: ${{ inputs.clio_server_binary_url != null }}
 | 
			
		||||
        shell: bash
 | 
			
		||||
        env:
 | 
			
		||||
          BINARY_URL: ${{ inputs.clio_server_binary_url }}
 | 
			
		||||
          BINARY_SHA256: ${{ inputs.binary_sha256 }}
 | 
			
		||||
        run: |
 | 
			
		||||
          wget "${{inputs.clio_server_binary_url}}" -P ./docker/clio/artifact/
 | 
			
		||||
          if [ "$(sha256sum ./docker/clio/clio_server | awk '{print $1}')" != "${{inputs.binary_sha256}}" ]; then
 | 
			
		||||
          wget "${BINARY_URL}" -P ./docker/clio/artifact/
 | 
			
		||||
          if [ "$(sha256sum ./docker/clio/clio_server | awk '{print $1}')" != "${BINARY_SHA256}" ]; then
 | 
			
		||||
            echo "Binary sha256 sum doesn't match"
 | 
			
		||||
            exit 1
 | 
			
		||||
          fi
 | 
			
		||||
@@ -73,7 +76,8 @@ jobs:
 | 
			
		||||
          elif [[ $artifact == *.tar.gz ]]; then
 | 
			
		||||
            tar -xvf $artifact
 | 
			
		||||
          fi
 | 
			
		||||
          mv clio_server ../
 | 
			
		||||
          chmod +x ./clio_server
 | 
			
		||||
          mv ./clio_server ../
 | 
			
		||||
          cd ../
 | 
			
		||||
          rm -rf ./artifact
 | 
			
		||||
 | 
			
		||||
@@ -82,19 +86,24 @@ jobs:
 | 
			
		||||
        shell: bash
 | 
			
		||||
        run: strip ./docker/clio/clio_server
 | 
			
		||||
 | 
			
		||||
      - name: Set GHCR_REPO
 | 
			
		||||
        id: set-ghcr-repo
 | 
			
		||||
        run: |
 | 
			
		||||
          echo "GHCR_REPO=$(echo ghcr.io/${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> ${GITHUB_OUTPUT}
 | 
			
		||||
 | 
			
		||||
      - name: Build Docker image
 | 
			
		||||
        uses: ./.github/actions/build_docker_image
 | 
			
		||||
        uses: ./.github/actions/build-docker-image
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
          DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
 | 
			
		||||
          DOCKERHUB_PW: ${{ secrets.DOCKERHUB_PW }}
 | 
			
		||||
        with:
 | 
			
		||||
          images: |
 | 
			
		||||
            ghcr.io/xrplf/clio
 | 
			
		||||
            rippleci/clio
 | 
			
		||||
            ghcr.io/${{ steps.set-ghcr-repo.outputs.GHCR_REPO }}/clio
 | 
			
		||||
            ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio' || '' }}
 | 
			
		||||
          push_image: ${{ inputs.publish_image }}
 | 
			
		||||
          directory: docker/clio
 | 
			
		||||
          tags: ${{ inputs.tags }}
 | 
			
		||||
          platforms: linux/amd64
 | 
			
		||||
          dockerhub_repo: rippleci/clio
 | 
			
		||||
          dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio' || '' }}
 | 
			
		||||
          dockerhub_description: Clio is an XRP Ledger API server.
 | 
			
		||||
							
								
								
									
										57
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							@@ -8,14 +8,14 @@ on:
 | 
			
		||||
    paths:
 | 
			
		||||
      - .github/workflows/build.yml
 | 
			
		||||
 | 
			
		||||
      - .github/workflows/build_and_test.yml
 | 
			
		||||
      - .github/workflows/build_impl.yml
 | 
			
		||||
      - .github/workflows/test_impl.yml
 | 
			
		||||
      - .github/workflows/upload_coverage_report.yml
 | 
			
		||||
      - .github/workflows/reusable-build-test.yml
 | 
			
		||||
      - .github/workflows/reusable-build.yml
 | 
			
		||||
      - .github/workflows/reusable-test.yml
 | 
			
		||||
      - .github/workflows/reusable-upload-coverage-report.yml
 | 
			
		||||
 | 
			
		||||
      - ".github/actions/**"
 | 
			
		||||
      - "!.github/actions/build_docker_image/**"
 | 
			
		||||
      - "!.github/actions/create_issue/**"
 | 
			
		||||
      - "!.github/actions/build-docker-image/**"
 | 
			
		||||
      - "!.github/actions/create-issue/**"
 | 
			
		||||
 | 
			
		||||
      - CMakeLists.txt
 | 
			
		||||
      - conanfile.py
 | 
			
		||||
@@ -28,8 +28,9 @@ on:
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
 | 
			
		||||
concurrency:
 | 
			
		||||
  # Only cancel in-progress jobs or runs for the current workflow - matches against branch & tags
 | 
			
		||||
  group: ${{ github.workflow }}-${{ github.ref }}
 | 
			
		||||
  # Develop branch: Each run gets unique group (using run_number) for parallel execution
 | 
			
		||||
  # Other branches: Shared group with cancel-in-progress to stop old runs when new commits are pushed
 | 
			
		||||
  group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/develop' && github.run_number || 'branch' }}
 | 
			
		||||
  cancel-in-progress: true
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
@@ -42,7 +43,10 @@ jobs:
 | 
			
		||||
        os: [heavy]
 | 
			
		||||
        conan_profile: [gcc, clang]
 | 
			
		||||
        build_type: [Release, Debug]
 | 
			
		||||
        container: ['{ "image": "ghcr.io/xrplf/clio-ci:latest" }']
 | 
			
		||||
        container:
 | 
			
		||||
          [
 | 
			
		||||
            '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }',
 | 
			
		||||
          ]
 | 
			
		||||
        static: [true]
 | 
			
		||||
 | 
			
		||||
        include:
 | 
			
		||||
@@ -52,12 +56,14 @@ jobs:
 | 
			
		||||
            container: ""
 | 
			
		||||
            static: false
 | 
			
		||||
 | 
			
		||||
    uses: ./.github/workflows/build_and_test.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-build-test.yml
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: ${{ matrix.os }}
 | 
			
		||||
      container: ${{ matrix.container }}
 | 
			
		||||
      conan_profile: ${{ matrix.conan_profile }}
 | 
			
		||||
      build_type: ${{ matrix.build_type }}
 | 
			
		||||
      download_ccache: true
 | 
			
		||||
      upload_ccache: true
 | 
			
		||||
      static: ${{ matrix.static }}
 | 
			
		||||
      run_unit_tests: true
 | 
			
		||||
      run_integration_tests: false
 | 
			
		||||
@@ -66,13 +72,14 @@ jobs:
 | 
			
		||||
  code_coverage:
 | 
			
		||||
    name: Run Code Coverage
 | 
			
		||||
 | 
			
		||||
    uses: ./.github/workflows/build_impl.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-build.yml
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: heavy
 | 
			
		||||
      container: '{ "image": "ghcr.io/xrplf/clio-ci:latest" }'
 | 
			
		||||
      container: '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
      conan_profile: gcc
 | 
			
		||||
      build_type: Debug
 | 
			
		||||
      disable_cache: false
 | 
			
		||||
      download_ccache: true
 | 
			
		||||
      upload_ccache: false
 | 
			
		||||
      code_coverage: true
 | 
			
		||||
      static: true
 | 
			
		||||
      upload_clio_server: false
 | 
			
		||||
@@ -81,17 +88,35 @@ jobs:
 | 
			
		||||
    secrets:
 | 
			
		||||
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
 | 
			
		||||
 | 
			
		||||
  package:
 | 
			
		||||
    name: Build packages
 | 
			
		||||
 | 
			
		||||
    uses: ./.github/workflows/reusable-build.yml
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: heavy
 | 
			
		||||
      container: '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
      conan_profile: gcc
 | 
			
		||||
      build_type: Release
 | 
			
		||||
      download_ccache: true
 | 
			
		||||
      upload_ccache: false
 | 
			
		||||
      code_coverage: false
 | 
			
		||||
      static: true
 | 
			
		||||
      upload_clio_server: false
 | 
			
		||||
      package: true
 | 
			
		||||
      targets: package
 | 
			
		||||
      analyze_build_time: false
 | 
			
		||||
 | 
			
		||||
  check_config:
 | 
			
		||||
    name: Check Config Description
 | 
			
		||||
    needs: build-and-test
 | 
			
		||||
    runs-on: heavy
 | 
			
		||||
    container:
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:latest
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - uses: actions/download-artifact@v4
 | 
			
		||||
      - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: clio_server_Linux_Release_gcc
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,42 +17,47 @@ jobs:
 | 
			
		||||
    name: Build Clio / `libXRPL ${{ github.event.client_payload.version }}`
 | 
			
		||||
    runs-on: heavy
 | 
			
		||||
    container:
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:latest
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0
 | 
			
		||||
 | 
			
		||||
      - name: Prepare runner
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
 | 
			
		||||
        with:
 | 
			
		||||
          disable_ccache: true
 | 
			
		||||
 | 
			
		||||
      - name: Update libXRPL version requirement
 | 
			
		||||
        shell: bash
 | 
			
		||||
        run: |
 | 
			
		||||
          sed -i.bak -E "s|'xrpl/[a-zA-Z0-9\\.\\-]+'|'xrpl/${{ github.event.client_payload.version }}'|g" conanfile.py
 | 
			
		||||
          sed -i.bak -E "s|'xrpl/[a-zA-Z0-9\\.\\-]+'|'xrpl/${{ github.event.client_payload.conan_ref }}'|g" conanfile.py
 | 
			
		||||
          rm -f conanfile.py.bak
 | 
			
		||||
 | 
			
		||||
      - name: Update conan lockfile
 | 
			
		||||
        shell: bash
 | 
			
		||||
        run: |
 | 
			
		||||
          conan lock create . -o '&:tests=True' -o '&:benchmark=True'
 | 
			
		||||
          conan lock create . --profile:all ${{ env.CONAN_PROFILE }}
 | 
			
		||||
 | 
			
		||||
      - name: Prepare runner
 | 
			
		||||
        uses: ./.github/actions/prepare_runner
 | 
			
		||||
      - name: Run conan
 | 
			
		||||
        uses: ./.github/actions/conan
 | 
			
		||||
        with:
 | 
			
		||||
          disable_ccache: true
 | 
			
		||||
          conan_profile: ${{ env.CONAN_PROFILE }}
 | 
			
		||||
 | 
			
		||||
      - name: Run conan and cmake
 | 
			
		||||
        uses: ./.github/actions/generate
 | 
			
		||||
      - name: Run CMake
 | 
			
		||||
        uses: ./.github/actions/cmake
 | 
			
		||||
        with:
 | 
			
		||||
          conan_profile: ${{ env.CONAN_PROFILE }}
 | 
			
		||||
 | 
			
		||||
      - name: Build Clio
 | 
			
		||||
        uses: ./.github/actions/build_clio
 | 
			
		||||
        uses: ./.github/actions/build-clio
 | 
			
		||||
 | 
			
		||||
      - name: Strip tests
 | 
			
		||||
        run: strip build/clio_tests
 | 
			
		||||
 | 
			
		||||
      - name: Upload clio_tests
 | 
			
		||||
        uses: actions/upload-artifact@v4
 | 
			
		||||
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: clio_tests_check_libxrpl
 | 
			
		||||
          path: build/clio_tests
 | 
			
		||||
@@ -62,10 +67,10 @@ jobs:
 | 
			
		||||
    needs: build
 | 
			
		||||
    runs-on: heavy
 | 
			
		||||
    container:
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:latest
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/download-artifact@v4
 | 
			
		||||
      - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: clio_tests_check_libxrpl
 | 
			
		||||
 | 
			
		||||
@@ -85,16 +90,17 @@ jobs:
 | 
			
		||||
      issues: write
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Create an issue
 | 
			
		||||
        uses: ./.github/actions/create_issue
 | 
			
		||||
        uses: ./.github/actions/create-issue
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ github.token }}
 | 
			
		||||
        with:
 | 
			
		||||
          labels: "compatibility,bug"
 | 
			
		||||
          title: "Proposed libXRPL check failed"
 | 
			
		||||
          body: >
 | 
			
		||||
            Clio build or tests failed against `libXRPL ${{ github.event.client_payload.version }}`.
 | 
			
		||||
            Clio build or tests failed against `libXRPL ${{ github.event.client_payload.conan_ref }}`.
 | 
			
		||||
 | 
			
		||||
            Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
 | 
			
		||||
            PR: ${{ github.event.client_payload.pr_url }}
 | 
			
		||||
            Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
 | 
			
		||||
@@ -10,8 +10,17 @@ jobs:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: ytanikin/pr-conventional-commits@8267db1bacc237419f9ed0228bb9d94e94271a1d # v1.4.1
 | 
			
		||||
      - uses: ytanikin/pr-conventional-commits@b72758283dcbee706975950e96bc4bf323a8d8c0 # 1.4.2
 | 
			
		||||
        with:
 | 
			
		||||
          task_types: '["build","feat","fix","docs","test","ci","style","refactor","perf","chore"]'
 | 
			
		||||
          add_label: false
 | 
			
		||||
          custom_labels: '{"build":"build", "feat":"enhancement", "fix":"bug", "docs":"documentation", "test":"testability", "ci":"ci", "style":"refactoring", "refactor":"refactoring", "perf":"performance", "chore":"tooling"}'
 | 
			
		||||
 | 
			
		||||
      - name: Check if message starts with upper-case letter
 | 
			
		||||
        env:
 | 
			
		||||
          PR_TITLE: ${{ github.event.pull_request.title }}
 | 
			
		||||
        run: |
 | 
			
		||||
          if [[ ! "${PR_TITLE}" =~ ^[a-z]+:\ [\[A-Z] ]]; then
 | 
			
		||||
            echo "Error: PR title must start with an upper-case letter."
 | 
			
		||||
            exit 1
 | 
			
		||||
          fi
 | 
			
		||||
							
								
								
									
										30
									
								
								.github/workflows/clang-tidy.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								.github/workflows/clang-tidy.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,8 @@
 | 
			
		||||
name: Clang-tidy check
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches: [develop]
 | 
			
		||||
  schedule:
 | 
			
		||||
    - cron: "0 9 * * 1-5"
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
@@ -22,9 +24,10 @@ env:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  clang_tidy:
 | 
			
		||||
    if: github.event_name != 'push' || contains(github.event.head_commit.message, 'clang-tidy auto fixes')
 | 
			
		||||
    runs-on: heavy
 | 
			
		||||
    container:
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:latest
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a
 | 
			
		||||
 | 
			
		||||
    permissions:
 | 
			
		||||
      contents: write
 | 
			
		||||
@@ -32,37 +35,42 @@ jobs:
 | 
			
		||||
      pull-requests: write
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0
 | 
			
		||||
 | 
			
		||||
      - name: Prepare runner
 | 
			
		||||
        uses: ./.github/actions/prepare_runner
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
 | 
			
		||||
        with:
 | 
			
		||||
          disable_ccache: true
 | 
			
		||||
 | 
			
		||||
      - name: Restore cache
 | 
			
		||||
        uses: ./.github/actions/restore_cache
 | 
			
		||||
        uses: ./.github/actions/restore-cache
 | 
			
		||||
        id: restore_cache
 | 
			
		||||
        with:
 | 
			
		||||
          conan_profile: ${{ env.CONAN_PROFILE }}
 | 
			
		||||
          ccache_dir: ${{ env.CCACHE_DIR }}
 | 
			
		||||
 | 
			
		||||
      - name: Run conan and cmake
 | 
			
		||||
        uses: ./.github/actions/generate
 | 
			
		||||
      - name: Run conan
 | 
			
		||||
        uses: ./.github/actions/conan
 | 
			
		||||
        with:
 | 
			
		||||
          conan_profile: ${{ env.CONAN_PROFILE }}
 | 
			
		||||
 | 
			
		||||
      - name: Get number of threads
 | 
			
		||||
        uses: ./.github/actions/get_number_of_threads
 | 
			
		||||
        id: number_of_threads
 | 
			
		||||
      - name: Run CMake
 | 
			
		||||
        uses: ./.github/actions/cmake
 | 
			
		||||
        with:
 | 
			
		||||
          conan_profile: ${{ env.CONAN_PROFILE }}
 | 
			
		||||
 | 
			
		||||
      - name: Get number of processors
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
 | 
			
		||||
        id: nproc
 | 
			
		||||
 | 
			
		||||
      - name: Run clang-tidy
 | 
			
		||||
        continue-on-error: true
 | 
			
		||||
        shell: bash
 | 
			
		||||
        id: run_clang_tidy
 | 
			
		||||
        run: |
 | 
			
		||||
          run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j "${{ steps.number_of_threads.outputs.threads_number }}" -fix -quiet 1>output.txt
 | 
			
		||||
          run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j "${{ steps.nproc.outputs.nproc }}" -fix -quiet 1>output.txt
 | 
			
		||||
 | 
			
		||||
      - name: Fix local includes and clang-format style
 | 
			
		||||
        if: ${{ steps.run_clang_tidy.outcome != 'success' }}
 | 
			
		||||
@@ -82,7 +90,7 @@ jobs:
 | 
			
		||||
      - name: Create an issue
 | 
			
		||||
        if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
 | 
			
		||||
        id: create_issue
 | 
			
		||||
        uses: ./.github/actions/create_issue
 | 
			
		||||
        uses: ./.github/actions/create-issue
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ github.token }}
 | 
			
		||||
        with:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								.github/workflows/clang-tidy_on_fix_merged.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								.github/workflows/clang-tidy_on_fix_merged.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,30 +0,0 @@
 | 
			
		||||
name: Restart clang-tidy workflow
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches: [develop]
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  restart_clang_tidy:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    permissions:
 | 
			
		||||
      actions: write
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - name: Check last commit matches clang-tidy auto fixes
 | 
			
		||||
        id: check
 | 
			
		||||
        shell: bash
 | 
			
		||||
        run: |
 | 
			
		||||
          passed=$(if [[ "$(git log -1 --pretty=format:%s | grep 'style: clang-tidy auto fixes')" ]]; then echo 'true' ; else echo 'false' ; fi)
 | 
			
		||||
          echo "passed=\"$passed\"" >> $GITHUB_OUTPUT
 | 
			
		||||
 | 
			
		||||
      - name: Run clang-tidy workflow
 | 
			
		||||
        if: ${{ contains(steps.check.outputs.passed, 'true') }}
 | 
			
		||||
        shell: bash
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ github.token }}
 | 
			
		||||
          GH_REPO: ${{ github.repository }}
 | 
			
		||||
        run: gh workflow run clang-tidy.yml
 | 
			
		||||
							
								
								
									
										12
									
								
								.github/workflows/docs.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/docs.yml
									
									
									
									
										vendored
									
									
								
							@@ -14,16 +14,16 @@ jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    container:
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:latest
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          lfs: true
 | 
			
		||||
 | 
			
		||||
      - name: Prepare runner
 | 
			
		||||
        uses: ./.github/actions/prepare_runner
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
 | 
			
		||||
        with:
 | 
			
		||||
          disable_ccache: true
 | 
			
		||||
 | 
			
		||||
@@ -39,10 +39,10 @@ jobs:
 | 
			
		||||
        run: cmake --build . --target docs
 | 
			
		||||
 | 
			
		||||
      - name: Setup Pages
 | 
			
		||||
        uses: actions/configure-pages@v5
 | 
			
		||||
        uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Upload artifact
 | 
			
		||||
        uses: actions/upload-pages-artifact@v3
 | 
			
		||||
        uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          path: build_docs/html
 | 
			
		||||
          name: docs-develop
 | 
			
		||||
@@ -62,6 +62,6 @@ jobs:
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Deploy to GitHub Pages
 | 
			
		||||
        id: deployment
 | 
			
		||||
        uses: actions/deploy-pages@v4
 | 
			
		||||
        uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
 | 
			
		||||
        with:
 | 
			
		||||
          artifact_name: docs-develop
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										67
									
								
								.github/workflows/nightly.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										67
									
								
								.github/workflows/nightly.yml
									
									
									
									
										vendored
									
									
								
							@@ -8,14 +8,14 @@ on:
 | 
			
		||||
    paths:
 | 
			
		||||
      - .github/workflows/nightly.yml
 | 
			
		||||
 | 
			
		||||
      - .github/workflows/release_impl.yml
 | 
			
		||||
      - .github/workflows/build_and_test.yml
 | 
			
		||||
      - .github/workflows/build_impl.yml
 | 
			
		||||
      - .github/workflows/test_impl.yml
 | 
			
		||||
      - .github/workflows/build_clio_docker_image.yml
 | 
			
		||||
      - .github/workflows/reusable-release.yml
 | 
			
		||||
      - .github/workflows/reusable-build-test.yml
 | 
			
		||||
      - .github/workflows/reusable-build.yml
 | 
			
		||||
      - .github/workflows/reusable-test.yml
 | 
			
		||||
      - .github/workflows/build-clio-docker-image.yml
 | 
			
		||||
 | 
			
		||||
      - ".github/actions/**"
 | 
			
		||||
      - "!.github/actions/code_coverage/**"
 | 
			
		||||
      - "!.github/actions/code-coverage/**"
 | 
			
		||||
      - .github/scripts/prepare-release-artifacts.sh
 | 
			
		||||
 | 
			
		||||
concurrency:
 | 
			
		||||
@@ -39,19 +39,19 @@ jobs:
 | 
			
		||||
            conan_profile: gcc
 | 
			
		||||
            build_type: Release
 | 
			
		||||
            static: true
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:latest" }'
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
          - os: heavy
 | 
			
		||||
            conan_profile: gcc
 | 
			
		||||
            build_type: Debug
 | 
			
		||||
            static: true
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:latest" }'
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
          - os: heavy
 | 
			
		||||
            conan_profile: gcc.ubsan
 | 
			
		||||
            build_type: Release
 | 
			
		||||
            static: false
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:latest" }'
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
 | 
			
		||||
    uses: ./.github/workflows/build_and_test.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-build-test.yml
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: ${{ matrix.os }}
 | 
			
		||||
      container: ${{ matrix.container }}
 | 
			
		||||
@@ -61,7 +61,8 @@ jobs:
 | 
			
		||||
      run_unit_tests: true
 | 
			
		||||
      run_integration_tests: true
 | 
			
		||||
      upload_clio_server: true
 | 
			
		||||
      disable_cache: true
 | 
			
		||||
      download_ccache: false
 | 
			
		||||
      upload_ccache: false
 | 
			
		||||
 | 
			
		||||
  analyze_build_time:
 | 
			
		||||
    name: Analyze Build Time
 | 
			
		||||
@@ -72,44 +73,54 @@ jobs:
 | 
			
		||||
        include:
 | 
			
		||||
          - os: heavy
 | 
			
		||||
            conan_profile: clang
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:latest" }'
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
            static: true
 | 
			
		||||
          - os: macos15
 | 
			
		||||
            conan_profile: apple-clang
 | 
			
		||||
            container: ""
 | 
			
		||||
            static: false
 | 
			
		||||
    uses: ./.github/workflows/build_impl.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-build.yml
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: ${{ matrix.os }}
 | 
			
		||||
      container: ${{ matrix.container }}
 | 
			
		||||
      conan_profile: ${{ matrix.conan_profile }}
 | 
			
		||||
      build_type: Release
 | 
			
		||||
      disable_cache: true
 | 
			
		||||
      download_ccache: false
 | 
			
		||||
      upload_ccache: false
 | 
			
		||||
      code_coverage: false
 | 
			
		||||
      static: ${{ matrix.static }}
 | 
			
		||||
      upload_clio_server: false
 | 
			
		||||
      targets: all
 | 
			
		||||
      analyze_build_time: true
 | 
			
		||||
 | 
			
		||||
  nightly_release:
 | 
			
		||||
    needs: build-and-test
 | 
			
		||||
    uses: ./.github/workflows/release_impl.yml
 | 
			
		||||
    with:
 | 
			
		||||
      overwrite_release: true
 | 
			
		||||
      prerelease: true
 | 
			
		||||
      title: "Clio development (nightly) build"
 | 
			
		||||
      version: nightly
 | 
			
		||||
      header: >
 | 
			
		||||
        # Release notes
 | 
			
		||||
  get_date:
 | 
			
		||||
    name: Get Date
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    outputs:
 | 
			
		||||
      date: ${{ steps.get_date.outputs.date }}
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Get current date
 | 
			
		||||
        id: get_date
 | 
			
		||||
        run: |
 | 
			
		||||
          echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
 | 
			
		||||
 | 
			
		||||
  nightly_release:
 | 
			
		||||
    needs: [build-and-test, get_date]
 | 
			
		||||
    uses: ./.github/workflows/reusable-release.yml
 | 
			
		||||
    with:
 | 
			
		||||
      delete_pattern: "nightly-*"
 | 
			
		||||
      prerelease: true
 | 
			
		||||
      title: "Clio development build (`nightly-${{ needs.get_date.outputs.date }}`)"
 | 
			
		||||
      version: nightly-${{ needs.get_date.outputs.date }}
 | 
			
		||||
      header: >
 | 
			
		||||
        > **Note:** Please remember that this is a development release and it is not recommended for production use.
 | 
			
		||||
 | 
			
		||||
        Changelog (including previous releases): <https://github.com/XRPLF/clio/commits/nightly>
 | 
			
		||||
        Changelog (including previous releases): <https://github.com/XRPLF/clio/commits/nightly-${{ needs.get_date.outputs.date }}>
 | 
			
		||||
      generate_changelog: false
 | 
			
		||||
      draft: false
 | 
			
		||||
 | 
			
		||||
  build_and_publish_docker_image:
 | 
			
		||||
    uses: ./.github/workflows/build_clio_docker_image.yml
 | 
			
		||||
    uses: ./.github/workflows/build-clio-docker-image.yml
 | 
			
		||||
    needs: build-and-test
 | 
			
		||||
    secrets: inherit
 | 
			
		||||
    with:
 | 
			
		||||
@@ -130,10 +141,10 @@ jobs:
 | 
			
		||||
      issues: write
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Create an issue
 | 
			
		||||
        uses: ./.github/actions/create_issue
 | 
			
		||||
        uses: ./.github/actions/create-issue
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ github.token }}
 | 
			
		||||
        with:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								.github/workflows/pre-commit-autoupdate.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								.github/workflows/pre-commit-autoupdate.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,50 +1,22 @@
 | 
			
		||||
name: Pre-commit auto-update
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  # every first day of the month
 | 
			
		||||
  schedule:
 | 
			
		||||
    # every first day of the month
 | 
			
		||||
    - cron: "0 0 1 * *"
 | 
			
		||||
  # on demand
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches: [release/*, develop]
 | 
			
		||||
    paths:
 | 
			
		||||
      - ".pre-commit-config.yaml"
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  auto-update:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    permissions:
 | 
			
		||||
      contents: write
 | 
			
		||||
      pull-requests: write
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
 | 
			
		||||
      - uses: actions/setup-python@v5
 | 
			
		||||
        with:
 | 
			
		||||
          python-version: 3.x
 | 
			
		||||
 | 
			
		||||
      - run: pip install pre-commit
 | 
			
		||||
      - run: pre-commit autoupdate --freeze
 | 
			
		||||
      - run: pre-commit run --all-files || true
 | 
			
		||||
 | 
			
		||||
      - uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
 | 
			
		||||
        if: github.event_name != 'pull_request'
 | 
			
		||||
        with:
 | 
			
		||||
          gpg_private_key: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
 | 
			
		||||
          passphrase: ${{ secrets.ACTIONS_GPG_PASSPHRASE }}
 | 
			
		||||
          git_user_signingkey: true
 | 
			
		||||
          git_commit_gpgsign: true
 | 
			
		||||
 | 
			
		||||
      - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
 | 
			
		||||
        if: always()
 | 
			
		||||
        env:
 | 
			
		||||
          GH_REPO: ${{ github.repository }}
 | 
			
		||||
          GH_TOKEN: ${{ github.token }}
 | 
			
		||||
        with:
 | 
			
		||||
          commit-message: "style: Update pre-commit hooks"
 | 
			
		||||
          committer: Clio CI <skuznetsov@ripple.com>
 | 
			
		||||
          branch: update/pre-commit-hooks
 | 
			
		||||
          branch-suffix: timestamp
 | 
			
		||||
          delete-branch: true
 | 
			
		||||
          title: "style: Update pre-commit hooks"
 | 
			
		||||
          body: Update versions of pre-commit hooks to latest version.
 | 
			
		||||
          reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
 | 
			
		||||
    uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@afbcbdafbe0ce5439492fb87eda6441371086386
 | 
			
		||||
    with:
 | 
			
		||||
      sign_commit: true
 | 
			
		||||
      committer: "Clio CI <skuznetsov@ripple.com>"
 | 
			
		||||
      reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
 | 
			
		||||
    secrets:
 | 
			
		||||
      GPG_PRIVATE_KEY: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
 | 
			
		||||
      GPG_PASSPHRASE: ${{ secrets.ACTIONS_GPG_PASSPHRASE }}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								.github/workflows/pre-commit.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.github/workflows/pre-commit.yml
									
									
									
									
										vendored
									
									
								
							@@ -8,20 +8,7 @@ on:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  run-hooks:
 | 
			
		||||
    runs-on: heavy
 | 
			
		||||
    container:
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout Repo ⚡️
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0
 | 
			
		||||
 | 
			
		||||
      - name: Prepare runner
 | 
			
		||||
        uses: ./.github/actions/prepare_runner
 | 
			
		||||
        with:
 | 
			
		||||
          disable_ccache: true
 | 
			
		||||
 | 
			
		||||
      - name: Run pre-commit ✅
 | 
			
		||||
        run: pre-commit run --all-files
 | 
			
		||||
    uses: XRPLF/actions/.github/workflows/pre-commit.yml@34790936fae4c6c751f62ec8c06696f9c1a5753a
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: heavy
 | 
			
		||||
      container: '{ "image": "ghcr.io/xrplf/clio-pre-commit:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							@@ -29,9 +29,9 @@ jobs:
 | 
			
		||||
            conan_profile: gcc
 | 
			
		||||
            build_type: Release
 | 
			
		||||
            static: true
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:latest" }'
 | 
			
		||||
            container: '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
 | 
			
		||||
    uses: ./.github/workflows/build_and_test.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-build-test.yml
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: ${{ matrix.os }}
 | 
			
		||||
      container: ${{ matrix.container }}
 | 
			
		||||
@@ -41,17 +41,19 @@ jobs:
 | 
			
		||||
      run_unit_tests: true
 | 
			
		||||
      run_integration_tests: true
 | 
			
		||||
      upload_clio_server: true
 | 
			
		||||
      disable_cache: true
 | 
			
		||||
      download_ccache: false
 | 
			
		||||
      upload_ccache: false
 | 
			
		||||
      expected_version: ${{ github.event_name == 'push' && github.ref_name || '' }}
 | 
			
		||||
 | 
			
		||||
  release:
 | 
			
		||||
    needs: build-and-test
 | 
			
		||||
    uses: ./.github/workflows/release_impl.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-release.yml
 | 
			
		||||
    with:
 | 
			
		||||
      overwrite_release: false
 | 
			
		||||
      delete_pattern: ""
 | 
			
		||||
      prerelease: ${{ contains(github.ref_name, '-') }}
 | 
			
		||||
      title: "${{ github.ref_name}}"
 | 
			
		||||
      title: "${{ github.ref_name }}"
 | 
			
		||||
      version: "${{ github.ref_name }}"
 | 
			
		||||
      header: >
 | 
			
		||||
        # Introducing Clio version ${{ github.ref_name }}
 | 
			
		||||
      generate_changelog: true
 | 
			
		||||
      draft: true
 | 
			
		||||
        ${{ contains(github.ref_name, '-') && '> **Note:** Please remember that this is a release candidate and it is not recommended for production use.' || '' }}
 | 
			
		||||
      generate_changelog: ${{ !contains(github.ref_name, '-') }}
 | 
			
		||||
      draft: ${{ !contains(github.ref_name, '-') }}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,14 @@ on:
 | 
			
		||||
        required: true
 | 
			
		||||
        type: string
 | 
			
		||||
 | 
			
		||||
      disable_cache:
 | 
			
		||||
        description: Whether ccache should be disabled
 | 
			
		||||
      download_ccache:
 | 
			
		||||
        description: Whether to download ccache from the cache
 | 
			
		||||
        required: false
 | 
			
		||||
        type: boolean
 | 
			
		||||
        default: true
 | 
			
		||||
 | 
			
		||||
      upload_ccache:
 | 
			
		||||
        description: Whether to upload ccache to the cache
 | 
			
		||||
        required: false
 | 
			
		||||
        type: boolean
 | 
			
		||||
        default: false
 | 
			
		||||
@@ -57,24 +63,39 @@ on:
 | 
			
		||||
        type: string
 | 
			
		||||
        default: all
 | 
			
		||||
 | 
			
		||||
      expected_version:
 | 
			
		||||
        description: Expected version of the clio_server binary
 | 
			
		||||
        required: false
 | 
			
		||||
        type: string
 | 
			
		||||
        default: ""
 | 
			
		||||
 | 
			
		||||
      package:
 | 
			
		||||
        description: Whether to generate Debian package
 | 
			
		||||
        required: false
 | 
			
		||||
        type: boolean
 | 
			
		||||
        default: false
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    uses: ./.github/workflows/build_impl.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-build.yml
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: ${{ inputs.runs_on }}
 | 
			
		||||
      container: ${{ inputs.container }}
 | 
			
		||||
      conan_profile: ${{ inputs.conan_profile }}
 | 
			
		||||
      build_type: ${{ inputs.build_type }}
 | 
			
		||||
      disable_cache: ${{ inputs.disable_cache }}
 | 
			
		||||
      download_ccache: ${{ inputs.download_ccache }}
 | 
			
		||||
      upload_ccache: ${{ inputs.upload_ccache }}
 | 
			
		||||
      code_coverage: false
 | 
			
		||||
      static: ${{ inputs.static }}
 | 
			
		||||
      upload_clio_server: ${{ inputs.upload_clio_server }}
 | 
			
		||||
      targets: ${{ inputs.targets }}
 | 
			
		||||
      analyze_build_time: false
 | 
			
		||||
      expected_version: ${{ inputs.expected_version }}
 | 
			
		||||
      package: ${{ inputs.package }}
 | 
			
		||||
 | 
			
		||||
  test:
 | 
			
		||||
    needs: build
 | 
			
		||||
    uses: ./.github/workflows/test_impl.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-test.yml
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: ${{ inputs.runs_on }}
 | 
			
		||||
      container: ${{ inputs.container }}
 | 
			
		||||
@@ -23,10 +23,17 @@ on:
 | 
			
		||||
        required: true
 | 
			
		||||
        type: string
 | 
			
		||||
 | 
			
		||||
      disable_cache:
 | 
			
		||||
        description: Whether ccache should be disabled
 | 
			
		||||
      download_ccache:
 | 
			
		||||
        description: Whether to download ccache from the cache
 | 
			
		||||
        required: false
 | 
			
		||||
        type: boolean
 | 
			
		||||
        default: true
 | 
			
		||||
 | 
			
		||||
      upload_ccache:
 | 
			
		||||
        description: Whether to upload ccache to the cache
 | 
			
		||||
        required: false
 | 
			
		||||
        type: boolean
 | 
			
		||||
        default: false
 | 
			
		||||
 | 
			
		||||
      code_coverage:
 | 
			
		||||
        description: Whether to enable code coverage
 | 
			
		||||
@@ -53,6 +60,17 @@ on:
 | 
			
		||||
        required: true
 | 
			
		||||
        type: boolean
 | 
			
		||||
 | 
			
		||||
      expected_version:
 | 
			
		||||
        description: Expected version of the clio_server binary
 | 
			
		||||
        required: false
 | 
			
		||||
        type: string
 | 
			
		||||
        default: ""
 | 
			
		||||
 | 
			
		||||
      package:
 | 
			
		||||
        description: Whether to generate Debian package
 | 
			
		||||
        required: false
 | 
			
		||||
        type: boolean
 | 
			
		||||
 | 
			
		||||
    secrets:
 | 
			
		||||
      CODECOV_TOKEN:
 | 
			
		||||
        required: false
 | 
			
		||||
@@ -64,27 +82,31 @@ jobs:
 | 
			
		||||
    container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Clean workdir
 | 
			
		||||
      - name: Cleanup workspace
 | 
			
		||||
        if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
        uses: kuznetsss/workspace-cleanup@80b9863b45562c148927c3d53621ef354e5ae7ce # v1.0
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
 | 
			
		||||
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0
 | 
			
		||||
          # We need to fetch tags to have correct version in the release
 | 
			
		||||
          # The workaround is based on https://github.com/actions/checkout/issues/1467
 | 
			
		||||
          fetch-tags: true
 | 
			
		||||
          ref: ${{ github.ref }}
 | 
			
		||||
 | 
			
		||||
      - name: Prepare runner
 | 
			
		||||
        uses: ./.github/actions/prepare_runner
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
 | 
			
		||||
        with:
 | 
			
		||||
          disable_ccache: ${{ inputs.disable_cache }}
 | 
			
		||||
          disable_ccache: ${{ !inputs.download_ccache }}
 | 
			
		||||
 | 
			
		||||
      - name: Setup conan on macOS
 | 
			
		||||
        if: runner.os == 'macOS'
 | 
			
		||||
        if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
        shell: bash
 | 
			
		||||
        run: ./.github/scripts/conan/init.sh
 | 
			
		||||
 | 
			
		||||
      - name: Restore cache
 | 
			
		||||
        if: ${{ !inputs.disable_cache }}
 | 
			
		||||
        uses: ./.github/actions/restore_cache
 | 
			
		||||
        if: ${{ inputs.download_ccache }}
 | 
			
		||||
        uses: ./.github/actions/restore-cache
 | 
			
		||||
        id: restore_cache
 | 
			
		||||
        with:
 | 
			
		||||
          conan_profile: ${{ inputs.conan_profile }}
 | 
			
		||||
@@ -92,17 +114,24 @@ jobs:
 | 
			
		||||
          build_type: ${{ inputs.build_type }}
 | 
			
		||||
          code_coverage: ${{ inputs.code_coverage }}
 | 
			
		||||
 | 
			
		||||
      - name: Run conan and cmake
 | 
			
		||||
        uses: ./.github/actions/generate
 | 
			
		||||
      - name: Run conan
 | 
			
		||||
        uses: ./.github/actions/conan
 | 
			
		||||
        with:
 | 
			
		||||
          conan_profile: ${{ inputs.conan_profile }}
 | 
			
		||||
          build_type: ${{ inputs.build_type }}
 | 
			
		||||
 | 
			
		||||
      - name: Run CMake
 | 
			
		||||
        uses: ./.github/actions/cmake
 | 
			
		||||
        with:
 | 
			
		||||
          conan_profile: ${{ inputs.conan_profile }}
 | 
			
		||||
          build_type: ${{ inputs.build_type }}
 | 
			
		||||
          code_coverage: ${{ inputs.code_coverage }}
 | 
			
		||||
          static: ${{ inputs.static }}
 | 
			
		||||
          time_trace: ${{ inputs.analyze_build_time }}
 | 
			
		||||
          package: ${{ inputs.package }}
 | 
			
		||||
 | 
			
		||||
      - name: Build Clio
 | 
			
		||||
        uses: ./.github/actions/build_clio
 | 
			
		||||
        uses: ./.github/actions/build-clio
 | 
			
		||||
        with:
 | 
			
		||||
          targets: ${{ inputs.targets }}
 | 
			
		||||
 | 
			
		||||
@@ -116,13 +145,13 @@ jobs:
 | 
			
		||||
 | 
			
		||||
      - name: Upload build time analyze report
 | 
			
		||||
        if: ${{ inputs.analyze_build_time }}
 | 
			
		||||
        uses: actions/upload-artifact@v4
 | 
			
		||||
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: build_time_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
 | 
			
		||||
          path: build_time_report.txt
 | 
			
		||||
 | 
			
		||||
      - name: Show ccache's statistics
 | 
			
		||||
        if: ${{ !inputs.disable_cache }}
 | 
			
		||||
        if: ${{ inputs.download_ccache }}
 | 
			
		||||
        shell: bash
 | 
			
		||||
        id: ccache_stats
 | 
			
		||||
        run: |
 | 
			
		||||
@@ -140,29 +169,36 @@ jobs:
 | 
			
		||||
        run: strip build/clio_integration_tests
 | 
			
		||||
 | 
			
		||||
      - name: Upload clio_server
 | 
			
		||||
        if: inputs.upload_clio_server && !inputs.code_coverage && !inputs.analyze_build_time
 | 
			
		||||
        uses: actions/upload-artifact@v4
 | 
			
		||||
        if: ${{ inputs.upload_clio_server && !inputs.code_coverage && !inputs.analyze_build_time }}
 | 
			
		||||
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: clio_server_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
 | 
			
		||||
          path: build/clio_server
 | 
			
		||||
 | 
			
		||||
      - name: Upload clio_tests
 | 
			
		||||
        if: ${{ !inputs.code_coverage && !inputs.analyze_build_time }}
 | 
			
		||||
        uses: actions/upload-artifact@v4
 | 
			
		||||
        if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
 | 
			
		||||
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
 | 
			
		||||
          path: build/clio_tests
 | 
			
		||||
 | 
			
		||||
      - name: Upload clio_integration_tests
 | 
			
		||||
        if: ${{ !inputs.code_coverage && !inputs.analyze_build_time }}
 | 
			
		||||
        uses: actions/upload-artifact@v4
 | 
			
		||||
        if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
 | 
			
		||||
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
 | 
			
		||||
          path: build/clio_integration_tests
 | 
			
		||||
 | 
			
		||||
      - name: Upload Clio Linux package
 | 
			
		||||
        if: ${{ inputs.package }}
 | 
			
		||||
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: clio_deb_package_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
 | 
			
		||||
          path: build/*.deb
 | 
			
		||||
 | 
			
		||||
      - name: Save cache
 | 
			
		||||
        if: ${{ !inputs.disable_cache && github.ref == 'refs/heads/develop' }}
 | 
			
		||||
        uses: ./.github/actions/save_cache
 | 
			
		||||
        if: ${{ inputs.upload_ccache && github.ref == 'refs/heads/develop' }}
 | 
			
		||||
        uses: ./.github/actions/save-cache
 | 
			
		||||
        with:
 | 
			
		||||
          conan_profile: ${{ inputs.conan_profile }}
 | 
			
		||||
          ccache_dir: ${{ env.CCACHE_DIR }}
 | 
			
		||||
@@ -174,14 +210,27 @@ jobs:
 | 
			
		||||
 | 
			
		||||
      # This is run as part of the build job, because it requires the following:
 | 
			
		||||
      # - source code
 | 
			
		||||
      # - generated source code (Build.cpp)
 | 
			
		||||
      # - conan packages
 | 
			
		||||
      # - .gcno files in build directory
 | 
			
		||||
      #
 | 
			
		||||
      # It's all available in the build job, but not in the test job
 | 
			
		||||
      - name: Run code coverage
 | 
			
		||||
        if: ${{ inputs.code_coverage }}
 | 
			
		||||
        uses: ./.github/actions/code_coverage
 | 
			
		||||
        uses: ./.github/actions/code-coverage
 | 
			
		||||
 | 
			
		||||
      - name: Verify expected version
 | 
			
		||||
        if: ${{ inputs.expected_version != '' }}
 | 
			
		||||
        shell: bash
 | 
			
		||||
        env:
 | 
			
		||||
          INPUT_EXPECTED_VERSION: ${{ inputs.expected_version }}
 | 
			
		||||
        run: |
 | 
			
		||||
          set -e
 | 
			
		||||
          EXPECTED_VERSION="clio-${INPUT_EXPECTED_VERSION}"
 | 
			
		||||
          actual_version=$(./build/clio_server --version)
 | 
			
		||||
          if [[ "$actual_version" != "$EXPECTED_VERSION" ]]; then
 | 
			
		||||
            echo "Expected version '${EXPECTED_VERSION}', but got '${actual_version}'"
 | 
			
		||||
            exit 1
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
  # `codecov/codecov-action` will rerun `gcov` if it's available and build directory is present
 | 
			
		||||
  # To prevent this from happening, we run this action in a separate workflow
 | 
			
		||||
@@ -191,6 +240,6 @@ jobs:
 | 
			
		||||
    if: ${{ inputs.code_coverage }}
 | 
			
		||||
    name: Codecov
 | 
			
		||||
    needs: build
 | 
			
		||||
    uses: ./.github/workflows/upload_coverage_report.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-upload-coverage-report.yml
 | 
			
		||||
    secrets:
 | 
			
		||||
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
 | 
			
		||||
@@ -3,10 +3,10 @@ name: Make release
 | 
			
		||||
on:
 | 
			
		||||
  workflow_call:
 | 
			
		||||
    inputs:
 | 
			
		||||
      overwrite_release:
 | 
			
		||||
        description: "Overwrite the current release and tag"
 | 
			
		||||
      delete_pattern:
 | 
			
		||||
        description: "Pattern to delete previous releases"
 | 
			
		||||
        required: true
 | 
			
		||||
        type: boolean
 | 
			
		||||
        type: string
 | 
			
		||||
 | 
			
		||||
      prerelease:
 | 
			
		||||
        description: "Create a prerelease"
 | 
			
		||||
@@ -42,7 +42,7 @@ jobs:
 | 
			
		||||
  release:
 | 
			
		||||
    runs-on: heavy
 | 
			
		||||
    container:
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:latest
 | 
			
		||||
      image: ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a
 | 
			
		||||
    env:
 | 
			
		||||
      GH_REPO: ${{ github.repository }}
 | 
			
		||||
      GH_TOKEN: ${{ github.token }}
 | 
			
		||||
@@ -51,72 +51,76 @@ jobs:
 | 
			
		||||
      contents: write
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0
 | 
			
		||||
 | 
			
		||||
      - name: Prepare runner
 | 
			
		||||
        uses: ./.github/actions/prepare_runner
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
 | 
			
		||||
        with:
 | 
			
		||||
          disable_ccache: true
 | 
			
		||||
 | 
			
		||||
      - uses: actions/download-artifact@v4
 | 
			
		||||
      - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          path: release_artifacts
 | 
			
		||||
          pattern: clio_server_*
 | 
			
		||||
 | 
			
		||||
      - name: Create release notes
 | 
			
		||||
        shell: bash
 | 
			
		||||
        env:
 | 
			
		||||
          RELEASE_HEADER: ${{ inputs.header }}
 | 
			
		||||
        run: |
 | 
			
		||||
          printf '%s\n' "${{ inputs.header }}" > "${RUNNER_TEMP}/release_notes.md"
 | 
			
		||||
          echo "# Release notes" > "${RUNNER_TEMP}/release_notes.md"
 | 
			
		||||
          echo "" >> "${RUNNER_TEMP}/release_notes.md"
 | 
			
		||||
          printf '%s\n' "${RELEASE_HEADER}" >> "${RUNNER_TEMP}/release_notes.md"
 | 
			
		||||
 | 
			
		||||
      - name: Generate changelog
 | 
			
		||||
        shell: bash
 | 
			
		||||
        if: ${{ inputs.generate_changelog }}
 | 
			
		||||
        run: |
 | 
			
		||||
          LAST_TAG="$(gh release view --json tagName -q .tagName)"
 | 
			
		||||
          LAST_TAG="$(gh release view --json tagName -q .tagName --repo XRPLF/clio)"
 | 
			
		||||
          LAST_TAG_COMMIT="$(git rev-parse $LAST_TAG)"
 | 
			
		||||
          BASE_COMMIT="$(git merge-base HEAD $LAST_TAG_COMMIT)"
 | 
			
		||||
          git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b"
 | 
			
		||||
          git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b|-rc"
 | 
			
		||||
          cat CHANGELOG.md >> "${RUNNER_TEMP}/release_notes.md"
 | 
			
		||||
 | 
			
		||||
      - name: Prepare release artifacts
 | 
			
		||||
        shell: bash
 | 
			
		||||
        run: .github/scripts/prepare-release-artifacts.sh release_artifacts
 | 
			
		||||
 | 
			
		||||
      - name: Append sha256 checksums
 | 
			
		||||
        shell: bash
 | 
			
		||||
        working-directory: release_artifacts
 | 
			
		||||
        run: |
 | 
			
		||||
          {
 | 
			
		||||
            echo '## SHA256 checksums'
 | 
			
		||||
            echo
 | 
			
		||||
            echo '```'
 | 
			
		||||
            cat *.sha256sum
 | 
			
		||||
            echo '```'
 | 
			
		||||
          } >> "${RUNNER_TEMP}/release_notes.md"
 | 
			
		||||
 | 
			
		||||
      - name: Upload release notes
 | 
			
		||||
        uses: actions/upload-artifact@v4
 | 
			
		||||
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: release_notes_${{ inputs.version }}
 | 
			
		||||
          path: "${RUNNER_TEMP}/release_notes.md"
 | 
			
		||||
 | 
			
		||||
      - name: Remove current release and tag
 | 
			
		||||
        if: ${{ github.event_name != 'pull_request' && inputs.overwrite_release }}
 | 
			
		||||
      - name: Remove previous release with a pattern
 | 
			
		||||
        if: ${{ github.event_name != 'pull_request' && inputs.delete_pattern != '' }}
 | 
			
		||||
        shell: bash
 | 
			
		||||
        env:
 | 
			
		||||
          DELETE_PATTERN: ${{ inputs.delete_pattern }}
 | 
			
		||||
        run: |
 | 
			
		||||
          gh release delete ${{ inputs.version }} --yes || true
 | 
			
		||||
          git push origin :${{ inputs.version }} || true
 | 
			
		||||
          RELEASES_TO_DELETE=$(gh release list --limit 50 --repo "${GH_REPO}" | grep -E "${DELETE_PATTERN}" | awk -F'\t' '{print $3}' || true)
 | 
			
		||||
          if [ -n "$RELEASES_TO_DELETE" ]; then
 | 
			
		||||
            for RELEASE in $RELEASES_TO_DELETE; do
 | 
			
		||||
              echo "Deleting release: $RELEASE"
 | 
			
		||||
              gh release delete "$RELEASE" --repo "${GH_REPO}" --yes --cleanup-tag
 | 
			
		||||
            done
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      - name: Publish release
 | 
			
		||||
        if: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
        shell: bash
 | 
			
		||||
        env:
 | 
			
		||||
          RELEASE_VERSION: ${{ inputs.version }}
 | 
			
		||||
          PRERELEASE_OPTION: ${{ inputs.prerelease && '--prerelease' || '' }}
 | 
			
		||||
          RELEASE_TITLE: ${{ inputs.title }}
 | 
			
		||||
          DRAFT_OPTION: ${{ inputs.draft && '--draft' || '' }}
 | 
			
		||||
        run: |
 | 
			
		||||
          gh release create "${{ inputs.version }}" \
 | 
			
		||||
            ${{ inputs.prerelease && '--prerelease' || '' }} \
 | 
			
		||||
            --title "${{ inputs.title }}" \
 | 
			
		||||
          gh release create "${RELEASE_VERSION}" \
 | 
			
		||||
            ${PRERELEASE_OPTION} \
 | 
			
		||||
            --title "${RELEASE_TITLE}" \
 | 
			
		||||
            --target "${GITHUB_SHA}" \
 | 
			
		||||
            ${{ inputs.draft && '--draft' || '' }} \
 | 
			
		||||
            ${DRAFT_OPTION} \
 | 
			
		||||
            --notes-file "${RUNNER_TEMP}/release_notes.md" \
 | 
			
		||||
            ./release_artifacts/clio_server*
 | 
			
		||||
@@ -39,22 +39,22 @@ jobs:
 | 
			
		||||
    runs-on: ${{ inputs.runs_on }}
 | 
			
		||||
    container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}
 | 
			
		||||
 | 
			
		||||
    if: inputs.run_unit_tests
 | 
			
		||||
    if: ${{ inputs.run_unit_tests }}
 | 
			
		||||
 | 
			
		||||
    env:
 | 
			
		||||
      # TODO: remove completely when we have fixed all currently existing issues with sanitizers
 | 
			
		||||
      SANITIZER_IGNORE_ERRORS: ${{ endsWith(inputs.conan_profile, '.asan') || endsWith(inputs.conan_profile, '.tsan') }}
 | 
			
		||||
      SANITIZER_IGNORE_ERRORS: ${{ endsWith(inputs.conan_profile, '.tsan') || (inputs.conan_profile == 'gcc.asan' && inputs.build_type == 'Release') }}
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Clean workdir
 | 
			
		||||
      - name: Cleanup workspace
 | 
			
		||||
        if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
        uses: kuznetsss/workspace-cleanup@80b9863b45562c148927c3d53621ef354e5ae7ce # v1.0
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
 | 
			
		||||
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0
 | 
			
		||||
 | 
			
		||||
      - uses: actions/download-artifact@v4
 | 
			
		||||
      - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
 | 
			
		||||
 | 
			
		||||
@@ -63,15 +63,15 @@ jobs:
 | 
			
		||||
        run: chmod +x ./clio_tests
 | 
			
		||||
 | 
			
		||||
      - name: Run clio_tests (regular)
 | 
			
		||||
        if: env.SANITIZER_IGNORE_ERRORS == 'false'
 | 
			
		||||
        if: ${{ env.SANITIZER_IGNORE_ERRORS == 'false' }}
 | 
			
		||||
        run: ./clio_tests
 | 
			
		||||
 | 
			
		||||
      - name: Run clio_tests (sanitizer errors ignored)
 | 
			
		||||
        if: env.SANITIZER_IGNORE_ERRORS == 'true'
 | 
			
		||||
        run: ./.github/scripts/execute-tests-under-sanitizer ./clio_tests
 | 
			
		||||
        if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' }}
 | 
			
		||||
        run: ./.github/scripts/execute-tests-under-sanitizer.sh ./clio_tests
 | 
			
		||||
 | 
			
		||||
      - name: Check for sanitizer report
 | 
			
		||||
        if: env.SANITIZER_IGNORE_ERRORS == 'true'
 | 
			
		||||
        if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' }}
 | 
			
		||||
        shell: bash
 | 
			
		||||
        id: check_report
 | 
			
		||||
        run: |
 | 
			
		||||
@@ -82,16 +82,16 @@ jobs:
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      - name: Upload sanitizer report
 | 
			
		||||
        if: env.SANITIZER_IGNORE_ERRORS == 'true' && steps.check_report.outputs.found_report == 'true'
 | 
			
		||||
        uses: actions/upload-artifact@v4
 | 
			
		||||
        if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' && steps.check_report.outputs.found_report == 'true' }}
 | 
			
		||||
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: sanitizer_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
 | 
			
		||||
          path: .sanitizer-report/*
 | 
			
		||||
          include-hidden-files: true
 | 
			
		||||
 | 
			
		||||
      - name: Create an issue
 | 
			
		||||
        if: false && env.SANITIZER_IGNORE_ERRORS == 'true' && steps.check_report.outputs.found_report == 'true'
 | 
			
		||||
        uses: ./.github/actions/create_issue
 | 
			
		||||
        if: ${{ false && env.SANITIZER_IGNORE_ERRORS == 'true' && steps.check_report.outputs.found_report == 'true' }}
 | 
			
		||||
        uses: ./.github/actions/create-issue
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ github.token }}
 | 
			
		||||
        with:
 | 
			
		||||
@@ -108,7 +108,7 @@ jobs:
 | 
			
		||||
    runs-on: ${{ inputs.runs_on }}
 | 
			
		||||
    container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}
 | 
			
		||||
 | 
			
		||||
    if: inputs.run_integration_tests
 | 
			
		||||
    if: ${{ inputs.run_integration_tests }}
 | 
			
		||||
 | 
			
		||||
    services:
 | 
			
		||||
      scylladb:
 | 
			
		||||
@@ -120,9 +120,9 @@ jobs:
 | 
			
		||||
          --health-retries 5
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Clean workdir
 | 
			
		||||
      - name: Cleanup workspace
 | 
			
		||||
        if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
        uses: kuznetsss/workspace-cleanup@80b9863b45562c148927c3d53621ef354e5ae7ce # v1.0
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
 | 
			
		||||
 | 
			
		||||
      - name: Spin up scylladb
 | 
			
		||||
        if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
@@ -144,7 +144,7 @@ jobs:
 | 
			
		||||
            sleep 5
 | 
			
		||||
          done
 | 
			
		||||
 | 
			
		||||
      - uses: actions/download-artifact@v4
 | 
			
		||||
      - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
 | 
			
		||||
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
name: Upload report
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
  workflow_call:
 | 
			
		||||
    secrets:
 | 
			
		||||
      CODECOV_TOKEN:
 | 
			
		||||
@@ -13,19 +12,19 @@ jobs:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0
 | 
			
		||||
 | 
			
		||||
      - name: Download report artifact
 | 
			
		||||
        uses: actions/download-artifact@v4
 | 
			
		||||
        uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          name: coverage-report.xml
 | 
			
		||||
          path: build
 | 
			
		||||
 | 
			
		||||
      - name: Upload coverage report
 | 
			
		||||
        if: ${{ hashFiles('build/coverage_report.xml') != '' }}
 | 
			
		||||
        uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
 | 
			
		||||
        uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
 | 
			
		||||
        with:
 | 
			
		||||
          files: build/coverage_report.xml
 | 
			
		||||
          fail_ci_if_error: true
 | 
			
		||||
							
								
								
									
										19
									
								
								.github/workflows/sanitizers.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								.github/workflows/sanitizers.yml
									
									
									
									
										vendored
									
									
								
							@@ -8,14 +8,14 @@ on:
 | 
			
		||||
    paths:
 | 
			
		||||
      - .github/workflows/sanitizers.yml
 | 
			
		||||
 | 
			
		||||
      - .github/workflows/build_and_test.yml
 | 
			
		||||
      - .github/workflows/build_impl.yml
 | 
			
		||||
      - .github/workflows/test_impl.yml
 | 
			
		||||
      - .github/workflows/reusable-build-test.yml
 | 
			
		||||
      - .github/workflows/reusable-build.yml
 | 
			
		||||
      - .github/workflows/reusable-test.yml
 | 
			
		||||
 | 
			
		||||
      - ".github/actions/**"
 | 
			
		||||
      - "!.github/actions/build_docker_image/**"
 | 
			
		||||
      - "!.github/actions/create_issue/**"
 | 
			
		||||
      - .github/scripts/execute-tests-under-sanitizer
 | 
			
		||||
      - "!.github/actions/build-docker-image/**"
 | 
			
		||||
      - "!.github/actions/create-issue/**"
 | 
			
		||||
      - .github/scripts/execute-tests-under-sanitizer.sh
 | 
			
		||||
 | 
			
		||||
      - CMakeLists.txt
 | 
			
		||||
      - conanfile.py
 | 
			
		||||
@@ -41,11 +41,12 @@ jobs:
 | 
			
		||||
        sanitizer_ext: [.asan, .tsan, .ubsan]
 | 
			
		||||
        build_type: [Release, Debug]
 | 
			
		||||
 | 
			
		||||
    uses: ./.github/workflows/build_and_test.yml
 | 
			
		||||
    uses: ./.github/workflows/reusable-build-test.yml
 | 
			
		||||
    with:
 | 
			
		||||
      runs_on: heavy
 | 
			
		||||
      container: '{ "image": "ghcr.io/xrplf/clio-ci:latest" }'
 | 
			
		||||
      disable_cache: true
 | 
			
		||||
      container: '{ "image": "ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
 | 
			
		||||
      download_ccache: false
 | 
			
		||||
      upload_ccache: false
 | 
			
		||||
      conan_profile: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
 | 
			
		||||
      build_type: ${{ matrix.build_type }}
 | 
			
		||||
      static: false
 | 
			
		||||
 
 | 
			
		||||
@@ -3,23 +3,23 @@ name: Update CI docker image
 | 
			
		||||
on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    paths:
 | 
			
		||||
      - .github/workflows/update_docker_ci.yml
 | 
			
		||||
      - .github/workflows/update-docker-ci.yml
 | 
			
		||||
 | 
			
		||||
      - ".github/actions/build_docker_image/**"
 | 
			
		||||
      - ".github/actions/build-docker-image/**"
 | 
			
		||||
 | 
			
		||||
      - "docker/ci/**"
 | 
			
		||||
      - "docker/compilers/**"
 | 
			
		||||
      - "docker/tools/**"
 | 
			
		||||
      - "docker/**"
 | 
			
		||||
      - "!docker/clio/**"
 | 
			
		||||
      - "!docker/develop/**"
 | 
			
		||||
  push:
 | 
			
		||||
    branches: [develop]
 | 
			
		||||
    paths:
 | 
			
		||||
      - .github/workflows/update_docker_ci.yml
 | 
			
		||||
      - .github/workflows/update-docker-ci.yml
 | 
			
		||||
 | 
			
		||||
      - ".github/actions/build_docker_image/**"
 | 
			
		||||
      - ".github/actions/build-docker-image/**"
 | 
			
		||||
 | 
			
		||||
      - "docker/ci/**"
 | 
			
		||||
      - "docker/compilers/**"
 | 
			
		||||
      - "docker/tools/**"
 | 
			
		||||
      - "docker/**"
 | 
			
		||||
      - "!docker/clio/**"
 | 
			
		||||
      - "!docker/develop/**"
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
 | 
			
		||||
concurrency:
 | 
			
		||||
@@ -30,8 +30,8 @@ concurrency:
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  CLANG_MAJOR_VERSION: 19
 | 
			
		||||
  GCC_MAJOR_VERSION: 14
 | 
			
		||||
  GCC_VERSION: 14.3.0
 | 
			
		||||
  GCC_MAJOR_VERSION: 15
 | 
			
		||||
  GCC_VERSION: 15.2.0
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  repo:
 | 
			
		||||
@@ -52,16 +52,16 @@ jobs:
 | 
			
		||||
    needs: repo
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Get changed files
 | 
			
		||||
        id: changed-files
 | 
			
		||||
        uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
 | 
			
		||||
        uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          files: "docker/compilers/gcc/**"
 | 
			
		||||
 | 
			
		||||
      - uses: ./.github/actions/build_docker_image
 | 
			
		||||
        if: steps.changed-files.outputs.any_changed == 'true'
 | 
			
		||||
      - uses: ./.github/actions/build-docker-image
 | 
			
		||||
        if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
          DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
 | 
			
		||||
@@ -69,7 +69,7 @@ jobs:
 | 
			
		||||
        with:
 | 
			
		||||
          images: |
 | 
			
		||||
            ${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
 | 
			
		||||
            rippleci/clio_gcc
 | 
			
		||||
            ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
 | 
			
		||||
          push_image: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
          directory: docker/compilers/gcc
 | 
			
		||||
          tags: |
 | 
			
		||||
@@ -81,7 +81,7 @@ jobs:
 | 
			
		||||
          build_args: |
 | 
			
		||||
            GCC_MAJOR_VERSION=${{ env.GCC_MAJOR_VERSION }}
 | 
			
		||||
            GCC_VERSION=${{ env.GCC_VERSION }}
 | 
			
		||||
          dockerhub_repo: rippleci/clio_gcc
 | 
			
		||||
          dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
 | 
			
		||||
          dockerhub_description: GCC compiler for XRPLF/clio.
 | 
			
		||||
 | 
			
		||||
  gcc-arm64:
 | 
			
		||||
@@ -90,7 +90,7 @@ jobs:
 | 
			
		||||
    needs: repo
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Get changed files
 | 
			
		||||
        id: changed-files
 | 
			
		||||
@@ -98,8 +98,8 @@ jobs:
 | 
			
		||||
        with:
 | 
			
		||||
          files: "docker/compilers/gcc/**"
 | 
			
		||||
 | 
			
		||||
      - uses: ./.github/actions/build_docker_image
 | 
			
		||||
        if: steps.changed-files.outputs.any_changed == 'true'
 | 
			
		||||
      - uses: ./.github/actions/build-docker-image
 | 
			
		||||
        if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
          DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
 | 
			
		||||
@@ -107,7 +107,7 @@ jobs:
 | 
			
		||||
        with:
 | 
			
		||||
          images: |
 | 
			
		||||
            ${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
 | 
			
		||||
            rippleci/clio_gcc
 | 
			
		||||
            ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
 | 
			
		||||
          push_image: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
          directory: docker/compilers/gcc
 | 
			
		||||
          tags: |
 | 
			
		||||
@@ -119,7 +119,7 @@ jobs:
 | 
			
		||||
          build_args: |
 | 
			
		||||
            GCC_MAJOR_VERSION=${{ env.GCC_MAJOR_VERSION }}
 | 
			
		||||
            GCC_VERSION=${{ env.GCC_VERSION }}
 | 
			
		||||
          dockerhub_repo: rippleci/clio_gcc
 | 
			
		||||
          dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
 | 
			
		||||
          dockerhub_description: GCC compiler for XRPLF/clio.
 | 
			
		||||
 | 
			
		||||
  gcc-merge:
 | 
			
		||||
@@ -128,44 +128,50 @@ jobs:
 | 
			
		||||
    needs: [repo, gcc-amd64, gcc-arm64]
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Get changed files
 | 
			
		||||
        id: changed-files
 | 
			
		||||
        uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
 | 
			
		||||
        uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          files: "docker/compilers/gcc/**"
 | 
			
		||||
 | 
			
		||||
      - name: Set up Docker Buildx
 | 
			
		||||
        uses: docker/setup-buildx-action@v3
 | 
			
		||||
        uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
 | 
			
		||||
 | 
			
		||||
      - name: Login to GitHub Container Registry
 | 
			
		||||
        if: github.event_name != 'pull_request'
 | 
			
		||||
        uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
 | 
			
		||||
        if: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
 | 
			
		||||
        with:
 | 
			
		||||
          registry: ghcr.io
 | 
			
		||||
          username: ${{ github.repository_owner }}
 | 
			
		||||
          password: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
 | 
			
		||||
      - name: Login to DockerHub
 | 
			
		||||
        if: github.event_name != 'pull_request'
 | 
			
		||||
        uses: docker/login-action@v3
 | 
			
		||||
        if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' }}
 | 
			
		||||
        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
 | 
			
		||||
        with:
 | 
			
		||||
          username: ${{ secrets.DOCKERHUB_USER }}
 | 
			
		||||
          password: ${{ secrets.DOCKERHUB_PW }}
 | 
			
		||||
 | 
			
		||||
      - name: Create and push multi-arch manifest
 | 
			
		||||
        if: github.event_name != 'pull_request' && steps.changed-files.outputs.any_changed == 'true'
 | 
			
		||||
        if: ${{ github.event_name != 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
 | 
			
		||||
        run: |
 | 
			
		||||
          for image in ${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc rippleci/clio_gcc; do
 | 
			
		||||
          push_image() {
 | 
			
		||||
            image=$1
 | 
			
		||||
 | 
			
		||||
            docker buildx imagetools create \
 | 
			
		||||
              -t $image:latest \
 | 
			
		||||
              -t $image:${{ env.GCC_MAJOR_VERSION }} \
 | 
			
		||||
              -t $image:${{ env.GCC_VERSION }} \
 | 
			
		||||
              -t $image:${{ github.sha }} \
 | 
			
		||||
              $image:arm64-latest \
 | 
			
		||||
              $image:amd64-latest
 | 
			
		||||
          done
 | 
			
		||||
                -t $image:latest \
 | 
			
		||||
                -t $image:${{ env.GCC_MAJOR_VERSION }} \
 | 
			
		||||
                -t $image:${{ env.GCC_VERSION }} \
 | 
			
		||||
                -t $image:${{ github.sha }} \
 | 
			
		||||
                $image:arm64-latest \
 | 
			
		||||
                $image:amd64-latest
 | 
			
		||||
          }
 | 
			
		||||
          push_image ${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
 | 
			
		||||
          if [[ ${{ github.repository_owner }} == 'XRPLF' ]]; then
 | 
			
		||||
            push_image rippleci/clio_clang
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
  clang:
 | 
			
		||||
    name: Build and push Clang docker image
 | 
			
		||||
@@ -173,16 +179,16 @@ jobs:
 | 
			
		||||
    needs: repo
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Get changed files
 | 
			
		||||
        id: changed-files
 | 
			
		||||
        uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
 | 
			
		||||
        uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          files: "docker/compilers/clang/**"
 | 
			
		||||
 | 
			
		||||
      - uses: ./.github/actions/build_docker_image
 | 
			
		||||
        if: steps.changed-files.outputs.any_changed == 'true'
 | 
			
		||||
      - uses: ./.github/actions/build-docker-image
 | 
			
		||||
        if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
          DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
 | 
			
		||||
@@ -190,7 +196,7 @@ jobs:
 | 
			
		||||
        with:
 | 
			
		||||
          images: |
 | 
			
		||||
            ${{ needs.repo.outputs.GHCR_REPO }}/clio-clang
 | 
			
		||||
            rippleci/clio_clang
 | 
			
		||||
            ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_clang' || '' }}
 | 
			
		||||
          push_image: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
          directory: docker/compilers/clang
 | 
			
		||||
          tags: |
 | 
			
		||||
@@ -200,7 +206,7 @@ jobs:
 | 
			
		||||
          platforms: linux/amd64,linux/arm64
 | 
			
		||||
          build_args: |
 | 
			
		||||
            CLANG_MAJOR_VERSION=${{ env.CLANG_MAJOR_VERSION }}
 | 
			
		||||
          dockerhub_repo: rippleci/clio_clang
 | 
			
		||||
          dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_clang' || '' }}
 | 
			
		||||
          dockerhub_description: Clang compiler for XRPLF/clio.
 | 
			
		||||
 | 
			
		||||
  tools-amd64:
 | 
			
		||||
@@ -209,16 +215,16 @@ jobs:
 | 
			
		||||
    needs: [repo, gcc-merge]
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Get changed files
 | 
			
		||||
        id: changed-files
 | 
			
		||||
        uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
 | 
			
		||||
        uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          files: "docker/tools/**"
 | 
			
		||||
 | 
			
		||||
      - uses: ./.github/actions/build_docker_image
 | 
			
		||||
        if: steps.changed-files.outputs.any_changed == 'true'
 | 
			
		||||
      - uses: ./.github/actions/build-docker-image
 | 
			
		||||
        if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        with:
 | 
			
		||||
@@ -240,7 +246,7 @@ jobs:
 | 
			
		||||
    needs: [repo, gcc-merge]
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Get changed files
 | 
			
		||||
        id: changed-files
 | 
			
		||||
@@ -248,8 +254,8 @@ jobs:
 | 
			
		||||
        with:
 | 
			
		||||
          files: "docker/tools/**"
 | 
			
		||||
 | 
			
		||||
      - uses: ./.github/actions/build_docker_image
 | 
			
		||||
        if: steps.changed-files.outputs.any_changed == 'true'
 | 
			
		||||
      - uses: ./.github/actions/build-docker-image
 | 
			
		||||
        if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        with:
 | 
			
		||||
@@ -271,27 +277,27 @@ jobs:
 | 
			
		||||
    needs: [repo, tools-amd64, tools-arm64]
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Get changed files
 | 
			
		||||
        id: changed-files
 | 
			
		||||
        uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
 | 
			
		||||
        uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
 | 
			
		||||
        with:
 | 
			
		||||
          files: "docker/tools/**"
 | 
			
		||||
 | 
			
		||||
      - name: Set up Docker Buildx
 | 
			
		||||
        uses: docker/setup-buildx-action@v3
 | 
			
		||||
        uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
 | 
			
		||||
 | 
			
		||||
      - name: Login to GitHub Container Registry
 | 
			
		||||
        if: github.event_name != 'pull_request'
 | 
			
		||||
        uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
 | 
			
		||||
        if: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
 | 
			
		||||
        with:
 | 
			
		||||
          registry: ghcr.io
 | 
			
		||||
          username: ${{ github.repository_owner }}
 | 
			
		||||
          password: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
 | 
			
		||||
      - name: Create and push multi-arch manifest
 | 
			
		||||
        if: github.event_name != 'pull_request' && steps.changed-files.outputs.any_changed == 'true'
 | 
			
		||||
        if: ${{ github.event_name != 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
 | 
			
		||||
        run: |
 | 
			
		||||
          image=${{ needs.repo.outputs.GHCR_REPO }}/clio-tools
 | 
			
		||||
          docker buildx imagetools create \
 | 
			
		||||
@@ -300,14 +306,36 @@ jobs:
 | 
			
		||||
            $image:arm64-latest \
 | 
			
		||||
            $image:amd64-latest
 | 
			
		||||
 | 
			
		||||
  pre-commit:
 | 
			
		||||
    name: Build and push pre-commit docker image
 | 
			
		||||
    runs-on: heavy
 | 
			
		||||
    needs: [repo, tools-merge]
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
      - uses: ./.github/actions/build-docker-image
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        with:
 | 
			
		||||
          images: |
 | 
			
		||||
            ${{ needs.repo.outputs.GHCR_REPO }}/clio-pre-commit
 | 
			
		||||
          push_image: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
          directory: docker/pre-commit
 | 
			
		||||
          tags: |
 | 
			
		||||
            type=raw,value=latest
 | 
			
		||||
            type=raw,value=${{ github.sha }}
 | 
			
		||||
          platforms: linux/amd64,linux/arm64
 | 
			
		||||
          build_args: |
 | 
			
		||||
            GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
 | 
			
		||||
 | 
			
		||||
  ci:
 | 
			
		||||
    name: Build and push CI docker image
 | 
			
		||||
    runs-on: heavy
 | 
			
		||||
    needs: [repo, gcc-merge, clang, tools-merge]
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: ./.github/actions/build_docker_image
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
      - uses: ./.github/actions/build-docker-image
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
          DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
 | 
			
		||||
@@ -315,7 +343,7 @@ jobs:
 | 
			
		||||
        with:
 | 
			
		||||
          images: |
 | 
			
		||||
            ${{ needs.repo.outputs.GHCR_REPO }}/clio-ci
 | 
			
		||||
            rippleci/clio_ci
 | 
			
		||||
            ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_ci' || '' }}
 | 
			
		||||
          push_image: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
          directory: docker/ci
 | 
			
		||||
          tags: |
 | 
			
		||||
@@ -328,5 +356,5 @@ jobs:
 | 
			
		||||
            CLANG_MAJOR_VERSION=${{ env.CLANG_MAJOR_VERSION }}
 | 
			
		||||
            GCC_MAJOR_VERSION=${{ env.GCC_MAJOR_VERSION }}
 | 
			
		||||
            GCC_VERSION=${{ env.GCC_VERSION }}
 | 
			
		||||
          dockerhub_repo: rippleci/clio_ci
 | 
			
		||||
          dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_ci' || '' }}
 | 
			
		||||
          dockerhub_description: CI image for XRPLF/clio.
 | 
			
		||||
@@ -10,27 +10,28 @@ on:
 | 
			
		||||
        required: false
 | 
			
		||||
        default: false
 | 
			
		||||
        type: boolean
 | 
			
		||||
      force_upload:
 | 
			
		||||
        description: "Force upload of all dependencies"
 | 
			
		||||
        required: false
 | 
			
		||||
        default: false
 | 
			
		||||
        type: boolean
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches: [develop]
 | 
			
		||||
    paths:
 | 
			
		||||
      - .github/workflows/upload_conan_deps.yml
 | 
			
		||||
      - .github/workflows/upload-conan-deps.yml
 | 
			
		||||
 | 
			
		||||
      - .github/actions/generate/action.yml
 | 
			
		||||
      - .github/actions/prepare_runner/action.yml
 | 
			
		||||
      - .github/actions/conan/action.yml
 | 
			
		||||
      - ".github/scripts/conan/**"
 | 
			
		||||
      - "!.github/scripts/conan/apple-clang-local.profile"
 | 
			
		||||
 | 
			
		||||
      - conanfile.py
 | 
			
		||||
      - conan.lock
 | 
			
		||||
  push:
 | 
			
		||||
    branches: [develop]
 | 
			
		||||
    paths:
 | 
			
		||||
      - .github/workflows/upload_conan_deps.yml
 | 
			
		||||
      - .github/workflows/upload-conan-deps.yml
 | 
			
		||||
 | 
			
		||||
      - .github/actions/generate/action.yml
 | 
			
		||||
      - .github/actions/prepare_runner/action.yml
 | 
			
		||||
      - .github/actions/conan/action.yml
 | 
			
		||||
      - ".github/scripts/conan/**"
 | 
			
		||||
      - "!.github/scripts/conan/apple-clang-local.profile"
 | 
			
		||||
 | 
			
		||||
      - conanfile.py
 | 
			
		||||
      - conan.lock
 | 
			
		||||
@@ -45,7 +46,7 @@ jobs:
 | 
			
		||||
    outputs:
 | 
			
		||||
      matrix: ${{ steps.set-matrix.outputs.matrix }}
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Calculate conan matrix
 | 
			
		||||
        id: set-matrix
 | 
			
		||||
@@ -59,6 +60,7 @@ jobs:
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
 | 
			
		||||
      max-parallel: 10
 | 
			
		||||
 | 
			
		||||
    runs-on: ${{ matrix.os }}
 | 
			
		||||
    container: ${{ matrix.container != '' && fromJson(matrix.container) || null }}
 | 
			
		||||
@@ -67,23 +69,23 @@ jobs:
 | 
			
		||||
      CONAN_PROFILE: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
 | 
			
		||||
 | 
			
		||||
      - name: Prepare runner
 | 
			
		||||
        uses: ./.github/actions/prepare_runner
 | 
			
		||||
        uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
 | 
			
		||||
        with:
 | 
			
		||||
          disable_ccache: true
 | 
			
		||||
 | 
			
		||||
      - name: Setup conan on macOS
 | 
			
		||||
        if: runner.os == 'macOS'
 | 
			
		||||
        if: ${{ runner.os == 'macOS' }}
 | 
			
		||||
        shell: bash
 | 
			
		||||
        run: ./.github/scripts/conan/init.sh
 | 
			
		||||
 | 
			
		||||
      - name: Show conan profile
 | 
			
		||||
        run: conan profile show --profile:all ${{ env.CONAN_PROFILE }}
 | 
			
		||||
 | 
			
		||||
      - name: Run conan and cmake
 | 
			
		||||
        uses: ./.github/actions/generate
 | 
			
		||||
      - name: Run conan
 | 
			
		||||
        uses: ./.github/actions/conan
 | 
			
		||||
        with:
 | 
			
		||||
          conan_profile: ${{ env.CONAN_PROFILE }}
 | 
			
		||||
          # We check that everything builds fine from source on scheduled runs
 | 
			
		||||
@@ -92,9 +94,11 @@ jobs:
 | 
			
		||||
          build_type: ${{ matrix.build_type }}
 | 
			
		||||
 | 
			
		||||
      - name: Login to Conan
 | 
			
		||||
        if: github.event_name != 'pull_request'
 | 
			
		||||
        run: conan remote login -p ${{ secrets.CONAN_PASSWORD }} ripple ${{ secrets.CONAN_USERNAME }}
 | 
			
		||||
        if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' }}
 | 
			
		||||
        run: conan remote login -p ${{ secrets.CONAN_PASSWORD }} xrplf ${{ secrets.CONAN_USERNAME }}
 | 
			
		||||
 | 
			
		||||
      - name: Upload Conan packages
 | 
			
		||||
        if: github.event_name != 'pull_request' && github.event_name != 'schedule'
 | 
			
		||||
        run: conan upload "*" -r=ripple --confirm
 | 
			
		||||
        if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' && github.event_name != 'schedule' }}
 | 
			
		||||
        env:
 | 
			
		||||
          FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
 | 
			
		||||
        run: conan upload "*" -r=xrplf --confirm ${FORCE_OPTION}
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -9,4 +9,3 @@
 | 
			
		||||
.sanitizer-report
 | 
			
		||||
CMakeUserPresets.json
 | 
			
		||||
config.json
 | 
			
		||||
src/util/build/Build.cpp
 | 
			
		||||
 
 | 
			
		||||
@@ -11,12 +11,15 @@
 | 
			
		||||
#
 | 
			
		||||
# See https://pre-commit.com for more information
 | 
			
		||||
# See https://pre-commit.com/hooks.html for more hooks
 | 
			
		||||
exclude: ^(docs/doxygen-awesome-theme/|conan\.lock$)
 | 
			
		||||
exclude: |
 | 
			
		||||
  (?x)^(
 | 
			
		||||
    docs/doxygen-awesome-theme/.*
 | 
			
		||||
  )$
 | 
			
		||||
 | 
			
		||||
repos:
 | 
			
		||||
  # `pre-commit sample-config` default hooks
 | 
			
		||||
  - repo: https://github.com/pre-commit/pre-commit-hooks
 | 
			
		||||
    rev: cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b # frozen: v5.0.0
 | 
			
		||||
    rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
 | 
			
		||||
    hooks:
 | 
			
		||||
      - id: check-added-large-files
 | 
			
		||||
      - id: check-executables-have-shebangs
 | 
			
		||||
@@ -37,13 +40,13 @@ repos:
 | 
			
		||||
        exclude: LICENSE.md
 | 
			
		||||
 | 
			
		||||
  - repo: https://github.com/hadolint/hadolint
 | 
			
		||||
    rev: c3dc18df7a501f02a560a2cc7ba3c69a85ca01d3 # frozen: v2.13.1-beta
 | 
			
		||||
    rev: 4e697ba704fd23b2409b947a319c19c3ee54d24f # frozen: v2.14.0
 | 
			
		||||
    hooks:
 | 
			
		||||
      - id: hadolint-docker
 | 
			
		||||
        # hadolint-docker is a special hook that runs hadolint in a Docker container
 | 
			
		||||
        # Docker is not installed in the environment where pre-commit is run
 | 
			
		||||
        stages: [manual]
 | 
			
		||||
        entry: hadolint/hadolint:v2.12.1-beta hadolint
 | 
			
		||||
        entry: hadolint/hadolint:v2.14.0 hadolint
 | 
			
		||||
 | 
			
		||||
  - repo: https://github.com/codespell-project/codespell
 | 
			
		||||
    rev: 63c8f8312b7559622c0d82815639671ae42132ac # frozen: v2.4.1
 | 
			
		||||
@@ -55,12 +58,6 @@ repos:
 | 
			
		||||
            --ignore-words=pre-commit-hooks/codespell_ignore.txt,
 | 
			
		||||
          ]
 | 
			
		||||
 | 
			
		||||
  - repo: https://github.com/trufflesecurity/trufflehog
 | 
			
		||||
    rev: 6641d4ba5b684fffe195b9820345de1bf19f3181 # frozen: v3.89.2
 | 
			
		||||
    hooks:
 | 
			
		||||
      - id: trufflehog
 | 
			
		||||
        entry: trufflehog git file://. --since-commit HEAD --no-verification --fail
 | 
			
		||||
 | 
			
		||||
  # Running some C++ hooks before clang-format
 | 
			
		||||
  # to ensure that the style is consistent.
 | 
			
		||||
  - repo: local
 | 
			
		||||
@@ -86,7 +83,7 @@ repos:
 | 
			
		||||
        language: script
 | 
			
		||||
 | 
			
		||||
  - repo: https://github.com/pre-commit/mirrors-clang-format
 | 
			
		||||
    rev: 6b9072cd80691b1b48d80046d884409fb1d962d1 # frozen: v20.1.7
 | 
			
		||||
    rev: 719856d56a62953b8d2839fb9e851f25c3cfeef8 # frozen: v21.1.2
 | 
			
		||||
    hooks:
 | 
			
		||||
      - id: clang-format
 | 
			
		||||
        args: [--style=file]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,5 @@
 | 
			
		||||
cmake_minimum_required(VERSION 3.20)
 | 
			
		||||
 | 
			
		||||
set(CMAKE_PROJECT_INCLUDE_BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClioVersion.cmake)
 | 
			
		||||
 | 
			
		||||
project(clio VERSION ${CLIO_VERSION} HOMEPAGE_URL "https://github.com/XRPLF/clio"
 | 
			
		||||
        DESCRIPTION "An XRP Ledger API Server"
 | 
			
		||||
)
 | 
			
		||||
@@ -13,7 +11,7 @@ option(integration_tests "Build integration tests" FALSE)
 | 
			
		||||
option(benchmark "Build benchmarks" FALSE)
 | 
			
		||||
option(docs "Generate doxygen docs" FALSE)
 | 
			
		||||
option(coverage "Build test coverage report" FALSE)
 | 
			
		||||
option(packaging "Create distribution packages" FALSE)
 | 
			
		||||
option(package "Create distribution packages" FALSE)
 | 
			
		||||
option(lint "Run clang-tidy checks during compilation" FALSE)
 | 
			
		||||
option(static "Statically linked Clio" FALSE)
 | 
			
		||||
option(snapshot "Build snapshot tool" FALSE)
 | 
			
		||||
@@ -31,6 +29,7 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
 | 
			
		||||
include(Ccache)
 | 
			
		||||
include(CheckCXXCompilerFlag)
 | 
			
		||||
include(ClangTidy)
 | 
			
		||||
include(Linker)
 | 
			
		||||
 | 
			
		||||
add_library(clio_options INTERFACE)
 | 
			
		||||
target_compile_features(clio_options INTERFACE cxx_std_23) # Clio needs c++23 but deps can remain c++20 for now
 | 
			
		||||
@@ -40,11 +39,6 @@ if (verbose)
 | 
			
		||||
  set(CMAKE_VERBOSE_MAKEFILE TRUE)
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
if (packaging)
 | 
			
		||||
  add_definitions(-DPKG=1)
 | 
			
		||||
  target_compile_definitions(clio_options INTERFACE PKG=1)
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
# Clio tweaks and checks
 | 
			
		||||
include(CheckCompiler)
 | 
			
		||||
include(Settings)
 | 
			
		||||
@@ -58,6 +52,7 @@ include(deps/Threads)
 | 
			
		||||
include(deps/libfmt)
 | 
			
		||||
include(deps/cassandra)
 | 
			
		||||
include(deps/libbacktrace)
 | 
			
		||||
include(deps/spdlog)
 | 
			
		||||
 | 
			
		||||
add_subdirectory(src)
 | 
			
		||||
add_subdirectory(tests)
 | 
			
		||||
@@ -93,8 +88,8 @@ if (docs)
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
include(install/install)
 | 
			
		||||
if (packaging)
 | 
			
		||||
  include(cmake/packaging.cmake) # This file exists only in build runner
 | 
			
		||||
if (package)
 | 
			
		||||
  include(ClioPackage)
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
if (snapshot)
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,6 @@ Below are some useful docs to learn more about Clio.
 | 
			
		||||
 | 
			
		||||
- [How to configure Clio and rippled](./docs/configure-clio.md)
 | 
			
		||||
- [How to run Clio](./docs/run-clio.md)
 | 
			
		||||
- [Logging](./docs/logging.md)
 | 
			
		||||
- [Troubleshooting guide](./docs/trouble_shooting.md)
 | 
			
		||||
 | 
			
		||||
**General reference material:**
 | 
			
		||||
 
 | 
			
		||||
@@ -7,10 +7,12 @@ target_sources(
 | 
			
		||||
          Playground.cpp
 | 
			
		||||
          # ExecutionContext
 | 
			
		||||
          util/async/ExecutionContextBenchmarks.cpp
 | 
			
		||||
          # Logger
 | 
			
		||||
          util/log/LoggerBenchmark.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
include(deps/gbench)
 | 
			
		||||
 | 
			
		||||
target_include_directories(clio_benchmark PRIVATE .)
 | 
			
		||||
target_link_libraries(clio_benchmark PUBLIC clio_etl benchmark::benchmark_main)
 | 
			
		||||
target_link_libraries(clio_benchmark PUBLIC clio_util benchmark::benchmark_main spdlog::spdlog)
 | 
			
		||||
set_target_properties(clio_benchmark PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										149
									
								
								benchmarks/util/log/LoggerBenchmark.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								benchmarks/util/log/LoggerBenchmark.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
/*
 | 
			
		||||
    This file is part of clio: https://github.com/XRPLF/clio
 | 
			
		||||
    Copyright (c) 2025, the clio developers.
 | 
			
		||||
 | 
			
		||||
    Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
    purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
    copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 | 
			
		||||
    THE  SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
    WITH  REGARD  TO  THIS  SOFTWARE  INCLUDING  ALL  IMPLIED  WARRANTIES  OF
 | 
			
		||||
    MERCHANTABILITY  AND  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
    ANY  SPECIAL,  DIRECT,  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
    WHATSOEVER  RESULTING  FROM  LOSS  OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
    ACTION  OF  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include "util/config/ConfigDefinition.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
#include "util/prometheus/Prometheus.hpp"
 | 
			
		||||
 | 
			
		||||
#include <benchmark/benchmark.h>
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
#include <spdlog/async.h>
 | 
			
		||||
#include <spdlog/async_logger.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 | 
			
		||||
#include <barrier>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
using namespace util;
 | 
			
		||||
 | 
			
		||||
static constexpr auto kLOG_FORMAT = "%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v";
 | 
			
		||||
 | 
			
		||||
struct BenchmarkLoggingInitializer {
 | 
			
		||||
    [[nodiscard]] static std::shared_ptr<spdlog::sinks::sink>
 | 
			
		||||
    createFileSink(LogService::FileLoggingParams const& params)
 | 
			
		||||
    {
 | 
			
		||||
        return LogService::createFileSink(params, kLOG_FORMAT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static Logger
 | 
			
		||||
    getLogger(std::shared_ptr<spdlog::logger> logger)
 | 
			
		||||
    {
 | 
			
		||||
        return Logger(std::move(logger));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
std::string
 | 
			
		||||
uniqueLogDir()
 | 
			
		||||
{
 | 
			
		||||
    auto const epochTime = std::chrono::high_resolution_clock::now().time_since_epoch();
 | 
			
		||||
    auto const tmpDir = std::filesystem::temp_directory_path();
 | 
			
		||||
    std::string const dirName =
 | 
			
		||||
        fmt::format("logs_{}", std::chrono::duration_cast<std::chrono::microseconds>(epochTime).count());
 | 
			
		||||
    return tmpDir / "clio_benchmark" / dirName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // anonymous namespace
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
benchmarkConcurrentFileLogging(benchmark::State& state)
 | 
			
		||||
{
 | 
			
		||||
    auto const numThreads = static_cast<size_t>(state.range(0));
 | 
			
		||||
    auto const messagesPerThread = static_cast<size_t>(state.range(1));
 | 
			
		||||
 | 
			
		||||
    PrometheusService::init(config::getClioConfig());
 | 
			
		||||
 | 
			
		||||
    auto const logDir = uniqueLogDir();
 | 
			
		||||
    for (auto _ : state) {
 | 
			
		||||
        state.PauseTiming();
 | 
			
		||||
 | 
			
		||||
        std::filesystem::create_directories(logDir);
 | 
			
		||||
        static constexpr size_t kQUEUE_SIZE = 8192;
 | 
			
		||||
        static constexpr size_t kTHREAD_COUNT = 1;
 | 
			
		||||
        spdlog::init_thread_pool(kQUEUE_SIZE, kTHREAD_COUNT);
 | 
			
		||||
 | 
			
		||||
        auto fileSink = BenchmarkLoggingInitializer::createFileSink({
 | 
			
		||||
            .logDir = logDir,
 | 
			
		||||
            .rotationSizeMB = 5,
 | 
			
		||||
            .dirMaxFiles = 25,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        std::vector<std::thread> threads;
 | 
			
		||||
        threads.reserve(numThreads);
 | 
			
		||||
 | 
			
		||||
        std::chrono::high_resolution_clock::time_point start;
 | 
			
		||||
        std::barrier barrier(numThreads, [&state, &start]() {
 | 
			
		||||
            state.ResumeTiming();
 | 
			
		||||
            start = std::chrono::high_resolution_clock::now();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        for (size_t threadNum = 0; threadNum < numThreads; ++threadNum) {
 | 
			
		||||
            threads.emplace_back([threadNum, messagesPerThread, fileSink, &barrier]() {
 | 
			
		||||
                std::string const channel = fmt::format("Thread_{}", threadNum);
 | 
			
		||||
                auto logger = std::make_shared<spdlog::async_logger>(
 | 
			
		||||
                    channel, fileSink, spdlog::thread_pool(), spdlog::async_overflow_policy::block
 | 
			
		||||
                );
 | 
			
		||||
                spdlog::register_logger(logger);
 | 
			
		||||
                Logger const threadLogger = BenchmarkLoggingInitializer::getLogger(std::move(logger));
 | 
			
		||||
 | 
			
		||||
                barrier.arrive_and_wait();
 | 
			
		||||
 | 
			
		||||
                for (size_t messageNum = 0; messageNum < messagesPerThread; ++messageNum) {
 | 
			
		||||
                    LOG(threadLogger.info()) << "Test log message #" << messageNum;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (auto& thread : threads) {
 | 
			
		||||
            thread.join();
 | 
			
		||||
        }
 | 
			
		||||
        spdlog::shutdown();
 | 
			
		||||
 | 
			
		||||
        auto const end = std::chrono::high_resolution_clock::now();
 | 
			
		||||
        state.SetIterationTime(std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count());
 | 
			
		||||
 | 
			
		||||
        std::filesystem::remove_all(logDir);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto const totalMessages = numThreads * messagesPerThread;
 | 
			
		||||
    state.counters["TotalMessagesRate"] = benchmark::Counter(totalMessages, benchmark::Counter::kIsRate);
 | 
			
		||||
    state.counters["Threads"] = numThreads;
 | 
			
		||||
    state.counters["MessagesPerThread"] = messagesPerThread;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// One line of log message is around 110 bytes
 | 
			
		||||
// So, 100K messages is around 10.5MB
 | 
			
		||||
 | 
			
		||||
BENCHMARK(benchmarkConcurrentFileLogging)
 | 
			
		||||
    ->ArgsProduct({
 | 
			
		||||
        // Number of threads
 | 
			
		||||
        {1, 2, 4, 8},
 | 
			
		||||
        // Messages per thread
 | 
			
		||||
        {10'000, 100'000, 500'000, 1'000'000, 10'000'000},
 | 
			
		||||
    })
 | 
			
		||||
    ->UseManualTime()
 | 
			
		||||
    ->Unit(benchmark::kMillisecond);
 | 
			
		||||
							
								
								
									
										8
									
								
								cmake/ClioPackage.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								cmake/ClioPackage.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
include("${CMAKE_CURRENT_LIST_DIR}/ClioVersion.cmake")
 | 
			
		||||
 | 
			
		||||
set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/clio")
 | 
			
		||||
set(CPACK_PACKAGE_VERSION "${CLIO_VERSION}")
 | 
			
		||||
set(CPACK_STRIP_FILES TRUE)
 | 
			
		||||
 | 
			
		||||
include(pkg/deb)
 | 
			
		||||
include(CPack)
 | 
			
		||||
@@ -1,7 +1,3 @@
 | 
			
		||||
#[===================================================================[
 | 
			
		||||
   write version to source
 | 
			
		||||
#]===================================================================]
 | 
			
		||||
 | 
			
		||||
find_package(Git REQUIRED)
 | 
			
		||||
 | 
			
		||||
set(GIT_COMMAND describe --tags --exact-match)
 | 
			
		||||
@@ -10,15 +6,17 @@ execute_process(
 | 
			
		||||
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
 | 
			
		||||
  OUTPUT_VARIABLE TAG
 | 
			
		||||
  RESULT_VARIABLE RC
 | 
			
		||||
  OUTPUT_STRIP_TRAILING_WHITESPACE
 | 
			
		||||
  ERROR_VARIABLE ERR
 | 
			
		||||
  OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if (RC EQUAL 0)
 | 
			
		||||
  # if we are on a tag, use the tag name
 | 
			
		||||
  message(STATUS "Found tag '${TAG}' in git. Will use it as Clio version")
 | 
			
		||||
  set(CLIO_VERSION "${TAG}")
 | 
			
		||||
  set(DOC_CLIO_VERSION "${TAG}")
 | 
			
		||||
else ()
 | 
			
		||||
  # if not, use YYYYMMDDHMS-<branch>-<git-rev>
 | 
			
		||||
  message(STATUS "Error finding tag in git: ${ERR}")
 | 
			
		||||
  message(STATUS "Will use 'YYYYMMDDHMS-<branch>-<git-rev>' as Clio version")
 | 
			
		||||
 | 
			
		||||
  set(GIT_COMMAND show -s --date=format:%Y%m%d%H%M%S --format=%cd)
 | 
			
		||||
  execute_process(
 | 
			
		||||
@@ -47,5 +45,3 @@ if (CMAKE_BUILD_TYPE MATCHES Debug)
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
message(STATUS "Build version: ${CLIO_VERSION}")
 | 
			
		||||
 | 
			
		||||
configure_file(${CMAKE_CURRENT_LIST_DIR}/Build.cpp.in ${CMAKE_CURRENT_LIST_DIR}/../src/util/build/Build.cpp)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								cmake/Linker.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								cmake/Linker.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
if (DEFINED CMAKE_LINKER_TYPE)
 | 
			
		||||
  message(STATUS "Custom linker is already set: ${CMAKE_LINKER_TYPE}")
 | 
			
		||||
  return()
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
find_program(MOLD_PATH mold)
 | 
			
		||||
 | 
			
		||||
if (MOLD_PATH AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
 | 
			
		||||
  message(STATUS "Using Mold linker: ${MOLD_PATH}")
 | 
			
		||||
  set(CMAKE_LINKER_TYPE MOLD)
 | 
			
		||||
endif ()
 | 
			
		||||
							
								
								
									
										5
									
								
								cmake/deps/spdlog.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								cmake/deps/spdlog.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
find_package(spdlog REQUIRED)
 | 
			
		||||
 | 
			
		||||
if (NOT TARGET spdlog::spdlog)
 | 
			
		||||
  message(FATAL_ERROR "spdlog::spdlog target not found")
 | 
			
		||||
endif ()
 | 
			
		||||
@@ -1,17 +0,0 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Clio XRPL API server
 | 
			
		||||
Documentation=https://github.com/XRPLF/clio.git
 | 
			
		||||
 | 
			
		||||
After=network-online.target
 | 
			
		||||
Wants=network-online.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
ExecStart=@CLIO_INSTALL_DIR@/bin/clio_server @CLIO_INSTALL_DIR@/etc/config.json
 | 
			
		||||
Restart=on-failure
 | 
			
		||||
User=clio
 | 
			
		||||
Group=clio
 | 
			
		||||
LimitNOFILE=65536
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
@@ -1,13 +1,13 @@
 | 
			
		||||
set(CLIO_INSTALL_DIR "/opt/clio")
 | 
			
		||||
set(CMAKE_INSTALL_PREFIX ${CLIO_INSTALL_DIR})
 | 
			
		||||
set(CMAKE_INSTALL_PREFIX "${CLIO_INSTALL_DIR}" CACHE PATH "Install prefix" FORCE)
 | 
			
		||||
 | 
			
		||||
install(TARGETS clio_server DESTINATION bin)
 | 
			
		||||
set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
 | 
			
		||||
 | 
			
		||||
include(GNUInstallDirs)
 | 
			
		||||
 | 
			
		||||
install(TARGETS clio_server DESTINATION "${CMAKE_INSTALL_BINDIR}")
 | 
			
		||||
 | 
			
		||||
file(READ docs/examples/config/example-config.json config)
 | 
			
		||||
string(REGEX REPLACE "./clio_log" "/var/log/clio/" config "${config}")
 | 
			
		||||
file(WRITE ${CMAKE_BINARY_DIR}/install-config.json "${config}")
 | 
			
		||||
install(FILES ${CMAKE_BINARY_DIR}/install-config.json DESTINATION etc RENAME config.json)
 | 
			
		||||
 | 
			
		||||
configure_file("${CMAKE_SOURCE_DIR}/cmake/install/clio.service.in" "${CMAKE_BINARY_DIR}/clio.service")
 | 
			
		||||
 | 
			
		||||
install(FILES "${CMAKE_BINARY_DIR}/clio.service" DESTINATION /lib/systemd/system)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								cmake/pkg/deb.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								cmake/pkg/deb.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
set(CPACK_GENERATOR "DEB")
 | 
			
		||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/XRPLF/clio")
 | 
			
		||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Ripple Labs Inc. <support@ripple.com>")
 | 
			
		||||
 | 
			
		||||
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
 | 
			
		||||
 | 
			
		||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
 | 
			
		||||
 | 
			
		||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA ${CMAKE_SOURCE_DIR}/cmake/pkg/postinst)
 | 
			
		||||
 | 
			
		||||
# We must replace "-" with "~" otherwise dpkg will sort "X.Y.Z-b1" as greater than "X.Y.Z"
 | 
			
		||||
string(REPLACE "-" "~" git "${CPACK_PACKAGE_VERSION}")
 | 
			
		||||
							
								
								
									
										46
									
								
								cmake/pkg/postinst
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										46
									
								
								cmake/pkg/postinst
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
USER_NAME=clio
 | 
			
		||||
GROUP_NAME="${USER_NAME}"
 | 
			
		||||
CLIO_EXECUTABLE="clio_server"
 | 
			
		||||
CLIO_PREFIX="/opt/clio"
 | 
			
		||||
CLIO_BIN="$CLIO_PREFIX/bin/${CLIO_EXECUTABLE}"
 | 
			
		||||
CLIO_CONFIG="$CLIO_PREFIX/etc/config.json"
 | 
			
		||||
 | 
			
		||||
case "$1" in
 | 
			
		||||
    configure)
 | 
			
		||||
        if ! id -u "$USER_NAME" >/dev/null 2>&1; then
 | 
			
		||||
            # Users who should not have a home directory should have their home directory set to /nonexistent
 | 
			
		||||
            # https://www.debian.org/doc/debian-policy/ch-opersys.html#non-existent-home-directories
 | 
			
		||||
            useradd \
 | 
			
		||||
                --system \
 | 
			
		||||
                --home-dir /nonexistent \
 | 
			
		||||
                --no-create-home \
 | 
			
		||||
                --shell /usr/sbin/nologin \
 | 
			
		||||
                --comment "system user for ${CLIO_EXECUTABLE}" \
 | 
			
		||||
                --user-group \
 | 
			
		||||
                ${USER_NAME}
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        install -d -o "$USER_NAME" -g "$GROUP_NAME" /var/log/clio
 | 
			
		||||
 | 
			
		||||
        if [ -f "$CLIO_CONFIG" ]; then
 | 
			
		||||
            chown "$USER_NAME:$GROUP_NAME" "$CLIO_CONFIG"
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        chown -R "$USER_NAME:$GROUP_NAME" "$CLIO_PREFIX"
 | 
			
		||||
 | 
			
		||||
        ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
 | 
			
		||||
 | 
			
		||||
        ;;
 | 
			
		||||
    abort-upgrade|abort-remove|abort-deconfigure)
 | 
			
		||||
        ;;
 | 
			
		||||
    *)
 | 
			
		||||
        echo "postinst called with unknown argument \`$1'" >&2
 | 
			
		||||
        exit 1
 | 
			
		||||
        ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
exit 0
 | 
			
		||||
							
								
								
									
										73
									
								
								conan.lock
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								conan.lock
									
									
									
									
									
								
							@@ -1,48 +1,49 @@
 | 
			
		||||
{
 | 
			
		||||
    "version": "0.5",
 | 
			
		||||
    "requires": [
 | 
			
		||||
        "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1752006674.465",
 | 
			
		||||
        "xxhash/0.8.2#7856c968c985b2981b707ee8f2413b2b%1752006674.334",
 | 
			
		||||
        "xrpl/2.5.0#7880d1696f11fceb1d498570f1a184c8%1752006708.218",
 | 
			
		||||
        "sqlite3/3.47.0#7a0904fd061f5f8a2366c294f9387830%1752006674.338",
 | 
			
		||||
        "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1752006674.465",
 | 
			
		||||
        "re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1752006674.077",
 | 
			
		||||
        "rapidjson/cci.20220822#1b9d8c2256876a154172dc5cfbe447c6%1752006673.227",
 | 
			
		||||
        "protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1752006673.172",
 | 
			
		||||
        "openssl/1.1.1v#216374e4fb5b2e0f5ab1fb6f27b5b434%1752006673.069",
 | 
			
		||||
        "nudb/2.0.8#63990d3e517038e04bf529eb8167f69f%1752006673.862",
 | 
			
		||||
        "minizip/1.2.13#9e87d57804bd372d6d1e32b1871517a3%1752006672.983",
 | 
			
		||||
        "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1752006672.825",
 | 
			
		||||
        "libuv/1.46.0#78565d142ac7102776256328a26cdf60%1752006672.827",
 | 
			
		||||
        "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1752006672.826",
 | 
			
		||||
        "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1752006672.822",
 | 
			
		||||
        "libarchive/3.7.6#e0453864b2a4d225f06b3304903cb2b7%1752006672.917",
 | 
			
		||||
        "http_parser/2.9.4#98d91690d6fd021e9e624218a85d9d97%1752006672.658",
 | 
			
		||||
        "gtest/1.14.0#f8f0757a574a8dd747d16af62d6eb1b7%1752006671.555",
 | 
			
		||||
        "grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1752006671.777",
 | 
			
		||||
        "fmt/11.2.0#579bb2cdf4a7607621beea4eb4651e0f%1752006671.557",
 | 
			
		||||
        "date/3.0.3#cf28fe9c0aab99fe12da08aa42df65e1%1752006671.553",
 | 
			
		||||
        "cassandra-cpp-driver/2.17.0#e50919efac8418c26be6671fd702540a%1752006671.654",
 | 
			
		||||
        "c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1752006671.554",
 | 
			
		||||
        "bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1752006671.549",
 | 
			
		||||
        "boost/1.83.0#5bcb2a14a35875e328bf312e080d3562%1752006671.557",
 | 
			
		||||
        "benchmark/1.8.3#1a2ce62c99e2b3feaa57b1f0c15a8c46%1752006671.408",
 | 
			
		||||
        "abseil/20230802.1#f0f91485b111dc9837a68972cb19ca7b%1752006671.555"
 | 
			
		||||
        "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
 | 
			
		||||
        "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1756234289.683",
 | 
			
		||||
        "xrpl/2.6.1#973af2bf9631f239941dd9f5a100bb84%1759275059.342",
 | 
			
		||||
        "sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1756234266.869",
 | 
			
		||||
        "spdlog/1.15.3#3ca0e9e6b83af4d0151e26541d140c86%1754401846.61",
 | 
			
		||||
        "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318",
 | 
			
		||||
        "re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1756234257.976",
 | 
			
		||||
        "rapidjson/cci.20220822#1b9d8c2256876a154172dc5cfbe447c6%1754325007.656",
 | 
			
		||||
        "protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
 | 
			
		||||
        "openssl/1.1.1w#a8f0792d7c5121b954578a7149d23e03%1756223730.729",
 | 
			
		||||
        "nudb/2.0.9#c62cfd501e57055a7e0d8ee3d5e5427d%1756234237.107",
 | 
			
		||||
        "minizip/1.2.13#9e87d57804bd372d6d1e32b1871517a3%1754325004.374",
 | 
			
		||||
        "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999",
 | 
			
		||||
        "libuv/1.46.0#dc28c1f653fa197f00db5b577a6f6011%1754325003.592",
 | 
			
		||||
        "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64",
 | 
			
		||||
        "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1756230911.03",
 | 
			
		||||
        "libarchive/3.8.1#5cf685686322e906cb42706ab7e099a8%1756234256.696",
 | 
			
		||||
        "http_parser/2.9.4#98d91690d6fd021e9e624218a85d9d97%1754325001.385",
 | 
			
		||||
        "gtest/1.14.0#f8f0757a574a8dd747d16af62d6eb1b7%1754325000.842",
 | 
			
		||||
        "grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1756234248.958",
 | 
			
		||||
        "fmt/11.2.0#579bb2cdf4a7607621beea4eb4651e0f%1754324999.086",
 | 
			
		||||
        "doctest/2.4.11#a4211dfc329a16ba9f280f9574025659%1756234220.819",
 | 
			
		||||
        "date/3.0.4#f74bbba5a08fa388256688743136cb6f%1756234217.493",
 | 
			
		||||
        "cassandra-cpp-driver/2.17.0#e50919efac8418c26be6671fd702540a%1754324997.363",
 | 
			
		||||
        "c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1756234217.915",
 | 
			
		||||
        "bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1756234261.716",
 | 
			
		||||
        "boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368%1754325043.336",
 | 
			
		||||
        "benchmark/1.9.4#ce4403f7a24d3e1f907cd9da4b678be4%1754578869.672",
 | 
			
		||||
        "abseil/20230802.1#f0f91485b111dc9837a68972cb19ca7b%1756234220.907"
 | 
			
		||||
    ],
 | 
			
		||||
    "build_requires": [
 | 
			
		||||
        "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1752006674.465",
 | 
			
		||||
        "protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1752006673.172",
 | 
			
		||||
        "protobuf/3.21.9#64ce20e1d9ea24f3d6c504015d5f6fa8%1752006673.173",
 | 
			
		||||
        "cmake/3.31.7#57c3e118bcf267552c0ea3f8bee1e7d5%1752006671.64",
 | 
			
		||||
        "b2/5.3.2#7b5fabfe7088ae933fb3e78302343ea0%1752006671.407"
 | 
			
		||||
        "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
 | 
			
		||||
        "protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
 | 
			
		||||
        "cmake/3.31.8#dde3bde00bb843687e55aea5afa0e220%1756234232.89",
 | 
			
		||||
        "b2/5.3.3#107c15377719889654eb9a162a673975%1756234226.28"
 | 
			
		||||
    ],
 | 
			
		||||
    "python_requires": [],
 | 
			
		||||
    "overrides": {
 | 
			
		||||
        "boost/1.83.0": [
 | 
			
		||||
            null,
 | 
			
		||||
            "boost/1.83.0#5bcb2a14a35875e328bf312e080d3562"
 | 
			
		||||
            "boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368"
 | 
			
		||||
        ],
 | 
			
		||||
        "protobuf/3.21.9": [
 | 
			
		||||
        "protobuf/3.21.12": [
 | 
			
		||||
            null,
 | 
			
		||||
            "protobuf/3.21.12"
 | 
			
		||||
        ],
 | 
			
		||||
@@ -50,8 +51,8 @@
 | 
			
		||||
            "lz4/1.10.0"
 | 
			
		||||
        ],
 | 
			
		||||
        "sqlite3/3.44.2": [
 | 
			
		||||
            "sqlite3/3.47.0"
 | 
			
		||||
            "sqlite3/3.49.1"
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    "config_requires": []
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								conanfile.py
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								conanfile.py
									
									
									
									
									
								
							@@ -9,19 +9,7 @@ class ClioConan(ConanFile):
 | 
			
		||||
    url = 'https://github.com/xrplf/clio'
 | 
			
		||||
    description = 'Clio RPC server'
 | 
			
		||||
    settings = 'os', 'compiler', 'build_type', 'arch'
 | 
			
		||||
    options = {
 | 
			
		||||
        'static': [True, False],              # static linkage
 | 
			
		||||
        'verbose': [True, False],
 | 
			
		||||
        'tests': [True, False],               # build unit tests; create `clio_tests` binary
 | 
			
		||||
        'integration_tests': [True, False],   # build integration tests; create `clio_integration_tests` binary
 | 
			
		||||
        'benchmark': [True, False],           # build benchmarks; create `clio_benchmarks` binary
 | 
			
		||||
        'docs': [True, False],                # doxygen API docs; create custom target 'docs'
 | 
			
		||||
        'packaging': [True, False],           # create distribution packages
 | 
			
		||||
        'coverage': [True, False],            # build for test coverage report; create custom target `clio_tests-ccov`
 | 
			
		||||
        'lint': [True, False],                # run clang-tidy checks during compilation
 | 
			
		||||
        'snapshot': [True, False],            # build export/import snapshot tool
 | 
			
		||||
        'time_trace': [True, False]           # build using -ftime-trace to create compiler trace reports
 | 
			
		||||
    }
 | 
			
		||||
    options = {}
 | 
			
		||||
 | 
			
		||||
    requires = [
 | 
			
		||||
        'boost/1.83.0',
 | 
			
		||||
@@ -29,25 +17,14 @@ class ClioConan(ConanFile):
 | 
			
		||||
        'fmt/11.2.0',
 | 
			
		||||
        'protobuf/3.21.12',
 | 
			
		||||
        'grpc/1.50.1',
 | 
			
		||||
        'openssl/1.1.1v',
 | 
			
		||||
        'xrpl/2.5.0',
 | 
			
		||||
        'openssl/1.1.1w',
 | 
			
		||||
        'xrpl/2.6.1',
 | 
			
		||||
        'zlib/1.3.1',
 | 
			
		||||
        'libbacktrace/cci.20210118'
 | 
			
		||||
        'libbacktrace/cci.20210118',
 | 
			
		||||
        'spdlog/1.15.3',
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    default_options = {
 | 
			
		||||
        'static': False,
 | 
			
		||||
        'verbose': False,
 | 
			
		||||
        'tests': False,
 | 
			
		||||
        'integration_tests': False,
 | 
			
		||||
        'benchmark': False,
 | 
			
		||||
        'packaging': False,
 | 
			
		||||
        'coverage': False,
 | 
			
		||||
        'lint': False,
 | 
			
		||||
        'docs': False,
 | 
			
		||||
        'snapshot': False,
 | 
			
		||||
        'time_trace': False,
 | 
			
		||||
 | 
			
		||||
        'xrpl/*:tests': False,
 | 
			
		||||
        'xrpl/*:rocksdb': False,
 | 
			
		||||
        'cassandra-cpp-driver/*:shared': False,
 | 
			
		||||
@@ -68,10 +45,8 @@ class ClioConan(ConanFile):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def requirements(self):
 | 
			
		||||
        if self.options.tests or self.options.integration_tests:
 | 
			
		||||
            self.requires('gtest/1.14.0')
 | 
			
		||||
        if self.options.benchmark:
 | 
			
		||||
            self.requires('benchmark/1.8.3')
 | 
			
		||||
        self.requires('gtest/1.14.0')
 | 
			
		||||
        self.requires('benchmark/1.9.4')
 | 
			
		||||
 | 
			
		||||
    def configure(self):
 | 
			
		||||
        if self.settings.compiler == 'apple-clang':
 | 
			
		||||
@@ -87,8 +62,6 @@ class ClioConan(ConanFile):
 | 
			
		||||
 | 
			
		||||
    def generate(self):
 | 
			
		||||
        tc = CMakeToolchain(self)
 | 
			
		||||
        for option_name, option_value in self.options.items():
 | 
			
		||||
            tc.variables[option_name] = option_value
 | 
			
		||||
        tc.generate()
 | 
			
		||||
 | 
			
		||||
    def build(self):
 | 
			
		||||
 
 | 
			
		||||
@@ -20,43 +20,57 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
 | 
			
		||||
USER root
 | 
			
		||||
WORKDIR /root
 | 
			
		||||
 | 
			
		||||
ARG LLVM_TOOLS_VERSION=20
 | 
			
		||||
 | 
			
		||||
# Add repositories
 | 
			
		||||
# Install common tools and dependencies
 | 
			
		||||
RUN apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        curl \
 | 
			
		||||
        dpkg-dev \
 | 
			
		||||
        file \
 | 
			
		||||
        git \
 | 
			
		||||
        git-lfs \
 | 
			
		||||
        gnupg \
 | 
			
		||||
        graphviz \
 | 
			
		||||
        jq \
 | 
			
		||||
        # libgmp, libmpfr and libncurses are gdb dependencies
 | 
			
		||||
        libgmp-dev \
 | 
			
		||||
        libmpfr-dev \
 | 
			
		||||
        libncurses-dev \
 | 
			
		||||
        make \
 | 
			
		||||
        ninja-build \
 | 
			
		||||
        wget \
 | 
			
		||||
        zip \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/* \
 | 
			
		||||
    && echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${LLVM_TOOLS_VERSION} main" >> /etc/apt/sources.list \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
# Install Python tools
 | 
			
		||||
RUN apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        python3 \
 | 
			
		||||
        python3-pip \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
RUN pip install -q --no-cache-dir \
 | 
			
		||||
        # TODO: Remove this once we switch to newer Ubuntu base image
 | 
			
		||||
        # lxml 6.0.0 is not compatible with our image
 | 
			
		||||
        'lxml<6.0.0' \
 | 
			
		||||
        cmake \
 | 
			
		||||
        conan==2.22.1 \
 | 
			
		||||
        gcovr \
 | 
			
		||||
        # We're adding pre-commit to this image as well,
 | 
			
		||||
        # because clang-tidy workflow requires it
 | 
			
		||||
        pre-commit
 | 
			
		||||
 | 
			
		||||
# Install LLVM tools
 | 
			
		||||
ARG LLVM_TOOLS_VERSION=20
 | 
			
		||||
 | 
			
		||||
RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${LLVM_TOOLS_VERSION} main" >> /etc/apt/sources.list \
 | 
			
		||||
    && wget --progress=dot:giga -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
 | 
			
		||||
 | 
			
		||||
# Install packages
 | 
			
		||||
RUN apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        clang-tidy-${LLVM_TOOLS_VERSION} \
 | 
			
		||||
        clang-tools-${LLVM_TOOLS_VERSION} \
 | 
			
		||||
        git \
 | 
			
		||||
        git-lfs \
 | 
			
		||||
        graphviz \
 | 
			
		||||
        jq \
 | 
			
		||||
        make \
 | 
			
		||||
        ninja-build \
 | 
			
		||||
        python3 \
 | 
			
		||||
        python3-pip \
 | 
			
		||||
        zip \
 | 
			
		||||
    && pip3 install -q --upgrade --no-cache-dir pip \
 | 
			
		||||
    && pip3 install -q --no-cache-dir \
 | 
			
		||||
        # TODO: Remove this once we switch to newer Ubuntu base image
 | 
			
		||||
        # lxml 6.0.0 is not compatible with our image
 | 
			
		||||
        'lxml<6.0.0' \
 | 
			
		||||
        \
 | 
			
		||||
        cmake==3.31.6 \
 | 
			
		||||
        conan==2.17.0 \
 | 
			
		||||
        gcovr \
 | 
			
		||||
        pre-commit \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
@@ -92,12 +106,13 @@ COPY --from=clio-tools \
 | 
			
		||||
    /usr/local/bin/ClangBuildAnalyzer \
 | 
			
		||||
    /usr/local/bin/git-cliff \
 | 
			
		||||
    /usr/local/bin/gh \
 | 
			
		||||
    /usr/local/bin/gdb \
 | 
			
		||||
    /usr/local/bin/
 | 
			
		||||
 | 
			
		||||
WORKDIR /root
 | 
			
		||||
 | 
			
		||||
# Setup conan
 | 
			
		||||
RUN conan remote add --index 0 ripple http://18.143.149.228:8081/artifactory/api/conan/dev
 | 
			
		||||
RUN conan remote add --index 0 xrplf https://conan.ripplex.io
 | 
			
		||||
 | 
			
		||||
WORKDIR /root/.conan2
 | 
			
		||||
COPY conan/global.conf ./global.conf
 | 
			
		||||
 
 | 
			
		||||
@@ -5,15 +5,17 @@ It is used in [Clio Github Actions](https://github.com/XRPLF/clio/actions) but c
 | 
			
		||||
 | 
			
		||||
The image is based on Ubuntu 20.04 and contains:
 | 
			
		||||
 | 
			
		||||
- ccache 4.11.3
 | 
			
		||||
- ccache 4.12.1
 | 
			
		||||
- Clang 19
 | 
			
		||||
- ClangBuildAnalyzer 1.6.0
 | 
			
		||||
- Conan 2.17.0
 | 
			
		||||
- Doxygen 1.12
 | 
			
		||||
- GCC 14.3.0
 | 
			
		||||
- gh 2.74
 | 
			
		||||
- git-cliff 2.9.1
 | 
			
		||||
- mold 2.40.1
 | 
			
		||||
- Conan 2.22.1
 | 
			
		||||
- Doxygen 1.15.0
 | 
			
		||||
- GCC 15.2.0
 | 
			
		||||
- GDB 16.3
 | 
			
		||||
- gh 2.82.1
 | 
			
		||||
- git-cliff 2.10.1
 | 
			
		||||
- mold 2.40.4
 | 
			
		||||
- Python 3.8
 | 
			
		||||
- and some other useful tools
 | 
			
		||||
 | 
			
		||||
Conan is set up to build Clio without any additional steps.
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@ build_type=Release
 | 
			
		||||
compiler=gcc
 | 
			
		||||
compiler.cppstd=20
 | 
			
		||||
compiler.libcxx=libstdc++11
 | 
			
		||||
compiler.version=14
 | 
			
		||||
compiler.version=15
 | 
			
		||||
os=Linux
 | 
			
		||||
 | 
			
		||||
[conf]
 | 
			
		||||
tools.build:compiler_executables={"c": "/usr/bin/gcc-14", "cpp": "/usr/bin/g++-14"}
 | 
			
		||||
tools.build:compiler_executables={"c": "/usr/bin/gcc-15", "cpp": "/usr/bin/g++-15"}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,20 @@
 | 
			
		||||
FROM ubuntu:22.04
 | 
			
		||||
 | 
			
		||||
RUN apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        libatomic1 \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
RUN groupadd -g 10001 clio \
 | 
			
		||||
    && useradd -u 10000 -g 10001 -s /bin/bash clio
 | 
			
		||||
 | 
			
		||||
COPY ./clio_server /opt/clio/bin/clio_server
 | 
			
		||||
 | 
			
		||||
RUN ln -s /opt/clio/bin/clio_server /usr/local/bin/clio_server \
 | 
			
		||||
    && mkdir -p /opt/clio/etc/ \
 | 
			
		||||
    && mkdir -p /opt/clio/log/ \
 | 
			
		||||
    && groupadd -g 10001 clio \
 | 
			
		||||
    && useradd -u 10000 -g 10001 -s /bin/bash clio \
 | 
			
		||||
    && chown clio:clio /opt/clio/log \
 | 
			
		||||
    && apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        libatomic1 \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
    && chown clio:clio /opt/clio/log
 | 
			
		||||
 | 
			
		||||
USER clio
 | 
			
		||||
ENTRYPOINT ["/opt/clio/bin/clio_server"]
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,8 @@ Clio repository provides an [example](https://github.com/XRPLF/clio/blob/develop
 | 
			
		||||
 | 
			
		||||
Config file recommendations:
 | 
			
		||||
 | 
			
		||||
- Set `log_to_console` to `false` if you want to avoid logs being written to `stdout`.
 | 
			
		||||
- Set `log_directory` to `/opt/clio/log` to store logs in a volume.
 | 
			
		||||
- Set `log.enable_console` to `false` if you want to avoid logs being written to `stdout`.
 | 
			
		||||
- Set `log.directory` to `/opt/clio/log` to store logs in a volume.
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ RUN apt-get update \
 | 
			
		||||
 | 
			
		||||
ARG CLANG_MAJOR_VERSION=invalid
 | 
			
		||||
# Bump this version to force rebuild of the image
 | 
			
		||||
ARG BUILD_VERSION=0
 | 
			
		||||
ARG BUILD_VERSION=1
 | 
			
		||||
 | 
			
		||||
RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
 | 
			
		||||
    && chmod +x llvm.sh \
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ ARG UBUNTU_VERSION
 | 
			
		||||
 | 
			
		||||
ARG GCC_MAJOR_VERSION
 | 
			
		||||
 | 
			
		||||
ARG BUILD_VERSION=0
 | 
			
		||||
ARG BUILD_VERSION=1
 | 
			
		||||
 | 
			
		||||
ARG DEBIAN_FRONTEND=noninteractive
 | 
			
		||||
ARG TARGETARCH
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
Package: gcc-14-ubuntu-UBUNTUVERSION
 | 
			
		||||
Package: gcc-15-ubuntu-UBUNTUVERSION
 | 
			
		||||
Version: VERSION
 | 
			
		||||
Architecture: TARGETARCH
 | 
			
		||||
Maintainer: Alex Kremer <akremer@ripple.com>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
services:
 | 
			
		||||
  clio_develop:
 | 
			
		||||
    image: ghcr.io/xrplf/clio-ci:latest
 | 
			
		||||
    image: ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a
 | 
			
		||||
    volumes:
 | 
			
		||||
      - clio_develop_conan_data:/root/.conan2/p
 | 
			
		||||
      - clio_develop_ccache:/root/.ccache
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								docker/pre-commit/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								docker/pre-commit/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
ARG GHCR_REPO=invalid
 | 
			
		||||
FROM ${GHCR_REPO}/clio-tools:latest AS clio-tools
 | 
			
		||||
 | 
			
		||||
# We're using Ubuntu 24.04 to have a more recent version of Python
 | 
			
		||||
FROM ubuntu:24.04
 | 
			
		||||
 | 
			
		||||
ARG DEBIAN_FRONTEND=noninteractive
 | 
			
		||||
 | 
			
		||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
 | 
			
		||||
 | 
			
		||||
# hadolint ignore=DL3002
 | 
			
		||||
USER root
 | 
			
		||||
WORKDIR /root
 | 
			
		||||
 | 
			
		||||
# Install common tools and dependencies
 | 
			
		||||
RUN apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        curl \
 | 
			
		||||
        git \
 | 
			
		||||
        libatomic1 \
 | 
			
		||||
        software-properties-common \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
# Install Python tools
 | 
			
		||||
RUN apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        python3 \
 | 
			
		||||
        python3-pip \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
RUN pip install -q --no-cache-dir --break-system-packages \
 | 
			
		||||
        pre-commit
 | 
			
		||||
 | 
			
		||||
COPY --from=clio-tools \
 | 
			
		||||
    /usr/local/bin/doxygen \
 | 
			
		||||
    /usr/local/bin/
 | 
			
		||||
@@ -8,25 +8,23 @@ ARG TARGETARCH
 | 
			
		||||
 | 
			
		||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
 | 
			
		||||
 | 
			
		||||
ARG BUILD_VERSION=1
 | 
			
		||||
ARG BUILD_VERSION=0
 | 
			
		||||
 | 
			
		||||
RUN apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        bison \
 | 
			
		||||
        flex \
 | 
			
		||||
        ninja-build \
 | 
			
		||||
        python3 \
 | 
			
		||||
        python3-pip \
 | 
			
		||||
        software-properties-common \
 | 
			
		||||
        wget \
 | 
			
		||||
    && pip3 install -q --no-cache-dir \
 | 
			
		||||
        cmake==3.31.6 \
 | 
			
		||||
        cmake \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
WORKDIR /tmp
 | 
			
		||||
 | 
			
		||||
ARG MOLD_VERSION=2.40.1
 | 
			
		||||
ARG MOLD_VERSION=2.40.4
 | 
			
		||||
RUN wget --progress=dot:giga "https://github.com/rui314/mold/archive/refs/tags/v${MOLD_VERSION}.tar.gz" \
 | 
			
		||||
    && tar xf "v${MOLD_VERSION}.tar.gz" \
 | 
			
		||||
    && cd "mold-${MOLD_VERSION}" \
 | 
			
		||||
@@ -36,7 +34,7 @@ RUN wget --progress=dot:giga "https://github.com/rui314/mold/archive/refs/tags/v
 | 
			
		||||
    && ninja install \
 | 
			
		||||
    && rm -rf /tmp/* /var/tmp/*
 | 
			
		||||
 | 
			
		||||
ARG CCACHE_VERSION=4.11.3
 | 
			
		||||
ARG CCACHE_VERSION=4.12.1
 | 
			
		||||
RUN wget --progress=dot:giga "https://github.com/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.gz" \
 | 
			
		||||
    && tar xf "ccache-${CCACHE_VERSION}.tar.gz" \
 | 
			
		||||
    && cd "ccache-${CCACHE_VERSION}" \
 | 
			
		||||
@@ -46,7 +44,14 @@ RUN wget --progress=dot:giga "https://github.com/ccache/ccache/releases/download
 | 
			
		||||
    && ninja install \
 | 
			
		||||
    && rm -rf /tmp/* /var/tmp/*
 | 
			
		||||
 | 
			
		||||
ARG DOXYGEN_VERSION=1.12.0
 | 
			
		||||
RUN apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        bison \
 | 
			
		||||
        flex \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
ARG DOXYGEN_VERSION=1.15.0
 | 
			
		||||
RUN wget --progress=dot:giga "https://github.com/doxygen/doxygen/releases/download/Release_${DOXYGEN_VERSION//./_}/doxygen-${DOXYGEN_VERSION}.src.tar.gz" \
 | 
			
		||||
    && tar xf "doxygen-${DOXYGEN_VERSION}.src.tar.gz" \
 | 
			
		||||
    && cd "doxygen-${DOXYGEN_VERSION}" \
 | 
			
		||||
@@ -66,16 +71,34 @@ RUN wget --progress=dot:giga "https://github.com/aras-p/ClangBuildAnalyzer/archi
 | 
			
		||||
    && ninja install \
 | 
			
		||||
    && rm -rf /tmp/* /var/tmp/*
 | 
			
		||||
 | 
			
		||||
ARG GIT_CLIFF_VERSION=2.9.1
 | 
			
		||||
ARG GIT_CLIFF_VERSION=2.10.1
 | 
			
		||||
RUN wget --progress=dot:giga "https://github.com/orhun/git-cliff/releases/download/v${GIT_CLIFF_VERSION}/git-cliff-${GIT_CLIFF_VERSION}-x86_64-unknown-linux-musl.tar.gz" \
 | 
			
		||||
    && tar xf git-cliff-${GIT_CLIFF_VERSION}-x86_64-unknown-linux-musl.tar.gz \
 | 
			
		||||
    && mv git-cliff-${GIT_CLIFF_VERSION}/git-cliff /usr/local/bin/git-cliff \
 | 
			
		||||
    && rm -rf /tmp/* /var/tmp/*
 | 
			
		||||
 | 
			
		||||
ARG GH_VERSION=2.74.0
 | 
			
		||||
ARG GH_VERSION=2.82.1
 | 
			
		||||
RUN wget --progress=dot:giga "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz" \
 | 
			
		||||
    && tar xf gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz \
 | 
			
		||||
    && mv gh_${GH_VERSION}_linux_${TARGETARCH}/bin/gh /usr/local/bin/gh \
 | 
			
		||||
    && rm -rf /tmp/* /var/tmp/*
 | 
			
		||||
 | 
			
		||||
RUN apt-get update \
 | 
			
		||||
    && apt-get install -y --no-install-recommends --no-install-suggests \
 | 
			
		||||
        libgmp-dev \
 | 
			
		||||
        libmpfr-dev \
 | 
			
		||||
        libncurses-dev \
 | 
			
		||||
        make \
 | 
			
		||||
    && apt-get clean \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
ARG GDB_VERSION=16.3
 | 
			
		||||
RUN wget --progress=dot:giga "https://sourceware.org/pub/gdb/releases/gdb-${GDB_VERSION}.tar.gz" \
 | 
			
		||||
    && tar xf "gdb-${GDB_VERSION}.tar.gz" \
 | 
			
		||||
    && cd "gdb-${GDB_VERSION}" \
 | 
			
		||||
    && ./configure --prefix=/usr/local \
 | 
			
		||||
    && make -j "$(nproc)" \
 | 
			
		||||
    && make install-gdb \
 | 
			
		||||
    && rm -rf /tmp/* /var/tmp/*
 | 
			
		||||
 | 
			
		||||
WORKDIR /root
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@ PROJECT_LOGO           = ${SOURCE}/docs/img/xrpl-logo.svg
 | 
			
		||||
PROJECT_NUMBER         = ${DOC_CLIO_VERSION}
 | 
			
		||||
PROJECT_BRIEF          = The XRP Ledger API server.
 | 
			
		||||
 | 
			
		||||
DOT_GRAPH_MAX_NODES    = 100
 | 
			
		||||
 | 
			
		||||
EXTRACT_ALL            = NO
 | 
			
		||||
EXTRACT_PRIVATE        = NO
 | 
			
		||||
EXTRACT_PACKAGE        = YES
 | 
			
		||||
@@ -13,6 +15,7 @@ EXTRACT_ANON_NSPACES   = NO
 | 
			
		||||
SORT_MEMBERS_CTORS_1ST = YES
 | 
			
		||||
 | 
			
		||||
INPUT                  = ${SOURCE}/src
 | 
			
		||||
USE_MDFILE_AS_MAINPAGE = ${SOURCE}/src/README.md
 | 
			
		||||
EXCLUDE_SYMBOLS        = ${EXCLUDES}
 | 
			
		||||
RECURSIVE              = YES
 | 
			
		||||
HAVE_DOT               = ${USE_DOT}
 | 
			
		||||
@@ -32,12 +35,18 @@ SORT_MEMBERS_CTORS_1ST = YES
 | 
			
		||||
GENERATE_TREEVIEW      = YES
 | 
			
		||||
DISABLE_INDEX          = NO
 | 
			
		||||
FULL_SIDEBAR           = NO
 | 
			
		||||
HTML_HEADER            = ${SOURCE}/docs/doxygen-awesome-theme/header.html
 | 
			
		||||
HTML_HEADER            = ${SOURCE}/docs/doxygen-awesome-theme/doxygen-custom/header.html
 | 
			
		||||
HTML_EXTRA_STYLESHEET  = ${SOURCE}/docs/doxygen-awesome-theme/doxygen-awesome.css \
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-awesome-sidebar-only.css \
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-awesome-sidebar-only-darkmode-toggle.css
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-awesome-sidebar-only-darkmode-toggle.css \
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-custom/custom.css \
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-custom/theme-robot.css \
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-custom/theme-round.css \
 | 
			
		||||
                         ${SOURCE}/docs/github-corner-disable.css
 | 
			
		||||
HTML_EXTRA_FILES       = ${SOURCE}/docs/doxygen-awesome-theme/doxygen-awesome-darkmode-toggle.js \
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-awesome-interactive-toc.js
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-awesome-fragment-copy-button.js \
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-awesome-interactive-toc.js \
 | 
			
		||||
                         ${SOURCE}/docs/doxygen-awesome-theme/doxygen-custom/toggle-alternative-theme.js
 | 
			
		||||
 | 
			
		||||
HTML_COLORSTYLE        = LIGHT
 | 
			
		||||
HTML_COLORSTYLE_HUE    = 209
 | 
			
		||||
 
 | 
			
		||||
@@ -6,16 +6,22 @@
 | 
			
		||||
## Minimum Requirements
 | 
			
		||||
 | 
			
		||||
- [Python 3.7](https://www.python.org/downloads/)
 | 
			
		||||
- [Conan 2.17.0](https://conan.io/downloads.html)
 | 
			
		||||
- [CMake 3.20, <4.0](https://cmake.org/download/)
 | 
			
		||||
- [Conan 2.20.1](https://conan.io/downloads.html)
 | 
			
		||||
- [CMake 3.20](https://cmake.org/download/)
 | 
			
		||||
- [**Optional**] [GCovr](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html): needed for code coverage generation
 | 
			
		||||
- [**Optional**] [CCache](https://ccache.dev/): speeds up compilation if you are going to compile Clio often
 | 
			
		||||
 | 
			
		||||
We use our Docker image `ghcr.io/XRPLF/clio-ci` to build `Clio`, see [Building Clio with Docker](#building-clio-with-docker).
 | 
			
		||||
You can find information about exact compiler versions and tools in the [image's README](https://github.com/XRPLF/clio/blob/develop/docker/ci/README.md).
 | 
			
		||||
 | 
			
		||||
The following compiler version are guaranteed to work.
 | 
			
		||||
Any compiler with lower version may not be able to build Clio:
 | 
			
		||||
 | 
			
		||||
| Compiler    | Version |
 | 
			
		||||
| ----------- | ------- |
 | 
			
		||||
| GCC         | 12.3    |
 | 
			
		||||
| Clang       | 16      |
 | 
			
		||||
| Apple Clang | 15      |
 | 
			
		||||
| GCC         | 15.2    |
 | 
			
		||||
| Clang       | 19      |
 | 
			
		||||
| Apple Clang | 17      |
 | 
			
		||||
 | 
			
		||||
### Conan Configuration
 | 
			
		||||
 | 
			
		||||
@@ -84,7 +90,7 @@ core.upload:parallel={{os.cpu_count()}}
 | 
			
		||||
Make sure artifactory is setup with Conan.
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
conan remote add --index 0 ripple http://18.143.149.228:8081/artifactory/api/conan/dev
 | 
			
		||||
conan remote add --index 0 xrplf https://conan.ripplex.io
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Now you should be able to download the prebuilt dependencies (including `xrpl` package) on supported platforms.
 | 
			
		||||
@@ -98,79 +104,100 @@ It is implicitly used when running `conan` commands, you don't need to specify i
 | 
			
		||||
 | 
			
		||||
You have to update this file every time you add a new dependency or change a revision or version of an existing dependency.
 | 
			
		||||
 | 
			
		||||
To do that, run the following command in the repository root:
 | 
			
		||||
> [!NOTE]
 | 
			
		||||
> Conan uses local cache by default when creating a lockfile.
 | 
			
		||||
>
 | 
			
		||||
> To ensure, that lockfile creation works the same way on all developer machines, you should clear the local cache before creating a new lockfile.
 | 
			
		||||
 | 
			
		||||
To create a new lockfile, run the following commands in the repository root:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
conan lock create . -o '&:tests=True' -o '&:benchmark=True'
 | 
			
		||||
conan remove '*' --confirm
 | 
			
		||||
rm conan.lock
 | 
			
		||||
# This ensure that xrplf remote is the first to be consulted
 | 
			
		||||
conan remote add --force --index 0 xrplf https://conan.ripplex.io
 | 
			
		||||
conan lock create .
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
> [!NOTE]
 | 
			
		||||
> If some dependencies are exclusive for some OS, you may need to run the last command for them adding `--profile:all <PROFILE>`.
 | 
			
		||||
 | 
			
		||||
## Building Clio
 | 
			
		||||
 | 
			
		||||
Navigate to Clio's root directory and run:
 | 
			
		||||
1. Navigate to Clio's root directory and run:
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
mkdir build && cd build
 | 
			
		||||
# You can also specify profile explicitly by adding `--profile:all <PROFILE_NAME>`
 | 
			
		||||
conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True'
 | 
			
		||||
# You can also add -GNinja to use Ninja build system instead of Make
 | 
			
		||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
 | 
			
		||||
cmake --build . --parallel 8 # or without the number if you feel extra adventurous
 | 
			
		||||
```
 | 
			
		||||
   ```sh
 | 
			
		||||
   mkdir build && cd build
 | 
			
		||||
   ```
 | 
			
		||||
 | 
			
		||||
> [!TIP]
 | 
			
		||||
> You can omit the `-o '&:tests=True'` if you don't want to build `clio_tests`.
 | 
			
		||||
2. Install dependencies through conan.
 | 
			
		||||
 | 
			
		||||
If successful, `conan install` will find the required packages and `cmake` will do the rest. You should see `clio_server` and `clio_tests` in the `build` directory (the current directory).
 | 
			
		||||
   ```sh
 | 
			
		||||
   conan install .. --output-folder . --build missing --settings build_type=Release
 | 
			
		||||
   ```
 | 
			
		||||
 | 
			
		||||
> [!TIP]
 | 
			
		||||
> To generate a Code Coverage report, include `-o '&:coverage=True'` in the `conan install` command above, along with `-o '&:tests=True'` to enable tests.
 | 
			
		||||
> After running the `cmake` commands, execute `make clio_tests-ccov`.
 | 
			
		||||
> The coverage report will be found at `clio_tests-llvm-cov/index.html`.
 | 
			
		||||
   > You can add `--profile:all <PROFILE_NAME>` to choose a specific conan profile.
 | 
			
		||||
 | 
			
		||||
<!-- markdownlint-disable-line MD028 -->
 | 
			
		||||
3. Configure and generate build files with CMake.
 | 
			
		||||
 | 
			
		||||
   ```sh
 | 
			
		||||
   cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
 | 
			
		||||
   ```
 | 
			
		||||
 | 
			
		||||
   > You can add `-GNinja` to use the Ninja build system (instead of Make).
 | 
			
		||||
 | 
			
		||||
4. Now, you can build all targets or specific ones:
 | 
			
		||||
 | 
			
		||||
   ```sh
 | 
			
		||||
   # builds all targets
 | 
			
		||||
   cmake --build . --parallel 8
 | 
			
		||||
   # builds only clio_server target
 | 
			
		||||
   cmake --build . --parallel 8 --target clio_server
 | 
			
		||||
   ```
 | 
			
		||||
 | 
			
		||||
   You should see `clio_server` and `clio_tests` in the current directory.
 | 
			
		||||
 | 
			
		||||
> [!NOTE]
 | 
			
		||||
> If you've built Clio before and the build is now failing, it's likely due to updated dependencies. Try deleting the build folder and then rerunning the Conan and CMake commands mentioned above.
 | 
			
		||||
 | 
			
		||||
### CMake options
 | 
			
		||||
 | 
			
		||||
There are several CMake options you can use to customize the build:
 | 
			
		||||
 | 
			
		||||
| CMake Option          | Default | CMake Target                                             | Description                           |
 | 
			
		||||
| --------------------- | ------- | -------------------------------------------------------- | ------------------------------------- |
 | 
			
		||||
| `-Dcoverage`          | OFF     | `clio_tests-ccov`                                        | Enables code coverage generation      |
 | 
			
		||||
| `-Dtests`             | OFF     | `clio_tests`                                             | Enables unit tests                    |
 | 
			
		||||
| `-Dintegration_tests` | OFF     | `clio_integration_tests`                                 | Enables integration tests             |
 | 
			
		||||
| `-Dbenchmark`         | OFF     | `clio_benchmark`                                         | Enables benchmark executable          |
 | 
			
		||||
| `-Ddocs`              | OFF     | `docs`                                                   | Enables API documentation generation  |
 | 
			
		||||
| `-Dlint`              | OFF     | See [#clang-tidy](#using-clang-tidy-for-static-analysis) | Enables `clang-tidy` static analysis  |
 | 
			
		||||
| `-Dsan`               | N/A     | N/A                                                      | Enables Sanitizer (asan, tsan, ubsan) |
 | 
			
		||||
| `-Dpackage`           | OFF     | N/A                                                      | Creates a debian package              |
 | 
			
		||||
 | 
			
		||||
### Generating API docs for Clio
 | 
			
		||||
 | 
			
		||||
The API documentation for Clio is generated by [Doxygen](https://www.doxygen.nl/index.html). If you want to generate the API documentation when building Clio, make sure to install Doxygen 1.12.0 on your system.
 | 
			
		||||
The API documentation for Clio is generated by [Doxygen](https://www.doxygen.nl/index.html). If you want to generate the API documentation when building Clio, make sure to install Doxygen 1.14.0 on your system.
 | 
			
		||||
 | 
			
		||||
To generate the API docs:
 | 
			
		||||
To generate the API docs, please use CMake option `-Ddocs=ON` as described above and build the `docs` target.
 | 
			
		||||
 | 
			
		||||
1. First, include `-o '&:docs=True'` in the conan install command. For example:
 | 
			
		||||
To view the generated files, go to `build/docs/html`.
 | 
			
		||||
Open the `index.html` file in your browser to see the documentation pages.
 | 
			
		||||
 | 
			
		||||
   ```sh
 | 
			
		||||
   mkdir build && cd build
 | 
			
		||||
   conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True' -o '&:docs=True'
 | 
			
		||||
   ```
 | 
			
		||||
 | 
			
		||||
2. Once that has completed successfully, run the `cmake` command and add the `--target docs` option:
 | 
			
		||||
 | 
			
		||||
   ```sh
 | 
			
		||||
   cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
 | 
			
		||||
   cmake --build . --parallel 8 --target docs
 | 
			
		||||
   ```
 | 
			
		||||
 | 
			
		||||
3. Go to `build/docs/html` to view the generated files.
 | 
			
		||||
 | 
			
		||||
   Open the `index.html` file in your browser to see the documentation pages.
 | 
			
		||||
 | 
			
		||||
   
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
## Building Clio with Docker
 | 
			
		||||
 | 
			
		||||
It is also possible to build Clio using [Docker](https://www.docker.com/) if you don't want to install all the dependencies on your machine.
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
docker run -it ghcr.io/xrplf/clio-ci:latest
 | 
			
		||||
docker run -it ghcr.io/xrplf/clio-ci:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a
 | 
			
		||||
git clone https://github.com/XRPLF/clio
 | 
			
		||||
mkdir build && cd build
 | 
			
		||||
conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True'
 | 
			
		||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
 | 
			
		||||
cmake --build . --parallel 8 # or without the number if you feel extra adventurous
 | 
			
		||||
cd clio
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Follow the same steps in the [Building Clio](#building-clio) section. You can use `--profile:all gcc` or `--profile:all clang` with the `conan install` command to choose the desired compiler.
 | 
			
		||||
 | 
			
		||||
## Developing against `rippled` in standalone mode
 | 
			
		||||
 | 
			
		||||
If you wish to develop against a `rippled` instance running in standalone mode there are a few quirks of both Clio and `rippled` that you need to keep in mind. You must:
 | 
			
		||||
@@ -223,10 +250,10 @@ Sometimes, during development, you need to build against a custom version of `li
 | 
			
		||||
## Using `clang-tidy` for static analysis
 | 
			
		||||
 | 
			
		||||
Clang-tidy can be run by CMake when building the project.
 | 
			
		||||
To achieve this, you just need to provide the option `-o '&:lint=True'` for the `conan install` command:
 | 
			
		||||
To achieve this, you just need to provide the option `-Dlint=ON` when generating CMake files:
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True' -o '&:lint=True' --profile:all clang
 | 
			
		||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release -Dlint=ON ..
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
By default CMake will try to find `clang-tidy` automatically in your system.
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,9 @@
 | 
			
		||||
This document provides a list of all available Clio configuration properties in detail.
 | 
			
		||||
 | 
			
		||||
> [!NOTE]
 | 
			
		||||
> Dot notation in configuration key names represents nested fields. For example, **database.scylladb** refers to the _scylladb_ field inside the _database_ object. If a key name includes "[]", it indicates that the nested field is an array (e.g., etl_sources.[]).
 | 
			
		||||
> Dot notation in configuration key names represents nested fields.
 | 
			
		||||
> For example, **database.scylladb** refers to the _scylladb_ field inside the _database_ object.
 | 
			
		||||
> If a key name includes "[]", it indicates that the nested field is an array (e.g., etl_sources.[]).
 | 
			
		||||
 | 
			
		||||
## Configuration Details
 | 
			
		||||
 | 
			
		||||
@@ -87,6 +89,14 @@ This document provides a list of all available Clio configuration properties in
 | 
			
		||||
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
 | 
			
		||||
- **Description**: Represents the number of threads that will be used for database operations.
 | 
			
		||||
 | 
			
		||||
### database.cassandra.provider
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: string
 | 
			
		||||
- **Default value**: `cassandra`
 | 
			
		||||
- **Constraints**: The value must be one of the following: `cassandra`, `aws_keyspace`.
 | 
			
		||||
- **Description**: The specific database backend provider we are using.
 | 
			
		||||
 | 
			
		||||
### database.cassandra.core_connections_per_host
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
@@ -155,7 +165,7 @@ This document provides a list of all available Clio configuration properties in
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: boolean
 | 
			
		||||
- **Default value**: `True`
 | 
			
		||||
- **Default value**: `False`
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: If set to `True`, allows Clio to start without any ETL source.
 | 
			
		||||
 | 
			
		||||
@@ -327,11 +337,27 @@ This document provides a list of all available Clio configuration properties in
 | 
			
		||||
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
 | 
			
		||||
- **Description**: Maximum queue size for sending subscription data to clients. This queue buffers data when a client is slow to receive it, ensuring delivery once the client is ready.
 | 
			
		||||
 | 
			
		||||
### server.proxy.ips.[]
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: string
 | 
			
		||||
- **Default value**: None
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: List of proxy ip addresses. When Clio receives a request from proxy it will use `Forwarded` value (if any) as client ip. When this option is used together with `server.proxy.tokens` Clio will identify proxy by ip or by token.
 | 
			
		||||
 | 
			
		||||
### server.proxy.tokens.[]
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: string
 | 
			
		||||
- **Default value**: None
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: List of tokens in identifying request as a request from proxy. Token should be provided in `X-Proxy-Token` header, e.g. `X-Proxy-Token: <very_secret_token>'. When Clio receives a request from proxy it will use 'Forwarded` value (if any) to get client ip. When this option is used together with 'server.proxy.ips' Clio will identify proxy by ip or by token.
 | 
			
		||||
 | 
			
		||||
### prometheus.enabled
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: boolean
 | 
			
		||||
- **Default value**: `False`
 | 
			
		||||
- **Default value**: `True`
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: Enables or disables Prometheus metrics.
 | 
			
		||||
 | 
			
		||||
@@ -339,7 +365,7 @@ This document provides a list of all available Clio configuration properties in
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: boolean
 | 
			
		||||
- **Default value**: `False`
 | 
			
		||||
- **Default value**: `True`
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: Enables or disables compression of Prometheus responses.
 | 
			
		||||
 | 
			
		||||
@@ -415,7 +441,7 @@ This document provides a list of all available Clio configuration properties in
 | 
			
		||||
- **Constraints**: The value must be one of the following: `sync`, `async`, `none`.
 | 
			
		||||
- **Description**: The strategy used for Cache loading.
 | 
			
		||||
 | 
			
		||||
### log_channels.[].channel
 | 
			
		||||
### log.channels.[].channel
 | 
			
		||||
 | 
			
		||||
- **Required**: False
 | 
			
		||||
- **Type**: string
 | 
			
		||||
@@ -423,39 +449,63 @@ This document provides a list of all available Clio configuration properties in
 | 
			
		||||
- **Constraints**: The value must be one of the following: `General`, `WebServer`, `Backend`, `RPC`, `ETL`, `Subscriptions`, `Performance`, `Migration`.
 | 
			
		||||
- **Description**: The name of the log channel.
 | 
			
		||||
 | 
			
		||||
### log_channels.[].log_level
 | 
			
		||||
### log.channels.[].level
 | 
			
		||||
 | 
			
		||||
- **Required**: False
 | 
			
		||||
- **Type**: string
 | 
			
		||||
- **Default value**: None
 | 
			
		||||
- **Constraints**: The value must be one of the following: `trace`, `debug`, `info`, `warning`, `error`, `fatal`, `count`.
 | 
			
		||||
- **Constraints**: The value must be one of the following: `trace`, `debug`, `info`, `warning`, `error`, `fatal`.
 | 
			
		||||
- **Description**: The log level for the specific log channel.
 | 
			
		||||
 | 
			
		||||
### log_level
 | 
			
		||||
### log.level
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: string
 | 
			
		||||
- **Default value**: `info`
 | 
			
		||||
- **Constraints**: The value must be one of the following: `trace`, `debug`, `info`, `warning`, `error`, `fatal`, `count`.
 | 
			
		||||
- **Constraints**: The value must be one of the following: `trace`, `debug`, `info`, `warning`, `error`, `fatal`.
 | 
			
		||||
- **Description**: The general logging level of Clio. This level is applied to all log channels that do not have an explicitly defined logging level.
 | 
			
		||||
 | 
			
		||||
### log_format
 | 
			
		||||
### log.format
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: string
 | 
			
		||||
- **Default value**: `%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% %Message%`
 | 
			
		||||
- **Default value**: `%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v`
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: The format string for log messages. The format is described here: <https://www.boost.org/doc/libs/1_83_0/libs/log/doc/html/log/tutorial/formatters.html>.
 | 
			
		||||
- **Description**: The format string for log messages using spdlog format patterns.
 | 
			
		||||
 | 
			
		||||
### log_to_console
 | 
			
		||||
Each of the variables expands like so:
 | 
			
		||||
 | 
			
		||||
- `%Y-%m-%d %H:%M:%S.%f`: The full date and time of the log entry with microsecond precision
 | 
			
		||||
- `%^`: Start color range
 | 
			
		||||
- `%3!l`: The severity (aka log level) the entry was sent at stripped to 3 characters
 | 
			
		||||
- `%n`: The logger name (channel) that this log entry was sent to
 | 
			
		||||
- `%$`: End color range
 | 
			
		||||
- `%v`: The actual log message
 | 
			
		||||
 | 
			
		||||
Some additional variables that might be useful:
 | 
			
		||||
 | 
			
		||||
- `%@`: A partial path to the C++ file and the line number in the said file (`src/file/path:linenumber`)
 | 
			
		||||
- `%t`: The ID of the thread the log entry is written from
 | 
			
		||||
 | 
			
		||||
Documentation can be found at: <https://github.com/gabime/spdlog/wiki/Custom-formatting>.
 | 
			
		||||
 | 
			
		||||
### log.is_async
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: boolean
 | 
			
		||||
- **Default value**: `True`
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: Whether spdlog is asynchronous or not.
 | 
			
		||||
 | 
			
		||||
### log.enable_console
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: boolean
 | 
			
		||||
- **Default value**: `False`
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: Enables or disables logging to the console.
 | 
			
		||||
 | 
			
		||||
### log_directory
 | 
			
		||||
### log.directory
 | 
			
		||||
 | 
			
		||||
- **Required**: False
 | 
			
		||||
- **Type**: string
 | 
			
		||||
@@ -463,7 +513,7 @@ This document provides a list of all available Clio configuration properties in
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: The directory path for the log files.
 | 
			
		||||
 | 
			
		||||
### log_rotation_size
 | 
			
		||||
### log.rotation_size
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: int
 | 
			
		||||
@@ -471,23 +521,15 @@ This document provides a list of all available Clio configuration properties in
 | 
			
		||||
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
 | 
			
		||||
- **Description**: The log rotation size in megabytes. When the log file reaches this particular size, a new log file starts.
 | 
			
		||||
 | 
			
		||||
### log_directory_max_size
 | 
			
		||||
### log.directory_max_files
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: int
 | 
			
		||||
- **Default value**: `51200`
 | 
			
		||||
- **Default value**: `25`
 | 
			
		||||
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
 | 
			
		||||
- **Description**: The maximum size of the log directory in megabytes.
 | 
			
		||||
- **Description**: The maximum number of log files in the directory.
 | 
			
		||||
 | 
			
		||||
### log_rotation_hour_interval
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: int
 | 
			
		||||
- **Default value**: `12`
 | 
			
		||||
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
 | 
			
		||||
- **Description**: Represents the interval (in hours) for log rotation. If the current log file reaches this value in logging, a new log file starts.
 | 
			
		||||
 | 
			
		||||
### log_tag_style
 | 
			
		||||
### log.tag_style
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: string
 | 
			
		||||
@@ -507,7 +549,7 @@ This document provides a list of all available Clio configuration properties in
 | 
			
		||||
 | 
			
		||||
- **Required**: True
 | 
			
		||||
- **Type**: boolean
 | 
			
		||||
- **Default value**: `True`
 | 
			
		||||
- **Default value**: `False`
 | 
			
		||||
- **Constraints**: None
 | 
			
		||||
- **Description**: Indicates if the server is allowed to write data to the database.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -88,13 +88,15 @@ Exactly equal password gains admin rights for the request or a websocket connect
 | 
			
		||||
Clio can cache requests to ETL sources to reduce the load on the ETL source.
 | 
			
		||||
Only following commands are cached: `server_info`, `server_state`, `server_definitions`, `fee`, `ledger_closed`.
 | 
			
		||||
By default the forwarding cache is off.
 | 
			
		||||
To enable the caching for a source, `forwarding_cache_timeout` value should be added to the configuration file, e.g.:
 | 
			
		||||
To enable the caching for a source, `forwarding.cache_timeout` value should be added to the configuration file, e.g.:
 | 
			
		||||
 | 
			
		||||
```json
 | 
			
		||||
"forwarding_cache_timeout": 0.250,
 | 
			
		||||
"forwarding": {
 | 
			
		||||
    "cache_timeout": 0.250,
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`forwarding_cache_timeout` defines for how long (in seconds) a cache entry will be valid after being placed into the cache.
 | 
			
		||||
`forwarding.cache_timeout` defines for how long (in seconds) a cache entry will be valid after being placed into the cache.
 | 
			
		||||
Zero value turns off the cache feature.
 | 
			
		||||
 | 
			
		||||
## Graceful shutdown (not fully implemented yet)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +1,10 @@
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
Doxygen Awesome
 | 
			
		||||
https://github.com/jothepro/doxygen-awesome-css
 | 
			
		||||
 | 
			
		||||
MIT License
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2021 - 2023 jothepro
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
Copyright (c) 2021 - 2025 jothepro
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
Doxygen Awesome
 | 
			
		||||
https://github.com/jothepro/doxygen-awesome-css
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2022 - 2025 jothepro
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
class DoxygenAwesomeFragmentCopyButton extends HTMLElement {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
        this.onclick=this.copyContent
 | 
			
		||||
    }
 | 
			
		||||
    static title = "Copy to clipboard"
 | 
			
		||||
    static copyIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M23.04,10.322c0,-2.582 -2.096,-4.678 -4.678,-4.678l-6.918,-0c-2.582,-0 -4.678,2.096 -4.678,4.678c0,-0 0,8.04 0,8.04c0,2.582 2.096,4.678 4.678,4.678c0,-0 6.918,-0 6.918,-0c2.582,-0 4.678,-2.096 4.678,-4.678c0,-0 0,-8.04 0,-8.04Zm-2.438,-0l-0,8.04c-0,1.236 -1.004,2.24 -2.24,2.24l-6.918,-0c-1.236,-0 -2.239,-1.004 -2.239,-2.24l-0,-8.04c-0,-1.236 1.003,-2.24 2.239,-2.24c0,0 6.918,0 6.918,0c1.236,0 2.24,1.004 2.24,2.24Z"/><path d="M5.327,16.748c-0,0.358 -0.291,0.648 -0.649,0.648c0,0 0,0 0,0c-2.582,0 -4.678,-2.096 -4.678,-4.678c0,0 0,-8.04 0,-8.04c0,-2.582 2.096,-4.678 4.678,-4.678l6.918,0c2.168,0 3.994,1.478 4.523,3.481c0.038,0.149 0.005,0.306 -0.09,0.428c-0.094,0.121 -0.239,0.191 -0.392,0.191c-0.451,0.005 -1.057,0.005 -1.457,0.005c-0.238,0 -0.455,-0.14 -0.553,-0.357c-0.348,-0.773 -1.128,-1.31 -2.031,-1.31c-0,0 -6.918,0 -6.918,0c-1.236,0 -2.24,1.004 -2.24,2.24l0,8.04c0,1.236 1.004,2.24 2.24,2.24l0,-0c0.358,-0 0.649,0.29 0.649,0.648c-0,0.353 -0,0.789 -0,1.142Z" style="fill-opacity:0.6;"/></svg>`
 | 
			
		||||
    static successIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M8.084,16.111c-0.09,0.09 -0.212,0.141 -0.34,0.141c-0.127,-0 -0.249,-0.051 -0.339,-0.141c-0.746,-0.746 -2.538,-2.538 -3.525,-3.525c-0.375,-0.375 -0.983,-0.375 -1.357,0c-0.178,0.178 -0.369,0.369 -0.547,0.547c-0.375,0.375 -0.375,0.982 -0,1.357c1.135,1.135 3.422,3.422 4.75,4.751c0.27,0.27 0.637,0.421 1.018,0.421c0.382,0 0.749,-0.151 1.019,-0.421c2.731,-2.732 10.166,-10.167 12.454,-12.455c0.375,-0.375 0.375,-0.982 -0,-1.357c-0.178,-0.178 -0.369,-0.369 -0.547,-0.547c-0.375,-0.375 -0.982,-0.375 -1.357,0c-2.273,2.273 -9.567,9.567 -11.229,11.229Z"/></svg>`
 | 
			
		||||
    static successDuration = 980
 | 
			
		||||
    static init() {
 | 
			
		||||
        $(function() {
 | 
			
		||||
            $(document).ready(function() {
 | 
			
		||||
                if(navigator.clipboard) {
 | 
			
		||||
                    const fragments = document.getElementsByClassName("fragment")
 | 
			
		||||
                    for(const fragment of fragments) {
 | 
			
		||||
                        const fragmentWrapper = document.createElement("div")
 | 
			
		||||
                        fragmentWrapper.className = "doxygen-awesome-fragment-wrapper"
 | 
			
		||||
                        const fragmentCopyButton = document.createElement("doxygen-awesome-fragment-copy-button")
 | 
			
		||||
                        fragmentCopyButton.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon
 | 
			
		||||
                        fragmentCopyButton.title = DoxygenAwesomeFragmentCopyButton.title
 | 
			
		||||
                
 | 
			
		||||
                        fragment.parentNode.replaceChild(fragmentWrapper, fragment)
 | 
			
		||||
                        fragmentWrapper.appendChild(fragment)
 | 
			
		||||
                        fragmentWrapper.appendChild(fragmentCopyButton)
 | 
			
		||||
            
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    copyContent() {
 | 
			
		||||
        const content = this.previousSibling.cloneNode(true)
 | 
			
		||||
        // filter out line number from file listings
 | 
			
		||||
        content.querySelectorAll(".lineno, .ttc").forEach((node) => {
 | 
			
		||||
            node.remove()
 | 
			
		||||
        })
 | 
			
		||||
        let textContent = content.textContent
 | 
			
		||||
        // remove trailing newlines that appear in file listings
 | 
			
		||||
        let numberOfTrailingNewlines = 0
 | 
			
		||||
        while(textContent.charAt(textContent.length - (numberOfTrailingNewlines + 1)) == '\n') {
 | 
			
		||||
            numberOfTrailingNewlines++;
 | 
			
		||||
        }
 | 
			
		||||
        textContent = textContent.substring(0, textContent.length - numberOfTrailingNewlines)
 | 
			
		||||
        navigator.clipboard.writeText(textContent);
 | 
			
		||||
        this.classList.add("success")
 | 
			
		||||
        this.innerHTML = DoxygenAwesomeFragmentCopyButton.successIcon
 | 
			
		||||
        window.setTimeout(() => {
 | 
			
		||||
            this.classList.remove("success")
 | 
			
		||||
            this.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon
 | 
			
		||||
        }, DoxygenAwesomeFragmentCopyButton.successDuration);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customElements.define("doxygen-awesome-fragment-copy-button", DoxygenAwesomeFragmentCopyButton)
 | 
			
		||||
@@ -1,29 +1,10 @@
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
Doxygen Awesome
 | 
			
		||||
https://github.com/jothepro/doxygen-awesome-css
 | 
			
		||||
 | 
			
		||||
MIT License
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2022 - 2023 jothepro
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
Copyright (c) 2022 - 2025 jothepro
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
@@ -55,9 +36,7 @@ class DoxygenAwesomeInteractiveToc {
 | 
			
		||||
                        headerNode: document.getElementById(id)
 | 
			
		||||
                    })
 | 
			
		||||
 | 
			
		||||
                    document.getElementById("doc-content")?.addEventListener("scroll", () => {
 | 
			
		||||
                        DoxygenAwesomeInteractiveToc.update()
 | 
			
		||||
                    })
 | 
			
		||||
                    document.getElementById("doc-content")?.addEventListener("scroll",this.throttle(DoxygenAwesomeInteractiveToc.update, 100))
 | 
			
		||||
                })
 | 
			
		||||
                DoxygenAwesomeInteractiveToc.update()
 | 
			
		||||
            }
 | 
			
		||||
@@ -78,4 +57,16 @@ class DoxygenAwesomeInteractiveToc {
 | 
			
		||||
        active?.classList.add("active")
 | 
			
		||||
        active?.classList.remove("aboveActive")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    static throttle(func, delay) {
 | 
			
		||||
        let lastCall = 0;
 | 
			
		||||
        return function (...args) {
 | 
			
		||||
            const now = new Date().getTime();
 | 
			
		||||
            if (now - lastCall < delay) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            lastCall = now;
 | 
			
		||||
            return setTimeout(() => {func(...args)}, delay);
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +1,10 @@
 | 
			
		||||
 | 
			
		||||
/* SPDX-License-Identifier: MIT */
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
Doxygen Awesome
 | 
			
		||||
https://github.com/jothepro/doxygen-awesome-css
 | 
			
		||||
 | 
			
		||||
MIT License
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2021 - 2023 jothepro
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
Copyright (c) 2021 - 2025 jothepro
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +1,10 @@
 | 
			
		||||
/* SPDX-License-Identifier: MIT */
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
Doxygen Awesome
 | 
			
		||||
https://github.com/jothepro/doxygen-awesome-css
 | 
			
		||||
 | 
			
		||||
MIT License
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2021 - 2023 jothepro
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
Copyright (c) 2021 - 2025 jothepro
 | 
			
		||||
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -60,10 +41,6 @@ html {
 | 
			
		||||
        height: calc(100vh - var(--top-height)) !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #nav-tree {
 | 
			
		||||
        padding: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #top {
 | 
			
		||||
        display: block;
 | 
			
		||||
        border-bottom: none;
 | 
			
		||||
@@ -73,22 +50,24 @@ html {
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
        background: var(--side-nav-background);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #main-nav {
 | 
			
		||||
        float: left;
 | 
			
		||||
        padding-right: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .ui-resizable-handle {
 | 
			
		||||
        cursor: default;
 | 
			
		||||
        width: 1px !important;
 | 
			
		||||
        background: var(--separator-color);
 | 
			
		||||
        box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color);
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .ui-resizable-e {
 | 
			
		||||
        width: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #nav-path {
 | 
			
		||||
        position: fixed;
 | 
			
		||||
        right: 0;
 | 
			
		||||
        left: var(--side-nav-fixed-width);
 | 
			
		||||
        left: calc(var(--side-nav-fixed-width) + 1px);
 | 
			
		||||
        bottom: 0;
 | 
			
		||||
        width: auto;
 | 
			
		||||
    }
 | 
			
		||||
@@ -113,4 +92,14 @@ html {
 | 
			
		||||
        left: var(--spacing-medium) !important;
 | 
			
		||||
        right: auto;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #nav-sync {
 | 
			
		||||
        bottom: 4px;
 | 
			
		||||
        right: auto;
 | 
			
		||||
        left: 300px;
 | 
			
		||||
        width: 35px;
 | 
			
		||||
        top: auto !important;
 | 
			
		||||
        user-select: none;
 | 
			
		||||
        position: fixed
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +1,10 @@
 | 
			
		||||
/* SPDX-License-Identifier: MIT */
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
Doxygen Awesome
 | 
			
		||||
https://github.com/jothepro/doxygen-awesome-css
 | 
			
		||||
 | 
			
		||||
MIT License
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2021 - 2023 jothepro
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
Copyright (c) 2021 - 2025 jothepro
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
@@ -32,6 +13,9 @@ html {
 | 
			
		||||
    --primary-color: #1779c4;
 | 
			
		||||
    --primary-dark-color: #335c80;
 | 
			
		||||
    --primary-light-color: #70b1e9;
 | 
			
		||||
    --on-primary-color: #ffffff;
 | 
			
		||||
 | 
			
		||||
    --link-color: var(--primary-color);
 | 
			
		||||
 | 
			
		||||
    /* page base colors */
 | 
			
		||||
    --page-background-color: #ffffff;
 | 
			
		||||
@@ -42,14 +26,15 @@ html {
 | 
			
		||||
    --separator-color: #dedede;
 | 
			
		||||
 | 
			
		||||
    /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */
 | 
			
		||||
    --border-radius-large: 8px;
 | 
			
		||||
    --border-radius-small: 4px;
 | 
			
		||||
    --border-radius-medium: 6px;
 | 
			
		||||
    --border-radius-large: 10px;
 | 
			
		||||
    --border-radius-small: 5px;
 | 
			
		||||
    --border-radius-medium: 8px;
 | 
			
		||||
 | 
			
		||||
    /* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */
 | 
			
		||||
    --spacing-small: 5px;
 | 
			
		||||
    --spacing-medium: 10px;
 | 
			
		||||
    --spacing-large: 16px;
 | 
			
		||||
    --spacing-xlarge: 20px;
 | 
			
		||||
 | 
			
		||||
    /* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */
 | 
			
		||||
    --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075);
 | 
			
		||||
@@ -113,7 +98,7 @@ html {
 | 
			
		||||
     */
 | 
			
		||||
    --menu-display: block;
 | 
			
		||||
 | 
			
		||||
    --menu-focus-foreground: var(--page-background-color);
 | 
			
		||||
    --menu-focus-foreground: var(--on-primary-color);
 | 
			
		||||
    --menu-focus-background: var(--primary-color);
 | 
			
		||||
    --menu-selected-background: rgba(0,0,0,.05);
 | 
			
		||||
 | 
			
		||||
@@ -310,10 +295,11 @@ body {
 | 
			
		||||
    font-size: var(--page-font-size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body, table, div, p, dl, #nav-tree .label, .title,
 | 
			
		||||
body, table, div, p, dl, #nav-tree .label, #nav-tree a, .title,
 | 
			
		||||
.sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname,
 | 
			
		||||
.SelectItem, #MSearchField, .navpath li.navelem a,
 | 
			
		||||
.navpath li.navelem a:hover, p.reference, p.definition, div.toc li, div.toc h3 {
 | 
			
		||||
.navpath li.navelem a:hover, p.reference, p.definition, div.toc li, div.toc h3,
 | 
			
		||||
#page-nav ul.page-outline li a {
 | 
			
		||||
    font-family: var(--font-family);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -332,8 +318,13 @@ p.reference, p.definition {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:link, a:visited, a:hover, a:focus, a:active {
 | 
			
		||||
    color: var(--primary-color) !important;
 | 
			
		||||
    color: var(--link-color) !important;
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
    background: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:hover {
 | 
			
		||||
    text-decoration: underline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a.anchor {
 | 
			
		||||
@@ -348,6 +339,8 @@ a.anchor {
 | 
			
		||||
#top {
 | 
			
		||||
    background: var(--header-background);
 | 
			
		||||
    border-bottom: 1px solid var(--separator-color);
 | 
			
		||||
    position: relative;
 | 
			
		||||
    z-index: 99;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media screen and (min-width: 768px) {
 | 
			
		||||
@@ -362,6 +355,7 @@ a.anchor {
 | 
			
		||||
#main-nav {
 | 
			
		||||
    flex-grow: 5;
 | 
			
		||||
    padding: var(--spacing-small) var(--spacing-medium);
 | 
			
		||||
    border-bottom: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#titlearea {
 | 
			
		||||
@@ -441,19 +435,36 @@ a.anchor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .sm-dox a span.sub-arrow {
 | 
			
		||||
        border-color: var(--header-foreground) transparent transparent transparent;
 | 
			
		||||
        top: 15px;
 | 
			
		||||
        right: 10px;
 | 
			
		||||
        box-sizing: content-box;
 | 
			
		||||
        padding: 0;
 | 
			
		||||
        margin: 0;
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        width: 5px;
 | 
			
		||||
        height: 5px;
 | 
			
		||||
        transform: rotate(45deg);
 | 
			
		||||
        border-width: 0;
 | 
			
		||||
        border-right: 2px solid var(--header-foreground);
 | 
			
		||||
        border-bottom: 2px solid var(--header-foreground);
 | 
			
		||||
        background: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .sm-dox a:hover span.sub-arrow {
 | 
			
		||||
        border-color: var(--menu-focus-foreground) transparent transparent transparent;
 | 
			
		||||
        border-color: var(--menu-focus-foreground);
 | 
			
		||||
        background: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .sm-dox ul a span.sub-arrow {
 | 
			
		||||
        border-color: transparent transparent transparent var(--page-foreground-color);
 | 
			
		||||
        transform: rotate(-45deg);
 | 
			
		||||
        border-width: 0;
 | 
			
		||||
        border-right: 2px solid var(--header-foreground);
 | 
			
		||||
        border-bottom: 2px solid var(--header-foreground);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .sm-dox ul a:hover span.sub-arrow {
 | 
			
		||||
        border-color: transparent transparent transparent var(--menu-focus-foreground);
 | 
			
		||||
        border-color: var(--menu-focus-foreground);
 | 
			
		||||
        background: none;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -480,7 +491,7 @@ a.anchor {
 | 
			
		||||
 | 
			
		||||
.sm-dox ul a {
 | 
			
		||||
    color: var(--page-foreground-color) !important;
 | 
			
		||||
    background: var(--page-background-color);
 | 
			
		||||
    background: none;
 | 
			
		||||
    font-size: var(--navigation-font-size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -552,6 +563,13 @@ a.anchor {
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
    display: block;
 | 
			
		||||
    margin-top: 0;
 | 
			
		||||
    margin-right: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (min-width: 768px) {
 | 
			
		||||
    .sm-dox li {
 | 
			
		||||
        padding: 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* until Doxygen 1.9.4 */
 | 
			
		||||
@@ -573,6 +591,17 @@ a.anchor {
 | 
			
		||||
    padding-left: 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Doxygen 1.14.0 */
 | 
			
		||||
.search-icon::before {
 | 
			
		||||
    background: none;
 | 
			
		||||
    top: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.search-icon::after {
 | 
			
		||||
    background: none;
 | 
			
		||||
    top: 12px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.SelectionMark {
 | 
			
		||||
    user-select: none;
 | 
			
		||||
}
 | 
			
		||||
@@ -776,12 +805,15 @@ html.dark-mode iframe#MSearchResults {
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#side-nav {
 | 
			
		||||
    padding: 0 !important;
 | 
			
		||||
    background: var(--side-nav-background);
 | 
			
		||||
    min-width: 8px;
 | 
			
		||||
    max-width: 50vw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#nav-tree, #top {
 | 
			
		||||
    border-right: 1px solid var(--separator-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media screen and (max-width: 767px) {
 | 
			
		||||
    #side-nav {
 | 
			
		||||
        display: none;
 | 
			
		||||
@@ -790,34 +822,95 @@ html.dark-mode iframe#MSearchResults {
 | 
			
		||||
    #doc-content {
 | 
			
		||||
        margin-left: 0 !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #top {
 | 
			
		||||
        border-right: none;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree {
 | 
			
		||||
    background: transparent;
 | 
			
		||||
    margin-right: 1px;
 | 
			
		||||
    background: var(--side-nav-background);
 | 
			
		||||
    margin-right: -1px;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree .label {
 | 
			
		||||
    font-size: var(--navigation-font-size);
 | 
			
		||||
    line-height: var(--tree-item-height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree span.label a:hover {
 | 
			
		||||
    background: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree .item {
 | 
			
		||||
    height: var(--tree-item-height);
 | 
			
		||||
    line-height: var(--tree-item-height);
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree-contents {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#main-menu > li:last-child {
 | 
			
		||||
    height: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree .item > a:focus {
 | 
			
		||||
    outline: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-sync {
 | 
			
		||||
    bottom: 12px;
 | 
			
		||||
    right: 12px;
 | 
			
		||||
    bottom: var(--spacing-medium);
 | 
			
		||||
    right: var(--spacing-medium) !important;
 | 
			
		||||
    top: auto !important;
 | 
			
		||||
    user-select: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.nav-sync-icon {
 | 
			
		||||
    border: 1px solid var(--separator-color);
 | 
			
		||||
    border-radius: var(--border-radius-medium);
 | 
			
		||||
    background: var(--page-background-color);
 | 
			
		||||
    width: 30px;
 | 
			
		||||
    height: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.nav-sync-icon:hover {
 | 
			
		||||
    background: var(--page-background-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
span.sync-icon-left, div.nav-sync-icon:hover span.sync-icon-left {
 | 
			
		||||
    border-left: 2px solid var(--primary-color);
 | 
			
		||||
    border-top: 2px solid var(--primary-color);
 | 
			
		||||
    top: 5px;
 | 
			
		||||
    left: 6px;
 | 
			
		||||
}
 | 
			
		||||
span.sync-icon-right, div.nav-sync-icon:hover span.sync-icon-right {
 | 
			
		||||
    border-right: 2px solid var(--primary-color);
 | 
			
		||||
    border-bottom: 2px solid var(--primary-color);
 | 
			
		||||
    top: 5px;
 | 
			
		||||
    left: initial;
 | 
			
		||||
    right: 6px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.nav-sync-icon.active::after, div.nav-sync-icon.active:hover::after {
 | 
			
		||||
    border-top: 2px solid var(--primary-color);
 | 
			
		||||
    top: 9px;
 | 
			
		||||
    left: 6px;
 | 
			
		||||
    width: 19px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree .selected {
 | 
			
		||||
    text-shadow: none;
 | 
			
		||||
    background-image: none;
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    color: var(--primary-color) !important;
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree .selected::after {
 | 
			
		||||
@@ -843,9 +936,27 @@ html.dark-mode iframe#MSearchResults {
 | 
			
		||||
 | 
			
		||||
#nav-tree .arrow {
 | 
			
		||||
    opacity: var(--side-nav-arrow-opacity);
 | 
			
		||||
    background: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.arrow {
 | 
			
		||||
#nav-tree span.arrowhead {
 | 
			
		||||
    margin: 0 0 1px 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
span.arrowhead {
 | 
			
		||||
    border-color: var(--primary-light-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.selected span.arrowhead {
 | 
			
		||||
    border-color: var(--primary-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree-contents > ul > li:first-child > div > a {
 | 
			
		||||
    opacity: 0;
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contents .arrow {
 | 
			
		||||
    color: inherit;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    font-size: 45%;
 | 
			
		||||
@@ -853,7 +964,7 @@ html.dark-mode iframe#MSearchResults {
 | 
			
		||||
    margin-right: 2px;
 | 
			
		||||
    font-family: serif;
 | 
			
		||||
    height: auto;
 | 
			
		||||
    text-align: right;
 | 
			
		||||
    padding-bottom: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow {
 | 
			
		||||
@@ -867,9 +978,11 @@ html.dark-mode iframe#MSearchResults {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ui-resizable-e {
 | 
			
		||||
    width: 4px;
 | 
			
		||||
    background: transparent;
 | 
			
		||||
    box-shadow: inset -1px 0 0 0 var(--separator-color);
 | 
			
		||||
    background: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ui-resizable-e:hover {
 | 
			
		||||
    background: var(--separator-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -878,7 +991,7 @@ html.dark-mode iframe#MSearchResults {
 | 
			
		||||
 | 
			
		||||
div.header {
 | 
			
		||||
    border-bottom: 1px solid var(--separator-color);
 | 
			
		||||
    background-color: var(--page-background-color);
 | 
			
		||||
    background: none;
 | 
			
		||||
    background-image: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -917,7 +1030,7 @@ div.headertitle {
 | 
			
		||||
div.header .title {
 | 
			
		||||
    font-weight: 600;
 | 
			
		||||
    font-size: 225%;
 | 
			
		||||
    padding: var(--spacing-medium) var(--spacing-large);
 | 
			
		||||
    padding: var(--spacing-medium) var(--spacing-xlarge);
 | 
			
		||||
    word-break: break-word;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -934,9 +1047,10 @@ td.memSeparator {
 | 
			
		||||
 | 
			
		||||
span.mlabel {
 | 
			
		||||
    background: var(--primary-color);
 | 
			
		||||
    color: var(--on-primary-color);
 | 
			
		||||
    border: none;
 | 
			
		||||
    padding: 4px 9px;
 | 
			
		||||
    border-radius: 12px;
 | 
			
		||||
    border-radius: var(--border-radius-large);
 | 
			
		||||
    margin-right: var(--spacing-medium);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -945,7 +1059,7 @@ span.mlabel:last-of-type {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.contents {
 | 
			
		||||
    padding: 0 var(--spacing-large);
 | 
			
		||||
    padding: 0 var(--spacing-xlarge);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.contents p, div.contents li {
 | 
			
		||||
@@ -956,6 +1070,16 @@ div.contents div.dyncontent {
 | 
			
		||||
    margin: var(--spacing-medium) 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media screen and (max-width: 767px) {
 | 
			
		||||
    div.contents {
 | 
			
		||||
        padding: 0 var(--spacing-large);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    div.header .title {
 | 
			
		||||
        padding: var(--spacing-medium) var(--spacing-large);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (prefers-color-scheme: dark) {
 | 
			
		||||
    html:not(.light-mode) div.contents div.dyncontent img,
 | 
			
		||||
    html:not(.light-mode) div.contents center img,
 | 
			
		||||
@@ -979,7 +1103,7 @@ html.dark-mode div.contents .dotgraph iframe
 | 
			
		||||
    filter: brightness(89%) hue-rotate(180deg) invert();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h2.groupheader {
 | 
			
		||||
td h2.groupheader, h2.groupheader {
 | 
			
		||||
    border-bottom: 0px;
 | 
			
		||||
    color: var(--page-foreground-color);
 | 
			
		||||
    box-shadow: 
 | 
			
		||||
@@ -1040,7 +1164,7 @@ blockquote::after {
 | 
			
		||||
blockquote p {
 | 
			
		||||
    margin: var(--spacing-small) 0 var(--spacing-medium) 0;
 | 
			
		||||
}
 | 
			
		||||
.paramname {
 | 
			
		||||
.paramname, .paramname em {
 | 
			
		||||
    font-weight: 600;
 | 
			
		||||
    color: var(--primary-dark-color);
 | 
			
		||||
}
 | 
			
		||||
@@ -1090,7 +1214,7 @@ div.contents .toc {
 | 
			
		||||
    border: 0;
 | 
			
		||||
    border-left: 1px solid var(--separator-color);
 | 
			
		||||
    border-radius: 0;
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
    background-color: var(--page-background-color);
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
    position: sticky;
 | 
			
		||||
    top: var(--toc-sticky-top);
 | 
			
		||||
@@ -1198,24 +1322,115 @@ div.toc li a.aboveActive {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 Page Outline (Doxygen >= 1.14.0)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#page-nav {
 | 
			
		||||
    background: var(--page-background-color);
 | 
			
		||||
    border-left: 1px solid var(--separator-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav #page-nav-resize-handle {
 | 
			
		||||
    background: var(--separator-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav #page-nav-resize-handle::after {
 | 
			
		||||
    border-left: 1px solid var(--primary-color);
 | 
			
		||||
    border-right: 1px solid var(--primary-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav #page-nav-tree #page-nav-contents {
 | 
			
		||||
    top: var(--spacing-large);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline li a {
 | 
			
		||||
    font-size: var(--toc-font-size) !important;
 | 
			
		||||
    color: var(--page-secondary-foreground-color) !important;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    line-height: calc(2 * var(--toc-font-size));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline li a a.anchorlink {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline li.vis ~ * a {
 | 
			
		||||
    color: var(--page-foreground-color) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline li.vis:not(.vis ~ .vis) a, #page-nav ul.page-outline li a:hover {
 | 
			
		||||
    color: var(--primary-color) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline .vis {
 | 
			
		||||
    background: var(--page-background-color);
 | 
			
		||||
    position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline .vis::after {
 | 
			
		||||
    content: "";
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    width: 4px;
 | 
			
		||||
    background: var(--page-secondary-foreground-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline .vis:not(.vis ~ .vis)::after {
 | 
			
		||||
    top: 1px;
 | 
			
		||||
    border-top-right-radius: var(--border-radius-small);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline .vis:not(:has(~ .vis))::after {
 | 
			
		||||
    bottom: 1px;
 | 
			
		||||
    border-bottom-right-radius: var(--border-radius-small);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline .arrow {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#page-nav ul.page-outline .arrow span {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media screen and (max-width: 767px) {
 | 
			
		||||
    #container {
 | 
			
		||||
        grid-template-columns: initial !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #page-nav {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 Code & Fragments
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
code, div.fragment, pre.fragment {
 | 
			
		||||
    border-radius: var(--border-radius-small);
 | 
			
		||||
code, div.fragment, pre.fragment, span.tt {
 | 
			
		||||
    border: 1px solid var(--separator-color);
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
code {
 | 
			
		||||
code, span.tt {
 | 
			
		||||
    display: inline;
 | 
			
		||||
    background: var(--code-background);
 | 
			
		||||
    color: var(--code-foreground);
 | 
			
		||||
    padding: 2px 6px;
 | 
			
		||||
    border-radius: var(--border-radius-small);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.fragment, pre.fragment {
 | 
			
		||||
    border-radius: var(--border-radius-medium);
 | 
			
		||||
    margin: var(--spacing-medium) 0;
 | 
			
		||||
    padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large);
 | 
			
		||||
    background: var(--fragment-background);
 | 
			
		||||
@@ -1273,7 +1488,7 @@ div.fragment, pre.fragment {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span {
 | 
			
		||||
code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span, span.tt {
 | 
			
		||||
    font-family: var(--font-family-monospace);
 | 
			
		||||
    font-size: var(--code-font-size) !important;
 | 
			
		||||
}
 | 
			
		||||
@@ -1347,6 +1562,10 @@ div.line.glow {
 | 
			
		||||
 dl warning, attention, note, deprecated, bug, ...
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
dl {
 | 
			
		||||
    line-height: calc(1.65 * var(--page-font-size));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dl.bug dt a, dl.deprecated dt a, dl.todo dt a {
 | 
			
		||||
    font-weight: bold !important;
 | 
			
		||||
}
 | 
			
		||||
@@ -1512,6 +1731,7 @@ div.memitem {
 | 
			
		||||
    border-top-right-radius: var(--border-radius-medium);
 | 
			
		||||
    border-bottom-right-radius: var(--border-radius-medium);
 | 
			
		||||
    border-bottom-left-radius: var(--border-radius-medium);
 | 
			
		||||
    border-top-left-radius: 0;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    display: block !important;
 | 
			
		||||
}
 | 
			
		||||
@@ -1743,7 +1963,7 @@ table.fieldtable th {
 | 
			
		||||
    color: var(--tablehead-foreground);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fielddoc, .fieldtable th {
 | 
			
		||||
table.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fieldinit, .fieldtable td.fielddoc, .fieldtable th {
 | 
			
		||||
    border-bottom: 1px solid var(--separator-color);
 | 
			
		||||
    border-right: 1px solid var(--separator-color);
 | 
			
		||||
}
 | 
			
		||||
@@ -1778,8 +1998,10 @@ table.memberdecls tr[class^='memitem'] .memTemplParams {
 | 
			
		||||
    white-space: normal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.memberdecls .memItemLeft,
 | 
			
		||||
table.memberdecls .memItemRight,
 | 
			
		||||
table.memberdecls tr.heading + tr[class^='memitem'] td.memItemLeft,
 | 
			
		||||
table.memberdecls tr.heading + tr[class^='memitem'] td.memItemRight,
 | 
			
		||||
table.memberdecls td.memItemLeft,
 | 
			
		||||
table.memberdecls td.memItemRight,
 | 
			
		||||
table.memberdecls .memTemplItemLeft,
 | 
			
		||||
table.memberdecls .memTemplItemRight,
 | 
			
		||||
table.memberdecls .memTemplParams {
 | 
			
		||||
@@ -1791,8 +2013,34 @@ table.memberdecls .memTemplParams {
 | 
			
		||||
    background-color: var(--fragment-background);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media screen and (min-width: 768px) {
 | 
			
		||||
 | 
			
		||||
    tr.heading + tr[class^='memitem'] td.memItemRight, tr.groupHeader + tr[class^='memitem'] td.memItemRight, tr.inherit_header + tr[class^='memitem'] td.memItemRight {
 | 
			
		||||
        border-top-right-radius: var(--border-radius-small);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    table.memberdecls tr:last-child td.memItemRight, table.memberdecls tr:last-child td.mdescRight, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemRight, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemRight, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescRight, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescRight {
 | 
			
		||||
        border-bottom-right-radius: var(--border-radius-small);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    table.memberdecls tr:last-child td.memItemLeft, table.memberdecls tr:last-child td.mdescLeft, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemLeft, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescLeft {
 | 
			
		||||
        border-bottom-left-radius: var(--border-radius-small);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tr.heading + tr[class^='memitem'] td.memItemLeft, tr.groupHeader + tr[class^='memitem'] td.memItemLeft, tr.inherit_header + tr[class^='memitem'] td.memItemLeft {
 | 
			
		||||
        border-top-left-radius: var(--border-radius-small);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.memname td.memname {
 | 
			
		||||
    font-size: var(--memname-font-size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.memberdecls .memTemplItemLeft,
 | 
			
		||||
table.memberdecls .memTemplItemRight {
 | 
			
		||||
table.memberdecls .template .memItemLeft,
 | 
			
		||||
table.memberdecls .memTemplItemRight,
 | 
			
		||||
table.memberdecls .template .memItemRight {
 | 
			
		||||
    padding-top: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1804,13 +2052,13 @@ table.memberdecls .memTemplParams {
 | 
			
		||||
    padding-bottom: var(--spacing-small);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.memberdecls .memTemplItemLeft {
 | 
			
		||||
table.memberdecls .memTemplItemLeft, table.memberdecls .template .memItemLeft {
 | 
			
		||||
    border-radius: 0 0 0 var(--border-radius-small);
 | 
			
		||||
    border-left: 1px solid var(--separator-color);
 | 
			
		||||
    border-top: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.memberdecls .memTemplItemRight {
 | 
			
		||||
table.memberdecls .memTemplItemRight, table.memberdecls .template .memItemRight {
 | 
			
		||||
    border-radius: 0 0 var(--border-radius-small) 0;
 | 
			
		||||
    border-right: 1px solid var(--separator-color);
 | 
			
		||||
    padding-left: 0;
 | 
			
		||||
@@ -1836,8 +2084,14 @@ table.memberdecls .mdescLeft, table.memberdecls .mdescRight {
 | 
			
		||||
    background: none;
 | 
			
		||||
    color: var(--page-foreground-color);
 | 
			
		||||
    padding: var(--spacing-small) 0;
 | 
			
		||||
    border: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.memberdecls [class^="memdesc"] {
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
table.memberdecls .memItemLeft,
 | 
			
		||||
table.memberdecls .memTemplItemLeft {
 | 
			
		||||
    padding-right: var(--spacing-medium);
 | 
			
		||||
@@ -1860,6 +2114,10 @@ table.memberdecls .inherit_header td {
 | 
			
		||||
    color: var(--page-secondary-foreground-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.memberdecls span.dynarrow {
 | 
			
		||||
    left: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.memberdecls img[src="closed.png"],
 | 
			
		||||
table.memberdecls img[src="open.png"],
 | 
			
		||||
div.dynheader img[src="open.png"],
 | 
			
		||||
@@ -1876,6 +2134,10 @@ div.dynheader img[src="closed.png"] {
 | 
			
		||||
    transition: transform var(--animation-duration) ease-out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tr.heading + tr[class^='memitem'] td.memItemLeft, tr.groupHeader + tr[class^='memitem'] td.memItemLeft, tr.inherit_header + tr[class^='memitem'] td.memItemLeft, tr.heading + tr[class^='memitem'] td.memItemRight, tr.groupHeader + tr[class^='memitem'] td.memItemRight, tr.inherit_header + tr[class^='memitem'] td.memItemRight {
 | 
			
		||||
    border-top: 1px solid var(--separator-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.memberdecls img {
 | 
			
		||||
    margin-right: 10px;
 | 
			
		||||
}
 | 
			
		||||
@@ -1900,7 +2162,10 @@ div.dynheader img[src="closed.png"] {
 | 
			
		||||
    table.memberdecls .mdescRight,
 | 
			
		||||
    table.memberdecls .memTemplItemLeft,
 | 
			
		||||
    table.memberdecls .memTemplItemRight,
 | 
			
		||||
    table.memberdecls .memTemplParams {
 | 
			
		||||
    table.memberdecls .memTemplParams,
 | 
			
		||||
    table.memberdecls .template .memItemLeft,
 | 
			
		||||
    table.memberdecls .template .memItemRight,
 | 
			
		||||
    table.memberdecls .template .memParams {
 | 
			
		||||
        display: block;
 | 
			
		||||
        text-align: left;
 | 
			
		||||
        padding-left: var(--spacing-large);
 | 
			
		||||
@@ -1913,12 +2178,14 @@ div.dynheader img[src="closed.png"] {
 | 
			
		||||
 | 
			
		||||
    table.memberdecls .memItemLeft,
 | 
			
		||||
    table.memberdecls .mdescLeft,
 | 
			
		||||
    table.memberdecls .memTemplItemLeft {
 | 
			
		||||
        border-bottom: 0;
 | 
			
		||||
        padding-bottom: 0;
 | 
			
		||||
    table.memberdecls .memTemplItemLeft,
 | 
			
		||||
    table.memberdecls .template .memItemLeft {
 | 
			
		||||
        border-bottom: 0 !important;
 | 
			
		||||
        padding-bottom: 0 !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    table.memberdecls .memTemplItemLeft {
 | 
			
		||||
    table.memberdecls .memTemplItemLeft,
 | 
			
		||||
    table.memberdecls .template .memItemLeft {
 | 
			
		||||
        padding-top: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1928,10 +2195,12 @@ div.dynheader img[src="closed.png"] {
 | 
			
		||||
 | 
			
		||||
    table.memberdecls .memItemRight, 
 | 
			
		||||
    table.memberdecls .mdescRight,
 | 
			
		||||
    table.memberdecls .memTemplItemRight {
 | 
			
		||||
        border-top: 0;
 | 
			
		||||
        padding-top: 0;
 | 
			
		||||
    table.memberdecls .memTemplItemRight,
 | 
			
		||||
    table.memberdecls .template .memItemRight {
 | 
			
		||||
        border-top: 0 !important;
 | 
			
		||||
        padding-top: 0 !important;
 | 
			
		||||
        padding-right: var(--spacing-large);
 | 
			
		||||
        padding-bottom: var(--spacing-medium);
 | 
			
		||||
        overflow-x: auto;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1966,6 +2235,22 @@ div.dynheader img[src="closed.png"] {
 | 
			
		||||
            max-height: 200px;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tr.heading + tr[class^='memitem'] td.memItemRight, tr.groupHeader + tr[class^='memitem'] td.memItemRight, tr.inherit_header + tr[class^='memitem'] td.memItemRight {
 | 
			
		||||
        border-top-right-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    table.memberdecls tr:last-child td.memItemRight, table.memberdecls tr:last-child td.mdescRight, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemRight, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemRight, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescRight, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescRight {
 | 
			
		||||
        border-bottom-right-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    table.memberdecls tr:last-child td.memItemLeft, table.memberdecls tr:last-child td.mdescLeft, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemLeft, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescLeft {
 | 
			
		||||
        border-bottom-left-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tr.heading + tr[class^='memitem'] td.memItemLeft, tr.groupHeader + tr[class^='memitem'] td.memItemLeft, tr.inherit_header + tr[class^='memitem'] td.memItemLeft {
 | 
			
		||||
        border-top-left-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1982,14 +2267,16 @@ hr {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contents hr {
 | 
			
		||||
    box-shadow: 100px 0 0 var(--separator-color),
 | 
			
		||||
                -100px 0 0 var(--separator-color),
 | 
			
		||||
                500px 0 0 var(--separator-color),
 | 
			
		||||
                -500px 0 0 var(--separator-color),
 | 
			
		||||
                1500px 0 0 var(--separator-color),
 | 
			
		||||
                -1500px 0 0 var(--separator-color),
 | 
			
		||||
                2000px 0 0 var(--separator-color),
 | 
			
		||||
                -2000px 0 0 var(--separator-color);
 | 
			
		||||
    box-shadow: 100px 0 var(--separator-color),
 | 
			
		||||
                -100px 0 var(--separator-color),
 | 
			
		||||
                500px 0 var(--separator-color),
 | 
			
		||||
                -500px 0 var(--separator-color),
 | 
			
		||||
                900px 0 var(--separator-color),
 | 
			
		||||
                -900px 0 var(--separator-color),
 | 
			
		||||
                1400px 0 var(--separator-color),
 | 
			
		||||
                -1400px 0 var(--separator-color),
 | 
			
		||||
                1900px 0 var(--separator-color),
 | 
			
		||||
                -1900px 0 var(--separator-color);       
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contents img, .contents .center, .contents center, .contents div.image object {
 | 
			
		||||
@@ -2152,9 +2439,7 @@ div.qindex {
 | 
			
		||||
    background: var(--page-background-color);
 | 
			
		||||
    border: none;
 | 
			
		||||
    border-top: 1px solid var(--separator-color);
 | 
			
		||||
    border-bottom: 1px solid var(--separator-color);
 | 
			
		||||
    border-bottom: 0;
 | 
			
		||||
    box-shadow: 0 0.75px 0 var(--separator-color);
 | 
			
		||||
    font-size: var(--navigation-font-size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2183,6 +2468,10 @@ address.footer {
 | 
			
		||||
    color: var(--primary-color) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.navpath li.navelem a:hover {
 | 
			
		||||
    text-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.navpath li.navelem b {
 | 
			
		||||
    color: var(--primary-dark-color);
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
@@ -2201,7 +2490,11 @@ li.navelem:first-child:before {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-path li.navelem:after {
 | 
			
		||||
#nav-path ul {
 | 
			
		||||
    padding-left: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-path li.navelem:has(.el):after {
 | 
			
		||||
    content: '';
 | 
			
		||||
    border: 5px solid var(--page-background-color);
 | 
			
		||||
    border-bottom-color: transparent;
 | 
			
		||||
@@ -2212,7 +2505,21 @@ li.navelem:first-child:before {
 | 
			
		||||
    margin-left: 6px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-path li.navelem:before {
 | 
			
		||||
#nav-path li.navelem:not(:has(.el)):after {
 | 
			
		||||
    background: var(--page-background-color);
 | 
			
		||||
    box-shadow: 1px -1px 0 1px var(--separator-color);
 | 
			
		||||
    border-radius: 0 var(--border-radius-medium) 0 50px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-path li.navelem:not(:has(.el)) {
 | 
			
		||||
    margin-left: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-path li.navelem:not(:has(.el)):hover, #nav-path li.navelem:not(:has(.el)):hover:after {
 | 
			
		||||
    background-color: var(--separator-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-path li.navelem:has(.el):before {
 | 
			
		||||
    content: '';
 | 
			
		||||
    border: 5px solid var(--separator-color);
 | 
			
		||||
    border-bottom-color: transparent;
 | 
			
		||||
@@ -2338,7 +2645,7 @@ doxygen-awesome-dark-mode-toggle {
 | 
			
		||||
    height: var(--searchbar-height);
 | 
			
		||||
    background: none;
 | 
			
		||||
    border: none;
 | 
			
		||||
    border-radius: var(--searchbar-height);
 | 
			
		||||
    border-radius: var(--searchbar-border-radius);
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    line-height: var(--searchbar-height);
 | 
			
		||||
@@ -2523,6 +2830,7 @@ h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.
 | 
			
		||||
    float: left;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    font-weight: normal;
 | 
			
		||||
    font-family: var(--font-family);
 | 
			
		||||
    padding: calc(var(--spacing-large) / 2) var(--spacing-large);
 | 
			
		||||
    border-radius: var(--border-radius-medium);
 | 
			
		||||
    transition: background-color var(--animation-duration) ease-in-out, font-weight var(--animation-duration) ease-in-out;
 | 
			
		||||
@@ -2667,3 +2975,46 @@ h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.
 | 
			
		||||
        border-radius: 0 var(--border-radius-medium) var(--border-radius-medium) 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 Bordered image
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
html.dark-mode .darkmode_inverted_image img, /* < doxygen 1.9.3 */
 | 
			
		||||
html.dark-mode .darkmode_inverted_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ {
 | 
			
		||||
    filter: brightness(89%) hue-rotate(180deg) invert();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.bordered_image {
 | 
			
		||||
    border-radius: var(--border-radius-small);
 | 
			
		||||
    border: 1px solid var(--separator-color);
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.bordered_image:empty {
 | 
			
		||||
    border: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html.dark-mode .bordered_image img, /* < doxygen 1.9.3 */
 | 
			
		||||
html.dark-mode .bordered_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ {
 | 
			
		||||
    border-radius: var(--border-radius-small);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 Button
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
.primary-button {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    background: var(--primary-color);
 | 
			
		||||
    color: var(--page-background-color) !important;
 | 
			
		||||
    border-radius: var(--border-radius-medium);
 | 
			
		||||
    padding: var(--spacing-small) var(--spacing-medium);
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.primary-button:hover {
 | 
			
		||||
    background: var(--primary-dark-color);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										129
									
								
								docs/doxygen-awesome-theme/doxygen-custom/custom.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								docs/doxygen-awesome-theme/doxygen-custom/custom.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
			
		||||
.github-corner svg {
 | 
			
		||||
    fill: var(--primary-light-color);
 | 
			
		||||
    color: var(--page-background-color);
 | 
			
		||||
    width: 72px;
 | 
			
		||||
    height: 72px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media screen and (max-width: 767px) {
 | 
			
		||||
    .github-corner svg {
 | 
			
		||||
        width: 50px;
 | 
			
		||||
        height: 50px;
 | 
			
		||||
    }
 | 
			
		||||
    #projectnumber {
 | 
			
		||||
        margin-right: 22px;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.title_screenshot {
 | 
			
		||||
    filter: drop-shadow(0px 3px 10px rgba(0,0,0,0.22));
 | 
			
		||||
    max-width: 500px;
 | 
			
		||||
    margin: var(--spacing-large) 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.title_screenshot .caption {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#theme-selection {
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    background: var(--side-nav-background);
 | 
			
		||||
    padding: 5px 2px 5px 8px;
 | 
			
		||||
    box-shadow: 0 -4px 4px -2px var(--side-nav-background);
 | 
			
		||||
    display: flex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#theme-selection label {
 | 
			
		||||
    border: 1px solid var(--separator-color);
 | 
			
		||||
    border-right: 0;
 | 
			
		||||
    color: var(--page-foreground-color);
 | 
			
		||||
    font-size: var(--toc-font-size);
 | 
			
		||||
    padding: 0 8px;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    height: 22px;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    border-radius: var(--border-radius-medium) 0 0 var(--border-radius-medium);
 | 
			
		||||
    line-height: 20px;
 | 
			
		||||
    background: var(--page-background-color);
 | 
			
		||||
    opacity: 0.7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (prefers-color-scheme: dark) {
 | 
			
		||||
    html:not(.light-mode) #theme-select {
 | 
			
		||||
        background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23aaaaaa'><polygon points='0,0 100,0 50,50'/></svg>") no-repeat;
 | 
			
		||||
        background-size: 8px;
 | 
			
		||||
        background-position: calc(100% - 6px) 65%;
 | 
			
		||||
        background-color: var(--page-background-color);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html.dark-mode #theme-select {
 | 
			
		||||
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23aaaaaa'><polygon points='0,0 100,0 50,50'/></svg>") no-repeat;
 | 
			
		||||
    background-size: 8px;
 | 
			
		||||
    background-position: calc(100% - 6px) 65%;
 | 
			
		||||
    background-color: var(--page-background-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#theme-select {
 | 
			
		||||
    border: 1px solid var(--separator-color);
 | 
			
		||||
    border-radius: 0 var(--border-radius-medium) var(--border-radius-medium) 0;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    height: 22px;
 | 
			
		||||
    font-size: var(--toc-font-size);
 | 
			
		||||
    font-family: var(--font-family);
 | 
			
		||||
    width: 215px;
 | 
			
		||||
    color: var(--primary-color);
 | 
			
		||||
    border-left: 0;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    opacity: 0.7;
 | 
			
		||||
    outline: none;
 | 
			
		||||
    -webkit-appearance: none;
 | 
			
		||||
    -moz-appearance: none;
 | 
			
		||||
    appearance: none;
 | 
			
		||||
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23888888'><polygon points='0,0 100,0 50,50'/></svg>") no-repeat;
 | 
			
		||||
    background-size: 8px;
 | 
			
		||||
    background-position: calc(100% - 6px) 65%;
 | 
			
		||||
    background-repeat: no-repeat;
 | 
			
		||||
    background-color: var(--page-background-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#theme-selection:hover #theme-select, #theme-selection:hover label {
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#nav-tree-contents {
 | 
			
		||||
    margin-bottom: 30px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media screen and (max-width: 767px) {
 | 
			
		||||
    #theme-selection {
 | 
			
		||||
        box-shadow: none;
 | 
			
		||||
        background: none;
 | 
			
		||||
        height: 20px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #theme-select {
 | 
			
		||||
        width: 80px;
 | 
			
		||||
        opacity: 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #theme-selection label {
 | 
			
		||||
        opacity: 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #nav-path ul li.navelem:first-child {
 | 
			
		||||
        margin-left: 160px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ul li.footer:not(:first-child) {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #nav-path {
 | 
			
		||||
        position: fixed;
 | 
			
		||||
        bottom: 0;
 | 
			
		||||
        background: var(--page-background-color);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										98
									
								
								docs/doxygen-awesome-theme/doxygen-custom/header.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								docs/doxygen-awesome-theme/doxygen-custom/header.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 | 
			
		||||
<html xmlns="http://www.w3.org/1999/xhtml">
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
 | 
			
		||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
 | 
			
		||||
<meta name="generator" content="Doxygen $doxygenversion"/>
 | 
			
		||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
 | 
			
		||||
 | 
			
		||||
<!-- BEGIN opengraph metadata -->
 | 
			
		||||
<meta property="og:title" content="Doxygen Awesome" />
 | 
			
		||||
<meta property="og:image" content="https://repository-images.githubusercontent.com/348492097/4f16df80-88fb-11eb-9d31-4015ff22c452" />
 | 
			
		||||
<meta property="og:description" content="Custom CSS theme for doxygen html-documentation with lots of customization parameters." />
 | 
			
		||||
<meta property="og:url" content="https://jothepro.github.io/doxygen-awesome-css/" />
 | 
			
		||||
<!-- END opengraph metadata -->
 | 
			
		||||
 | 
			
		||||
<!-- BEGIN twitter metadata -->
 | 
			
		||||
<meta name="twitter:image:src" content="https://repository-images.githubusercontent.com/348492097/4f16df80-88fb-11eb-9d31-4015ff22c452" />
 | 
			
		||||
<meta name="twitter:title" content="Doxygen Awesome" />
 | 
			
		||||
<meta name="twitter:description" content="Custom CSS theme for doxygen html-documentation with lots of customization parameters." />
 | 
			
		||||
<!-- END twitter metadata -->
 | 
			
		||||
 | 
			
		||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
 | 
			
		||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
 | 
			
		||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
 | 
			
		||||
<link rel="icon" type="image/svg+xml" href="logo.drawio.svg"/>
 | 
			
		||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
 | 
			
		||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
 | 
			
		||||
<script type="text/javascript" src="$relpath^doxygen-awesome-darkmode-toggle.js"></script>
 | 
			
		||||
<script type="text/javascript" src="$relpath^doxygen-awesome-fragment-copy-button.js"></script>
 | 
			
		||||
<script type="text/javascript" src="$relpath^doxygen-awesome-paragraph-link.js"></script>
 | 
			
		||||
<script type="text/javascript" src="$relpath^doxygen-awesome-interactive-toc.js"></script>
 | 
			
		||||
<script type="text/javascript" src="$relpath^doxygen-awesome-tabs.js"></script>
 | 
			
		||||
<script type="text/javascript" src="$relpath^toggle-alternative-theme.js"></script>
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
    DoxygenAwesomeFragmentCopyButton.init()
 | 
			
		||||
    DoxygenAwesomeDarkModeToggle.init()
 | 
			
		||||
    DoxygenAwesomeParagraphLink.init()
 | 
			
		||||
    DoxygenAwesomeInteractiveToc.init()
 | 
			
		||||
    DoxygenAwesomeTabs.init()
 | 
			
		||||
</script>
 | 
			
		||||
$treeview
 | 
			
		||||
$search
 | 
			
		||||
$mathjax
 | 
			
		||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
 | 
			
		||||
$extrastylesheet
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
 | 
			
		||||
<!-- https://tholman.com/github-corners/ -->
 | 
			
		||||
<a href="https://github.com/jothepro/doxygen-awesome-css" class="github-corner" title="View source on GitHub" target="_blank" rel="noopener noreferrer">
 | 
			
		||||
    <svg viewBox="0 0 250 250" width="40" height="40" style="position: absolute; top: 0; border: 0; right: 0; z-index: 99;" aria-hidden="true">
 | 
			
		||||
    <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
 | 
			
		||||
 | 
			
		||||
<!--BEGIN TITLEAREA-->
 | 
			
		||||
<div id="titlearea">
 | 
			
		||||
<table cellspacing="0" cellpadding="0">
 | 
			
		||||
 <tbody>
 | 
			
		||||
 <tr style="height: 56px;">
 | 
			
		||||
  <!--BEGIN PROJECT_LOGO-->
 | 
			
		||||
  <td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
 | 
			
		||||
  <!--END PROJECT_LOGO-->
 | 
			
		||||
  <!--BEGIN PROJECT_NAME-->
 | 
			
		||||
  <td id="projectalign" style="padding-left: 0.5em;">
 | 
			
		||||
   <div id="projectname">$projectname
 | 
			
		||||
   <!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
 | 
			
		||||
   </div>
 | 
			
		||||
   <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
 | 
			
		||||
  </td>
 | 
			
		||||
  <!--END PROJECT_NAME-->
 | 
			
		||||
  <!--BEGIN !PROJECT_NAME-->
 | 
			
		||||
   <!--BEGIN PROJECT_BRIEF-->
 | 
			
		||||
    <td style="padding-left: 0.5em;">
 | 
			
		||||
    <div id="projectbrief">$projectbrief</div>
 | 
			
		||||
    </td>
 | 
			
		||||
   <!--END PROJECT_BRIEF-->
 | 
			
		||||
  <!--END !PROJECT_NAME-->
 | 
			
		||||
  <!--BEGIN DISABLE_INDEX-->
 | 
			
		||||
   <!--BEGIN SEARCHENGINE-->
 | 
			
		||||
   <td>$searchbox</td>
 | 
			
		||||
   <!--END SEARCHENGINE-->
 | 
			
		||||
  <!--END DISABLE_INDEX-->
 | 
			
		||||
 </tr>
 | 
			
		||||
 </tbody>
 | 
			
		||||
</table>
 | 
			
		||||
<div id="theme-selection">
 | 
			
		||||
 <label for="theme-select">Theme:</label>
 | 
			
		||||
 <select id="theme-select">
 | 
			
		||||
  <option value="theme-default">Default</option>
 | 
			
		||||
  <option value="theme-round">Round</option>
 | 
			
		||||
  <option value="theme-robot">Robot</option>
 | 
			
		||||
 </select>
 | 
			
		||||
</div>
 | 
			
		||||
</div>
 | 
			
		||||
<!--END TITLEAREA-->
 | 
			
		||||
<!-- end header part -->
 | 
			
		||||
							
								
								
									
										62
									
								
								docs/doxygen-awesome-theme/doxygen-custom/theme-robot.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								docs/doxygen-awesome-theme/doxygen-custom/theme-robot.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
html.theme-robot {
 | 
			
		||||
    /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */
 | 
			
		||||
    --primary-color: #1c89a4;
 | 
			
		||||
    --primary-dark-color: #1a6f84;
 | 
			
		||||
    --primary-light-color: #5abcd4;
 | 
			
		||||
    --primary-lighter-color: #cae1f1;
 | 
			
		||||
    --primary-lightest-color: #e9f1f8;
 | 
			
		||||
 | 
			
		||||
    --fragment-background: #ececec;
 | 
			
		||||
    --code-background: #ececec;
 | 
			
		||||
 | 
			
		||||
    /* page base colors */
 | 
			
		||||
    --page-background-color: white;
 | 
			
		||||
    --page-foreground-color: #2c3e50;
 | 
			
		||||
    --page-secondary-foreground-color: #67727e;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    --border-radius-large: 0px;
 | 
			
		||||
    --border-radius-small: 0px;
 | 
			
		||||
    --border-radius-medium: 0px;
 | 
			
		||||
 | 
			
		||||
    --spacing-small: 3px;
 | 
			
		||||
    --spacing-medium: 6px;
 | 
			
		||||
    --spacing-large: 12px;
 | 
			
		||||
 | 
			
		||||
    --top-height: 125px;
 | 
			
		||||
 | 
			
		||||
    --side-nav-background: var(--page-background-color);
 | 
			
		||||
    --side-nav-foreground: var(--page-foreground-color);
 | 
			
		||||
    --header-foreground: var(--side-nav-foreground);
 | 
			
		||||
    --searchbar-border-radius: var(--border-radius-medium);
 | 
			
		||||
    --header-background: var(--side-nav-background);
 | 
			
		||||
    --header-foreground: var(--side-nav-foreground);
 | 
			
		||||
 | 
			
		||||
    --toc-background: rgb(243, 240, 252);
 | 
			
		||||
    --toc-foreground: var(--page-foreground-color);
 | 
			
		||||
 | 
			
		||||
    --font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
 | 
			
		||||
    --page-font-size: 14px;
 | 
			
		||||
    --box-shadow: none;
 | 
			
		||||
    --separator-color: #cdcdcd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html.theme-robot.dark-mode {
 | 
			
		||||
    color-scheme: dark;
 | 
			
		||||
 | 
			
		||||
    --primary-color: #49cad3;
 | 
			
		||||
    --primary-dark-color: #8ed2d7;
 | 
			
		||||
    --primary-light-color: #377479;
 | 
			
		||||
    --primary-lighter-color: #191e21;
 | 
			
		||||
    --primary-lightest-color: #191a1c;
 | 
			
		||||
 | 
			
		||||
    --fragment-background: #000000;
 | 
			
		||||
    --code-background: #000000;
 | 
			
		||||
 | 
			
		||||
    --page-background-color: #161616;
 | 
			
		||||
    --page-foreground-color: #d2dbde;
 | 
			
		||||
    --page-secondary-foreground-color: #555555;
 | 
			
		||||
    --separator-color: #545454;
 | 
			
		||||
    --toc-background: #20142C;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								docs/doxygen-awesome-theme/doxygen-custom/theme-round.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								docs/doxygen-awesome-theme/doxygen-custom/theme-round.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
html.theme-round {
 | 
			
		||||
    /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */
 | 
			
		||||
    --primary-color: #AF7FE4;
 | 
			
		||||
    --primary-dark-color: #9270E4;
 | 
			
		||||
    --primary-light-color: #d2b7ef;
 | 
			
		||||
    --primary-lighter-color: #cae1f1;
 | 
			
		||||
    --primary-lightest-color: #e9f1f8;
 | 
			
		||||
 | 
			
		||||
    /* page base colors */
 | 
			
		||||
    --page-background-color: white;
 | 
			
		||||
    --page-foreground-color: #2c3e50;
 | 
			
		||||
    --page-secondary-foreground-color: #67727e;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    --border-radius-large: 22px;
 | 
			
		||||
    --border-radius-small: 9px;
 | 
			
		||||
    --border-radius-medium: 14px;
 | 
			
		||||
    --spacing-small: 8px;
 | 
			
		||||
    --spacing-medium: 14px;
 | 
			
		||||
    --spacing-large: 19px;
 | 
			
		||||
    --spacing-xlarge: 21px;
 | 
			
		||||
 | 
			
		||||
    --top-height: 125px;
 | 
			
		||||
 | 
			
		||||
    --side-nav-background: #324067;
 | 
			
		||||
    --side-nav-foreground: #F1FDFF;
 | 
			
		||||
    --header-foreground: var(--side-nav-foreground);
 | 
			
		||||
    --searchbar-background: var(--side-nav-foreground);
 | 
			
		||||
    --searchbar-border-radius: var(--border-radius-medium);
 | 
			
		||||
    --header-background: var(--side-nav-background);
 | 
			
		||||
    --header-foreground: var(--side-nav-foreground);
 | 
			
		||||
 | 
			
		||||
    --toc-background: rgb(243, 240, 252);
 | 
			
		||||
    --toc-foreground: var(--page-foreground-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html.theme-round.dark-mode {
 | 
			
		||||
    color-scheme: dark;
 | 
			
		||||
 | 
			
		||||
    --primary-color: #AF7FE4;
 | 
			
		||||
    --primary-dark-color: #715292;
 | 
			
		||||
    --primary-light-color: #ae97c7;
 | 
			
		||||
    --primary-lighter-color: #191e21;
 | 
			
		||||
    --primary-lightest-color: #191a1c;
 | 
			
		||||
 | 
			
		||||
    --page-background-color: #1C1D1F;
 | 
			
		||||
    --page-foreground-color: #d2dbde;
 | 
			
		||||
    --page-secondary-foreground-color: #859399;
 | 
			
		||||
    --separator-color: #3a3246;
 | 
			
		||||
    --side-nav-background: #171D32;
 | 
			
		||||
    --side-nav-foreground: #F1FDFF;
 | 
			
		||||
    --toc-background: #20142C;
 | 
			
		||||
    --searchbar-background: var(--page-background-color);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,52 @@
 | 
			
		||||
// Toggle zwischen drei Theme-Zuständen und speichere im localStorage
 | 
			
		||||
const THEME_CLASSES = ['theme-default', 'theme-round', 'theme-robot'];
 | 
			
		||||
// Ermögliche das Umschalten per Button/Funktion (z.B. für onclick im HTML)
 | 
			
		||||
function toggleThemeVariant() {
 | 
			
		||||
	let idx = getCurrentThemeIndex();
 | 
			
		||||
	idx = (idx + 1) % THEME_CLASSES.length;
 | 
			
		||||
	applyThemeClass(idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Funktion global verfügbar machen
 | 
			
		||||
window.toggleThemeVariant = toggleThemeVariant;
 | 
			
		||||
 | 
			
		||||
function getCurrentThemeIndex() {
 | 
			
		||||
	const stored = localStorage.getItem('theme-variant');
 | 
			
		||||
	if (stored === null) return 0;
 | 
			
		||||
	const idx = THEME_CLASSES.indexOf(stored);
 | 
			
		||||
	return idx === -1 ? 0 : idx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function applyThemeClass(idx) {
 | 
			
		||||
	document.documentElement.classList.remove(...THEME_CLASSES);
 | 
			
		||||
	if (THEME_CLASSES[idx] && THEME_CLASSES[idx] !== 'theme-default') {
 | 
			
		||||
		document.documentElement.classList.add(THEME_CLASSES[idx]);
 | 
			
		||||
	}
 | 
			
		||||
	localStorage.setItem('theme-variant', THEME_CLASSES[idx] || 'theme-default');
 | 
			
		||||
	// Select synchronisieren, falls vorhanden
 | 
			
		||||
	const select = document.getElementById('theme-select');
 | 
			
		||||
	if (select) select.value = THEME_CLASSES[idx];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setThemeByName(themeName) {
 | 
			
		||||
	const idx = THEME_CLASSES.indexOf(themeName);
 | 
			
		||||
	applyThemeClass(idx === -1 ? 0 : idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
document.addEventListener('DOMContentLoaded', () => {
 | 
			
		||||
	const select = document.getElementById('theme-select');
 | 
			
		||||
	if (select) {
 | 
			
		||||
		// Initialisiere Auswahl aus localStorage
 | 
			
		||||
		const idx = getCurrentThemeIndex();
 | 
			
		||||
		select.value = THEME_CLASSES[idx];
 | 
			
		||||
		applyThemeClass(idx);
 | 
			
		||||
		// Theme bei Auswahl ändern
 | 
			
		||||
		select.addEventListener('change', e => {
 | 
			
		||||
			setThemeByName(e.target.value);
 | 
			
		||||
		});
 | 
			
		||||
	} else {
 | 
			
		||||
		// Fallback: Theme trotzdem setzen
 | 
			
		||||
		applyThemeClass(getCurrentThemeIndex());
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
@@ -1,82 +0,0 @@
 | 
			
		||||
<!-- HTML header for doxygen 1.9.7-->
 | 
			
		||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 | 
			
		||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="$langISO">
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
 | 
			
		||||
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
 | 
			
		||||
<meta name="generator" content="Doxygen $doxygenversion"/>
 | 
			
		||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
 | 
			
		||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
 | 
			
		||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
 | 
			
		||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
 | 
			
		||||
<!--BEGIN DISABLE_INDEX-->
 | 
			
		||||
  <!--BEGIN FULL_SIDEBAR-->
 | 
			
		||||
<script type="text/javascript">var page_layout=1;</script>
 | 
			
		||||
  <!--END FULL_SIDEBAR-->
 | 
			
		||||
<!--END DISABLE_INDEX-->
 | 
			
		||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
 | 
			
		||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
 | 
			
		||||
$treeview
 | 
			
		||||
$search
 | 
			
		||||
$mathjax
 | 
			
		||||
$darkmode
 | 
			
		||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
 | 
			
		||||
$extrastylesheet
 | 
			
		||||
<script type="text/javascript" src="$relpath^doxygen-awesome-darkmode-toggle.js"></script>
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
  DoxygenAwesomeDarkModeToggle.init()
 | 
			
		||||
</script>
 | 
			
		||||
<script type="text/javascript" src="$relpath^doxygen-awesome-interactive-toc.js"></script>
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
  DoxygenAwesomeInteractiveToc.init()
 | 
			
		||||
</script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<!--BEGIN DISABLE_INDEX-->
 | 
			
		||||
  <!--BEGIN FULL_SIDEBAR-->
 | 
			
		||||
<div id="side-nav" class="ui-resizable side-nav-resizable"><!-- do not remove this div, it is closed by doxygen! -->
 | 
			
		||||
  <!--END FULL_SIDEBAR-->
 | 
			
		||||
<!--END DISABLE_INDEX-->
 | 
			
		||||
 | 
			
		||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
 | 
			
		||||
 | 
			
		||||
<!--BEGIN TITLEAREA-->
 | 
			
		||||
<div id="titlearea">
 | 
			
		||||
<table cellspacing="0" cellpadding="0">
 | 
			
		||||
 <tbody>
 | 
			
		||||
 <tr id="projectrow">
 | 
			
		||||
  <!--BEGIN PROJECT_LOGO-->
 | 
			
		||||
  <td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
 | 
			
		||||
  <!--END PROJECT_LOGO-->
 | 
			
		||||
  <!--BEGIN PROJECT_NAME-->
 | 
			
		||||
  <td id="projectalign">
 | 
			
		||||
   <div id="projectname">$projectname<!--BEGIN PROJECT_NUMBER--><span id="projectnumber"> $projectnumber</span><!--END PROJECT_NUMBER-->
 | 
			
		||||
   </div>
 | 
			
		||||
   <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
 | 
			
		||||
  </td>
 | 
			
		||||
  <!--END PROJECT_NAME-->
 | 
			
		||||
  <!--BEGIN !PROJECT_NAME-->
 | 
			
		||||
   <!--BEGIN PROJECT_BRIEF-->
 | 
			
		||||
    <td>
 | 
			
		||||
    <div id="projectbrief">$projectbrief</div>
 | 
			
		||||
    </td>
 | 
			
		||||
   <!--END PROJECT_BRIEF-->
 | 
			
		||||
  <!--END !PROJECT_NAME-->
 | 
			
		||||
  <!--BEGIN DISABLE_INDEX-->
 | 
			
		||||
   <!--BEGIN SEARCHENGINE-->
 | 
			
		||||
     <!--BEGIN !FULL_SIDEBAR-->
 | 
			
		||||
    <td>$searchbox</td>
 | 
			
		||||
     <!--END !FULL_SIDEBAR-->
 | 
			
		||||
   <!--END SEARCHENGINE-->
 | 
			
		||||
  <!--END DISABLE_INDEX-->
 | 
			
		||||
 </tr>
 | 
			
		||||
  <!--BEGIN SEARCHENGINE-->
 | 
			
		||||
   <!--BEGIN FULL_SIDEBAR-->
 | 
			
		||||
   <tr><td colspan="2">$searchbox</td></tr>
 | 
			
		||||
   <!--END FULL_SIDEBAR-->
 | 
			
		||||
  <!--END SEARCHENGINE-->
 | 
			
		||||
 </tbody>
 | 
			
		||||
</table>
 | 
			
		||||
</div>
 | 
			
		||||
<!--END TITLEAREA-->
 | 
			
		||||
<!-- end header part -->
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
  "etl_sources": [
 | 
			
		||||
    {
 | 
			
		||||
      "ip": "127.0.0.1",
 | 
			
		||||
      "ws_port": "6005",
 | 
			
		||||
      "ws_port": "6006",
 | 
			
		||||
      "grpc_port": "50051"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
@@ -76,38 +76,60 @@
 | 
			
		||||
    "parallel_requests_limit": 10, // Optional parameter, used only if "processing_strategy" is "parallel". It limits the number of requests for one client connection processed in parallel. Infinite if not specified.
 | 
			
		||||
    // Max number of responses to queue up before sent successfully. If a client's waiting queue is too long, the server will close the connection.
 | 
			
		||||
    "ws_max_sending_queue_size": 1500,
 | 
			
		||||
    "__ng_web_server": false // Use ng web server. This is a temporary setting which will be deleted after switching to ng web server
 | 
			
		||||
    "__ng_web_server": false, // Use ng web server. This is a temporary setting which will be deleted after switching to ng web server
 | 
			
		||||
    "proxy": {
 | 
			
		||||
      "ips": [],
 | 
			
		||||
      "tokens": []
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  // Time in seconds for graceful shutdown. Defaults to 10 seconds. Not fully implemented yet.
 | 
			
		||||
  "graceful_period": 10.0,
 | 
			
		||||
  // Overrides log level on a per logging channel.
 | 
			
		||||
  // Defaults to global "log_level" for each unspecified channel.
 | 
			
		||||
  "log_channels": [
 | 
			
		||||
    {
 | 
			
		||||
      "channel": "Backend",
 | 
			
		||||
      "log_level": "fatal"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "channel": "WebServer",
 | 
			
		||||
      "log_level": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "channel": "Subscriptions",
 | 
			
		||||
      "log_level": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "channel": "RPC",
 | 
			
		||||
      "log_level": "error"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "channel": "ETL",
 | 
			
		||||
      "log_level": "debug"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "channel": "Performance",
 | 
			
		||||
      "log_level": "trace"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "log": {
 | 
			
		||||
    // Overrides log level on a per logging channel.
 | 
			
		||||
    // Defaults to global "log.level" for each unspecified channel.
 | 
			
		||||
    "channels": [
 | 
			
		||||
      {
 | 
			
		||||
        "channel": "Backend",
 | 
			
		||||
        "level": "fatal"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "channel": "WebServer",
 | 
			
		||||
        "level": "info"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "channel": "Subscriptions",
 | 
			
		||||
        "level": "info"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "channel": "RPC",
 | 
			
		||||
        "level": "error"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "channel": "ETL",
 | 
			
		||||
        "level": "debug"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "channel": "Performance",
 | 
			
		||||
        "level": "trace"
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
    // The general logging level of Clio. This level is applied to all log channels that do not have an explicitly defined logging level.
 | 
			
		||||
    "level": "info",
 | 
			
		||||
    // Log format using spdlog format patterns (this is the default format)
 | 
			
		||||
    "format": "%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v",
 | 
			
		||||
    // Whether spdlog is asynchronous or not.
 | 
			
		||||
    "is_async": true,
 | 
			
		||||
    // Enables or disables logging to the console.
 | 
			
		||||
    "enable_console": true,
 | 
			
		||||
    // Clio logs to file in the specified directory only if "log.directory" is set
 | 
			
		||||
    // "directory": "./clio_log",
 | 
			
		||||
    // The log rotation size in megabytes. When the log file reaches this particular size, a new log file starts.
 | 
			
		||||
    "rotation_size": 2048,
 | 
			
		||||
    // The maximum number of log files in the directory.
 | 
			
		||||
    "directory_max_files": 25,
 | 
			
		||||
    // Log tags style to use
 | 
			
		||||
    "tag_style": "uint"
 | 
			
		||||
  },
 | 
			
		||||
  "cache": {
 | 
			
		||||
    // Configure this to use either "num_diffs", "num_cursors_from_diff", or "num_cursors_from_account". By default, Clio uses "num_diffs".
 | 
			
		||||
    "num_diffs": 32, // Generate the cursors from the latest ledger diff, then use the cursors to partition the ledger to load concurrently. The cursors number is affected by the busyness of the network.
 | 
			
		||||
@@ -121,16 +143,6 @@
 | 
			
		||||
    "enabled": true,
 | 
			
		||||
    "compress_reply": true
 | 
			
		||||
  },
 | 
			
		||||
  "log_level": "info",
 | 
			
		||||
  // Log format (this is the default format)
 | 
			
		||||
  "log_format": "%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% %Message%",
 | 
			
		||||
  "log_to_console": true,
 | 
			
		||||
  // Clio logs to file in the specified directory only if "log_directory" is set
 | 
			
		||||
  // "log_directory": "./clio_log",
 | 
			
		||||
  "log_rotation_size": 2048,
 | 
			
		||||
  "log_directory_max_size": 51200,
 | 
			
		||||
  "log_rotation_hour_interval": 12,
 | 
			
		||||
  "log_tag_style": "uint",
 | 
			
		||||
  "extractor_threads": 8,
 | 
			
		||||
  "read_only": false,
 | 
			
		||||
  // "start_sequence": [integer] the ledger index to start from,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								docs/github-corner-disable.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docs/github-corner-disable.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
.github-corner {
 | 
			
		||||
  display: none !important;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,76 +0,0 @@
 | 
			
		||||
# Logging
 | 
			
		||||
 | 
			
		||||
Clio provides several logging options, which all are configurable via the config file. These are detailed in the following sections.
 | 
			
		||||
 | 
			
		||||
## `log_level`
 | 
			
		||||
 | 
			
		||||
The minimum level of severity at which the log message will be outputted by default. Severity options are `trace`, `debug`, `info`, `warning`, `error`, `fatal`. Defaults to `info`.
 | 
			
		||||
 | 
			
		||||
## `log_format`
 | 
			
		||||
 | 
			
		||||
The format of log lines produced by Clio. Defaults to `"%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% %Message%"`.
 | 
			
		||||
 | 
			
		||||
Each of the variables expands like so:
 | 
			
		||||
 | 
			
		||||
- `TimeStamp`: The full date and time of the log entry
 | 
			
		||||
- `SourceLocation`: A partial path to the c++ file and the line number in said file (`source/file/path:linenumber`)
 | 
			
		||||
- `ThreadID`: The ID of the thread the log entry is written from
 | 
			
		||||
- `Channel`: The channel that this log entry was sent to
 | 
			
		||||
- `Severity`: The severity (aka log level) the entry was sent at
 | 
			
		||||
- `Message`: The actual log message
 | 
			
		||||
 | 
			
		||||
## `log_channels`
 | 
			
		||||
 | 
			
		||||
An array of JSON objects, each overriding properties for a logging `channel`.
 | 
			
		||||
 | 
			
		||||
> [!IMPORTANT]
 | 
			
		||||
> At the time of writing, only `log_level` can be overridden using this mechanism.
 | 
			
		||||
 | 
			
		||||
Each object is of this format:
 | 
			
		||||
 | 
			
		||||
```json
 | 
			
		||||
{
 | 
			
		||||
  "channel": "Backend",
 | 
			
		||||
  "log_level": "fatal"
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If no override is present for a given channel, that channel will log at the severity specified by the global `log_level`.
 | 
			
		||||
 | 
			
		||||
The log channels that can be overridden are: `Backend`, `WebServer`, `Subscriptions`, `RPC`, `ETL` and `Performance`.
 | 
			
		||||
 | 
			
		||||
> [!NOTE]
 | 
			
		||||
> See [example-config.json](../docs/examples/config/example-config.json) for more details.
 | 
			
		||||
 | 
			
		||||
## `log_to_console`
 | 
			
		||||
 | 
			
		||||
Enable or disable log output to console. Options are `true`/`false`. This option defaults to `true`.
 | 
			
		||||
 | 
			
		||||
## `log_directory`
 | 
			
		||||
 | 
			
		||||
Path to the directory where log files are stored. If such directory doesn't exist, Clio will create it.
 | 
			
		||||
 | 
			
		||||
If the option is not specified, the logs are not written to a file.
 | 
			
		||||
 | 
			
		||||
## `log_rotation_size`
 | 
			
		||||
 | 
			
		||||
The max size of the log file in **megabytes** before it will rotate into a smaller file. Defaults to 2GB.
 | 
			
		||||
 | 
			
		||||
## `log_directory_max_size`
 | 
			
		||||
 | 
			
		||||
The max size of the log directory in **megabytes** before old log files will be deleted to free up space. Defaults to 50GB.
 | 
			
		||||
 | 
			
		||||
## `log_rotation_hour_interval`
 | 
			
		||||
 | 
			
		||||
The time interval in **hours** after the last log rotation to automatically rotate the current log file. Defaults to 12 hours.
 | 
			
		||||
 | 
			
		||||
> [!NOTE]
 | 
			
		||||
> Log rotation based on time occurs in conjunction with size-based log rotation. For example, if a size-based log rotation occurs, the timer for the time-based rotation will reset.
 | 
			
		||||
 | 
			
		||||
## `log_tag_style`
 | 
			
		||||
 | 
			
		||||
Tag implementation to use. Must be one of:
 | 
			
		||||
 | 
			
		||||
- `uint`: Lock free and threadsafe but outputs just a simple unsigned integer
 | 
			
		||||
- `uuid`: Threadsafe and outputs a UUID tag
 | 
			
		||||
- `none`: Doesn't use tagging at all
 | 
			
		||||
@@ -77,7 +77,7 @@ It's possible to configure `minimum`, `maximum` and `default` version like so:
 | 
			
		||||
 | 
			
		||||
All of the above are optional.
 | 
			
		||||
 | 
			
		||||
Clio will fallback to hardcoded defaults when these values are not specified in the config file, or if the configured values are outside of the minimum and maximum supported versions hardcoded in [src/rpc/common/APIVersion.h](../src/rpc/common/APIVersion.hpp).
 | 
			
		||||
Clio will fallback to hardcoded defaults when these values are not specified in the config file, or if the configured values are outside of the minimum and maximum supported versions hardcoded in [src/rpc/common/APIVersion.hpp](../src/rpc/common/APIVersion.hpp).
 | 
			
		||||
 | 
			
		||||
> [!TIP]
 | 
			
		||||
> See the [example-config.json](../docs/examples/config/example-config.json) for more details.
 | 
			
		||||
 
 | 
			
		||||
@@ -36,19 +36,19 @@ EOF
 | 
			
		||||
    exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Check version of doxygen is at least 1.12
 | 
			
		||||
# Check version of doxygen is at least 1.14
 | 
			
		||||
version=$($DOXYGEN --version | grep -o '[0-9\.]*')
 | 
			
		||||
 | 
			
		||||
if [[ "1.12.0" > "$version" ]]; then
 | 
			
		||||
if [[ "1.14.0" > "$version" ]]; then
 | 
			
		||||
    # No hard error if doxygen version is not the one we want - let CI deal with it
 | 
			
		||||
    cat <<EOF
 | 
			
		||||
 | 
			
		||||
                                    ERROR
 | 
			
		||||
-----------------------------------------------------------------------------
 | 
			
		||||
        A minimum of version 1.12 of `which doxygen` is required.
 | 
			
		||||
        Your version is $version. Please upgrade it for next time.
 | 
			
		||||
        A minimum of version 1.14 of `which doxygen` is required.
 | 
			
		||||
        Your version is $version. Please upgrade it.
 | 
			
		||||
 | 
			
		||||
        Your changes may fail to pass CI once pushed.
 | 
			
		||||
        Your changes may fail CI checks.
 | 
			
		||||
-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
EOF
 | 
			
		||||
 
 | 
			
		||||
@@ -5,11 +5,14 @@ import re
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PATTERN = r'R"JSON\((.*?)\)JSON"'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def use_uppercase(cpp_content: str) -> str:
 | 
			
		||||
    return cpp_content.replace('R"json(', 'R"JSON(').replace(')json"', ')JSON"')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fix_json_style(cpp_content: str) -> str:
 | 
			
		||||
    cpp_content = cpp_content.replace('R"json(', 'R"JSON(').replace(')json"', ')JSON"')
 | 
			
		||||
 | 
			
		||||
    pattern = r'R"JSON\((.*?)\)JSON"'
 | 
			
		||||
 | 
			
		||||
    def replace_json(match):
 | 
			
		||||
        raw_json = match.group(1)
 | 
			
		||||
 | 
			
		||||
@@ -29,12 +32,51 @@ def fix_json_style(cpp_content: str) -> str:
 | 
			
		||||
            raw_json = raw_json.replace(f'":{digit}', f'": {digit}')
 | 
			
		||||
        return f'R"JSON({raw_json})JSON"'
 | 
			
		||||
 | 
			
		||||
    return re.sub(pattern, replace_json, cpp_content, flags=re.DOTALL)
 | 
			
		||||
    return re.sub(PATTERN, replace_json, cpp_content, flags=re.DOTALL)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fix_colon_spacing(cpp_content: str) -> str:
 | 
			
		||||
    def replace_json(match):
 | 
			
		||||
        raw_json = match.group(1)
 | 
			
		||||
        raw_json = re.sub(r'":\n\s*(\[|\{)', r'": \1', raw_json)
 | 
			
		||||
        return f'R"JSON({raw_json})JSON"'
 | 
			
		||||
    return re.sub(PATTERN, replace_json, cpp_content, flags=re.DOTALL)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fix_indentation(cpp_content: str) -> str:
 | 
			
		||||
    lines = cpp_content.splitlines()
 | 
			
		||||
 | 
			
		||||
    def find_indentation(line: str) -> int:
 | 
			
		||||
        return len(line) - len(line.lstrip())
 | 
			
		||||
 | 
			
		||||
    for (line_num, (line, next_line)) in enumerate(zip(lines[:-1], lines[1:])):
 | 
			
		||||
        if "JSON(" in line and ")JSON" not in line:
 | 
			
		||||
            indent = find_indentation(line)
 | 
			
		||||
            next_indent = find_indentation(next_line)
 | 
			
		||||
 | 
			
		||||
            by_how_much = next_indent - (indent + 4)
 | 
			
		||||
            if by_how_much != 0:
 | 
			
		||||
                print(
 | 
			
		||||
                    f"Indentation error at line: {line_num + 2}: expected {indent + 4} spaces, found {next_indent} spaces"
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                for i in range(line_num + 1, len(lines)):
 | 
			
		||||
                    if ")JSON" in lines[i]:
 | 
			
		||||
                        lines[i] = " " * indent + lines[i].lstrip()
 | 
			
		||||
                        break
 | 
			
		||||
                    lines[i] = lines[i][by_how_much:] if by_how_much > 0 else " " * (-by_how_much) + lines[i]
 | 
			
		||||
 | 
			
		||||
    return "\n".join(lines) + "\n"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def process_file(file_path: Path, dry_run: bool) -> bool:
 | 
			
		||||
    content = file_path.read_text(encoding="utf-8")
 | 
			
		||||
    new_content = fix_json_style(content)
 | 
			
		||||
 | 
			
		||||
    new_content = content
 | 
			
		||||
    new_content = use_uppercase(new_content)
 | 
			
		||||
    new_content = fix_json_style(new_content)
 | 
			
		||||
    new_content = fix_colon_spacing(new_content)
 | 
			
		||||
    new_content = fix_indentation(new_content)
 | 
			
		||||
 | 
			
		||||
    if new_content != content:
 | 
			
		||||
        print(f"Processing file: {file_path}")
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								src/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
# Clio API server
 | 
			
		||||
 | 
			
		||||
## Introduction
 | 
			
		||||
 | 
			
		||||
Clio is an XRP Ledger API server optimized for RPC calls over WebSocket or JSON-RPC.
 | 
			
		||||
 | 
			
		||||
It stores validated historical ledger and transaction data in a more space efficient format, and uses up to 4 times
 | 
			
		||||
less space than [rippled](https://github.com/XRPLF/rippled).
 | 
			
		||||
 | 
			
		||||
Clio can be configured to store data in [Apache Cassandra](https://cassandra.apache.org/_/index.html) or
 | 
			
		||||
[ScyllaDB](https://www.scylladb.com/), enabling scalable read throughput. Multiple Clio nodes can share
 | 
			
		||||
access to the same dataset, which allows for a highly available cluster of Clio nodes without the need for redundant
 | 
			
		||||
data storage or computation.
 | 
			
		||||
 | 
			
		||||
## Develop
 | 
			
		||||
 | 
			
		||||
As you prepare to develop code for Clio, please be sure you are aware of our current
 | 
			
		||||
[Contribution guidelines](https://github.com/XRPLF/clio/blob/develop/CONTRIBUTING.md).
 | 
			
		||||
 | 
			
		||||
Read about @ref "rpc" carefully to know more about writing your own handlers for Clio.
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
#include "util/build/Build.hpp"
 | 
			
		||||
#include "util/config/ConfigDescription.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/program_options/errors.hpp>
 | 
			
		||||
#include <boost/program_options/options_description.hpp>
 | 
			
		||||
#include <boost/program_options/parsers.hpp>
 | 
			
		||||
#include <boost/program_options/positional_options.hpp>
 | 
			
		||||
@@ -56,12 +57,22 @@ CliArgs::parse(int argc, char const* argv[])
 | 
			
		||||
    po::positional_options_description positional;
 | 
			
		||||
    positional.add("conf", 1);
 | 
			
		||||
 | 
			
		||||
    auto const printHelp = [&description]() {
 | 
			
		||||
        std::cout << "Clio server " << util::build::getClioFullVersionString() << "\n\n" << description;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    po::variables_map parsed;
 | 
			
		||||
    po::store(po::command_line_parser(argc, argv).options(description).positional(positional).run(), parsed);
 | 
			
		||||
    po::notify(parsed);
 | 
			
		||||
    try {
 | 
			
		||||
        po::store(po::command_line_parser(argc, argv).options(description).positional(positional).run(), parsed);
 | 
			
		||||
        po::notify(parsed);
 | 
			
		||||
    } catch (po::error const& e) {
 | 
			
		||||
        std::cerr << "Error: " << e.what() << std::endl << std::endl;
 | 
			
		||||
        printHelp();
 | 
			
		||||
        return Action{Action::Exit{EXIT_FAILURE}};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (parsed.contains("help")) {
 | 
			
		||||
        std::cout << "Clio server " << util::build::getClioFullVersionString() << "\n\n" << description;
 | 
			
		||||
        printHelp();
 | 
			
		||||
        return Action{Action::Exit{EXIT_SUCCESS}};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -178,7 +178,9 @@ ClioApplication::run(bool const useNgWebServer)
 | 
			
		||||
        }
 | 
			
		||||
        auto const adminVerifier = std::move(expectedAdminVerifier).value();
 | 
			
		||||
 | 
			
		||||
        auto httpServer = web::ng::makeServer(config_, OnConnectCheck{dosGuard}, DisconnectHook{dosGuard}, ioc);
 | 
			
		||||
        auto httpServer = web::ng::makeServer(
 | 
			
		||||
            config_, OnConnectCheck{dosGuard}, IpChangeHook{dosGuard}, DisconnectHook{dosGuard}, ioc
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (not httpServer.has_value()) {
 | 
			
		||||
            LOG(util::LogService::error()) << "Error creating web server: " << httpServer.error();
 | 
			
		||||
@@ -187,6 +189,7 @@ ClioApplication::run(bool const useNgWebServer)
 | 
			
		||||
 | 
			
		||||
        httpServer->onGet("/metrics", MetricsHandler{adminVerifier});
 | 
			
		||||
        httpServer->onGet("/health", HealthCheckHandler{});
 | 
			
		||||
        httpServer->onGet("/cache_state", CacheStateHandler{cache});
 | 
			
		||||
        auto requestHandler = RequestHandler{adminVerifier, handler};
 | 
			
		||||
        httpServer->onPost("/", requestHandler);
 | 
			
		||||
        httpServer->onWs(std::move(requestHandler));
 | 
			
		||||
@@ -212,7 +215,7 @@ ClioApplication::run(bool const useNgWebServer)
 | 
			
		||||
    // Init the web server
 | 
			
		||||
    auto handler = std::make_shared<web::RPCServerHandler<RPCEngineType>>(config_, backend, rpcEngine, etl, dosGuard);
 | 
			
		||||
 | 
			
		||||
    auto const httpServer = web::makeHttpServer(config_, ioc, dosGuard, handler);
 | 
			
		||||
    auto const httpServer = web::makeHttpServer(config_, ioc, dosGuard, handler, cache);
 | 
			
		||||
 | 
			
		||||
    // Blocks until stopped.
 | 
			
		||||
    // When stopped, shared_ptrs fall out of scope
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,8 @@
 | 
			
		||||
 | 
			
		||||
#include "app/Stopper.hpp"
 | 
			
		||||
 | 
			
		||||
#include "util/Spawn.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/asio/spawn.hpp>
 | 
			
		||||
 | 
			
		||||
#include <functional>
 | 
			
		||||
@@ -36,7 +38,7 @@ Stopper::~Stopper()
 | 
			
		||||
void
 | 
			
		||||
Stopper::setOnStop(std::function<void(boost::asio::yield_context)> cb)
 | 
			
		||||
{
 | 
			
		||||
    boost::asio::spawn(ctx_, std::move(cb));
 | 
			
		||||
    util::spawn(ctx_, std::move(cb));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
@@ -108,6 +108,8 @@ public:
 | 
			
		||||
 | 
			
		||||
            ioc.stop();
 | 
			
		||||
            LOG(util::LogService::info()) << "io_context stopped";
 | 
			
		||||
 | 
			
		||||
            util::LogService::shutdown();
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ parseConfig(std::string_view configPath)
 | 
			
		||||
        std::cerr << "Error parsing json from config: " << configPath << "\n" << json.error().error << std::endl;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    auto const errors = gClioConfig.parse(json.value());
 | 
			
		||||
    auto const errors = getClioConfig().parse(json.value());
 | 
			
		||||
    if (errors.has_value()) {
 | 
			
		||||
        for (auto const& err : errors.value()) {
 | 
			
		||||
            std::cerr << "Issues found in provided config '" << configPath << "':\n";
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace app {
 | 
			
		||||
@@ -54,6 +55,17 @@ OnConnectCheck::operator()(web::ng::Connection const& connection)
 | 
			
		||||
    return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IpChangeHook::IpChangeHook(web::dosguard::DOSGuardInterface& dosguard) : dosguard_(dosguard)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
IpChangeHook::operator()(std::string const& oldIp, std::string const& newIp)
 | 
			
		||||
{
 | 
			
		||||
    dosguard_.get().decrement(oldIp);
 | 
			
		||||
    dosguard_.get().increment(newIp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DisconnectHook::DisconnectHook(web::dosguard::DOSGuardInterface& dosguard) : dosguard_{dosguard}
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
@@ -108,4 +120,34 @@ HealthCheckHandler::operator()(
 | 
			
		||||
    return web::ng::Response{boost::beast::http::status::ok, kHEALTH_CHECK_HTML, request};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
web::ng::Response
 | 
			
		||||
CacheStateHandler::operator()(
 | 
			
		||||
    web::ng::Request const& request,
 | 
			
		||||
    web::ng::ConnectionMetadata&,
 | 
			
		||||
    web::SubscriptionContextPtr,
 | 
			
		||||
    boost::asio::yield_context
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    static constexpr auto kCACHE_CHECK_LOADED_HTML = R"html(
 | 
			
		||||
    <!DOCTYPE html>
 | 
			
		||||
    <html>
 | 
			
		||||
        <head><title>Cache state</title></head>
 | 
			
		||||
        <body><h1>Cache state</h1><p>Cache is fully loaded</p></body>
 | 
			
		||||
    </html>
 | 
			
		||||
)html";
 | 
			
		||||
 | 
			
		||||
    static constexpr auto kCACHE_CHECK_NOT_LOADED_HTML = R"html(
 | 
			
		||||
    <!DOCTYPE html>
 | 
			
		||||
    <html>
 | 
			
		||||
        <head><title>Cache state</title></head>
 | 
			
		||||
        <body><h1>Cache state</h1><p>Cache is not yet loaded</p></body>
 | 
			
		||||
    </html>
 | 
			
		||||
)html";
 | 
			
		||||
 | 
			
		||||
    if (cache_.get().isFull())
 | 
			
		||||
        return web::ng::Response{boost::beast::http::status::ok, kCACHE_CHECK_LOADED_HTML, request};
 | 
			
		||||
 | 
			
		||||
    return web::ng::Response{boost::beast::http::status::service_unavailable, kCACHE_CHECK_NOT_LOADED_HTML, request};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace app
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "data/LedgerCacheInterface.hpp"
 | 
			
		||||
#include "rpc/Errors.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
#include "web/AdminVerificationStrategy.hpp"
 | 
			
		||||
@@ -36,6 +37,7 @@
 | 
			
		||||
#include <exception>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace app {
 | 
			
		||||
@@ -64,6 +66,31 @@ public:
 | 
			
		||||
    operator()(web::ng::Connection const& connection);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief A function object that is called when the IP of a connection changes (usually if proxy detected).
 | 
			
		||||
 * This is used to update the DOS guard.
 | 
			
		||||
 */
 | 
			
		||||
class IpChangeHook {
 | 
			
		||||
    std::reference_wrapper<web::dosguard::DOSGuardInterface> dosguard_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief Construct a new IpChangeHook object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param dosguard The DOS guard to use.
 | 
			
		||||
     */
 | 
			
		||||
    IpChangeHook(web::dosguard::DOSGuardInterface& dosguard);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief The call of the function object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param oldIp The old IP of the connection.
 | 
			
		||||
     * @param newIp The new IP of the connection.
 | 
			
		||||
     */
 | 
			
		||||
    void
 | 
			
		||||
    operator()(std::string const& oldIp, std::string const& newIp);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief A function object to be called when a connection is disconnected.
 | 
			
		||||
 */
 | 
			
		||||
@@ -137,6 +164,37 @@ public:
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief A function object that handles the cache state check endpoint.
 | 
			
		||||
 */
 | 
			
		||||
class CacheStateHandler {
 | 
			
		||||
    std::reference_wrapper<data::LedgerCacheInterface const> cache_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief Construct a new CacheStateHandler object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cache The ledger cache to use.
 | 
			
		||||
     */
 | 
			
		||||
    CacheStateHandler(data::LedgerCacheInterface const& cache) : cache_{cache}
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief The call of the function object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param request The request to handle.
 | 
			
		||||
     * @return The response to the request
 | 
			
		||||
     */
 | 
			
		||||
    web::ng::Response
 | 
			
		||||
    operator()(
 | 
			
		||||
        web::ng::Request const& request,
 | 
			
		||||
        web::ng::ConnectionMetadata&,
 | 
			
		||||
        web::SubscriptionContextPtr,
 | 
			
		||||
        boost::asio::yield_context
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief A function object that handles the websocket endpoint.
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -21,10 +21,16 @@
 | 
			
		||||
 | 
			
		||||
#include "cluster/ClioNode.hpp"
 | 
			
		||||
#include "data/BackendInterface.hpp"
 | 
			
		||||
#include "util/Assert.hpp"
 | 
			
		||||
#include "util/Spawn.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/asio/bind_cancellation_slot.hpp>
 | 
			
		||||
#include <boost/asio/cancellation_type.hpp>
 | 
			
		||||
#include <boost/asio/error.hpp>
 | 
			
		||||
#include <boost/asio/spawn.hpp>
 | 
			
		||||
#include <boost/asio/steady_timer.hpp>
 | 
			
		||||
#include <boost/asio/use_future.hpp>
 | 
			
		||||
#include <boost/json/parse.hpp>
 | 
			
		||||
#include <boost/json/serialize.hpp>
 | 
			
		||||
#include <boost/json/value.hpp>
 | 
			
		||||
@@ -35,11 +41,16 @@
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include <latch>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
constexpr auto kTOTAL_WORKERS = 2uz;  // 1 reading and 1 writing worker (coroutines)
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
namespace cluster {
 | 
			
		||||
 | 
			
		||||
ClusterCommunicationService::ClusterCommunicationService(
 | 
			
		||||
@@ -50,6 +61,7 @@ ClusterCommunicationService::ClusterCommunicationService(
 | 
			
		||||
    : backend_(std::move(backend))
 | 
			
		||||
    , readInterval_(readInterval)
 | 
			
		||||
    , writeInterval_(writeInterval)
 | 
			
		||||
    , finishedCountdown_(kTOTAL_WORKERS)
 | 
			
		||||
    , selfData_{ClioNode{
 | 
			
		||||
          .uuid = std::make_shared<boost::uuids::uuid>(boost::uuids::random_generator{}()),
 | 
			
		||||
          .updateTime = std::chrono::system_clock::time_point{}
 | 
			
		||||
@@ -62,22 +74,42 @@ ClusterCommunicationService::ClusterCommunicationService(
 | 
			
		||||
void
 | 
			
		||||
ClusterCommunicationService::run()
 | 
			
		||||
{
 | 
			
		||||
    boost::asio::spawn(strand_, [this](boost::asio::yield_context yield) {
 | 
			
		||||
    ASSERT(not running_ and not stopped_, "Can only be ran once");
 | 
			
		||||
    running_ = true;
 | 
			
		||||
 | 
			
		||||
    util::spawn(strand_, [this](boost::asio::yield_context yield) {
 | 
			
		||||
        boost::asio::steady_timer timer(yield.get_executor());
 | 
			
		||||
        while (true) {
 | 
			
		||||
        boost::system::error_code ec;
 | 
			
		||||
 | 
			
		||||
        while (running_) {
 | 
			
		||||
            timer.expires_after(readInterval_);
 | 
			
		||||
            timer.async_wait(yield);
 | 
			
		||||
            auto token = cancelSignal_.slot();
 | 
			
		||||
            timer.async_wait(boost::asio::bind_cancellation_slot(token, yield[ec]));
 | 
			
		||||
 | 
			
		||||
            if (ec == boost::asio::error::operation_aborted or not running_)
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            doRead(yield);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        finishedCountdown_.count_down(1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    boost::asio::spawn(strand_, [this](boost::asio::yield_context yield) {
 | 
			
		||||
    util::spawn(strand_, [this](boost::asio::yield_context yield) {
 | 
			
		||||
        boost::asio::steady_timer timer(yield.get_executor());
 | 
			
		||||
        while (true) {
 | 
			
		||||
        boost::system::error_code ec;
 | 
			
		||||
 | 
			
		||||
        while (running_) {
 | 
			
		||||
            doWrite();
 | 
			
		||||
            timer.expires_after(writeInterval_);
 | 
			
		||||
            timer.async_wait(yield);
 | 
			
		||||
            auto token = cancelSignal_.slot();
 | 
			
		||||
            timer.async_wait(boost::asio::bind_cancellation_slot(token, yield[ec]));
 | 
			
		||||
 | 
			
		||||
            if (ec == boost::asio::error::operation_aborted or not running_)
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        finishedCountdown_.count_down(1);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -92,9 +124,19 @@ ClusterCommunicationService::stop()
 | 
			
		||||
    if (stopped_)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    ctx_.stop();
 | 
			
		||||
    ctx_.join();
 | 
			
		||||
    stopped_ = true;
 | 
			
		||||
 | 
			
		||||
    // for ASAN to see through concurrency correctly we need to exit all coroutines before joining the ctx
 | 
			
		||||
    running_ = false;
 | 
			
		||||
 | 
			
		||||
    // cancelSignal_ is not thread safe so we execute emit on the same strand
 | 
			
		||||
    boost::asio::spawn(
 | 
			
		||||
        strand_, [this](auto&&) { cancelSignal_.emit(boost::asio::cancellation_type::all); }, boost::asio::use_future
 | 
			
		||||
    )
 | 
			
		||||
        .wait();
 | 
			
		||||
    finishedCountdown_.wait();
 | 
			
		||||
 | 
			
		||||
    ctx_.join();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<boost::uuids::uuid>
 | 
			
		||||
@@ -108,7 +150,7 @@ ClioNode
 | 
			
		||||
ClusterCommunicationService::selfData() const
 | 
			
		||||
{
 | 
			
		||||
    ClioNode result{};
 | 
			
		||||
    boost::asio::spawn(strand_, [this, &result](boost::asio::yield_context) { result = selfData_; });
 | 
			
		||||
    util::spawn(strand_, [this, &result](boost::asio::yield_context) { result = selfData_; });
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -119,7 +161,7 @@ ClusterCommunicationService::clusterData() const
 | 
			
		||||
        return std::unexpected{"Service is not healthy"};
 | 
			
		||||
    }
 | 
			
		||||
    std::vector<ClioNode> result;
 | 
			
		||||
    boost::asio::spawn(strand_, [this, &result](boost::asio::yield_context) {
 | 
			
		||||
    util::spawn(strand_, [this, &result](boost::asio::yield_context) {
 | 
			
		||||
        result = otherNodesData_;
 | 
			
		||||
        result.push_back(selfData_);
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -27,12 +27,15 @@
 | 
			
		||||
#include "util/prometheus/Gauge.hpp"
 | 
			
		||||
#include "util/prometheus/Prometheus.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/asio/cancellation_signal.hpp>
 | 
			
		||||
#include <boost/asio/spawn.hpp>
 | 
			
		||||
#include <boost/asio/strand.hpp>
 | 
			
		||||
#include <boost/asio/thread_pool.hpp>
 | 
			
		||||
#include <boost/uuid/uuid.hpp>
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <latch>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
@@ -65,11 +68,14 @@ class ClusterCommunicationService : public ClusterCommunicationServiceInterface
 | 
			
		||||
    std::chrono::steady_clock::duration readInterval_;
 | 
			
		||||
    std::chrono::steady_clock::duration writeInterval_;
 | 
			
		||||
 | 
			
		||||
    boost::asio::cancellation_signal cancelSignal_;
 | 
			
		||||
    std::latch finishedCountdown_;
 | 
			
		||||
    std::atomic_bool running_ = false;
 | 
			
		||||
    bool stopped_ = false;
 | 
			
		||||
 | 
			
		||||
    ClioNode selfData_;
 | 
			
		||||
    std::vector<ClioNode> otherNodesData_;
 | 
			
		||||
 | 
			
		||||
    bool stopped_ = false;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    static constexpr std::chrono::milliseconds kDEFAULT_READ_INTERVAL{2100};
 | 
			
		||||
    static constexpr std::chrono::milliseconds kDEFAULT_WRITE_INTERVAL{1200};
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,6 @@ struct Amendments {
 | 
			
		||||
 | 
			
		||||
    /** @cond */
 | 
			
		||||
    // NOLINTBEGIN(readability-identifier-naming)
 | 
			
		||||
    REGISTER(OwnerPaysFee);
 | 
			
		||||
    REGISTER(Flow);
 | 
			
		||||
    REGISTER(FlowCross);
 | 
			
		||||
    REGISTER(fix1513);
 | 
			
		||||
@@ -145,6 +144,9 @@ struct Amendments {
 | 
			
		||||
    REGISTER(TokenEscrow);
 | 
			
		||||
    REGISTER(fixAMMv1_3);
 | 
			
		||||
    REGISTER(fixEnforceNFTokenTrustlineV2);
 | 
			
		||||
    REGISTER(fixAMMClawbackRounding);
 | 
			
		||||
    REGISTER(fixMPTDeliveredAmount);
 | 
			
		||||
    REGISTER(fixPriceOracleOrder);
 | 
			
		||||
 | 
			
		||||
    // Obsolete but supported by libxrpl
 | 
			
		||||
    REGISTER(CryptoConditionsSuite);
 | 
			
		||||
@@ -153,6 +155,7 @@ struct Amendments {
 | 
			
		||||
    REGISTER(fixNFTokenNegOffer);
 | 
			
		||||
 | 
			
		||||
    // Retired amendments
 | 
			
		||||
    REGISTER(OwnerPaysFee);  // Removed in xrpl 2.6.0 (https://github.com/XRPLF/rippled/pull/5435)
 | 
			
		||||
    REGISTER(MultiSign);
 | 
			
		||||
    REGISTER(TrustSetAuth);
 | 
			
		||||
    REGISTER(FeeEscalation);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@
 | 
			
		||||
 | 
			
		||||
#include "data/BackendInterface.hpp"
 | 
			
		||||
#include "data/CassandraBackend.hpp"
 | 
			
		||||
#include "data/KeyspaceBackend.hpp"
 | 
			
		||||
#include "data/LedgerCacheInterface.hpp"
 | 
			
		||||
#include "data/cassandra/SettingsProvider.hpp"
 | 
			
		||||
#include "util/config/ConfigDefinition.hpp"
 | 
			
		||||
@@ -45,6 +46,7 @@ namespace data {
 | 
			
		||||
inline std::shared_ptr<BackendInterface>
 | 
			
		||||
makeBackend(util::config::ClioConfigDefinition const& config, data::LedgerCacheInterface& cache)
 | 
			
		||||
{
 | 
			
		||||
    using namespace cassandra::impl;
 | 
			
		||||
    static util::Logger const log{"Backend"};  // NOLINT(readability-identifier-naming)
 | 
			
		||||
    LOG(log.info()) << "Constructing BackendInterface";
 | 
			
		||||
 | 
			
		||||
@@ -55,9 +57,15 @@ makeBackend(util::config::ClioConfigDefinition const& config, data::LedgerCacheI
 | 
			
		||||
 | 
			
		||||
    if (boost::iequals(type, "cassandra")) {
 | 
			
		||||
        auto const cfg = config.getObject("database." + type);
 | 
			
		||||
        backend = std::make_shared<data::cassandra::CassandraBackend>(
 | 
			
		||||
            data::cassandra::SettingsProvider{cfg}, cache, readOnly
 | 
			
		||||
        );
 | 
			
		||||
        if (providerFromString(cfg.getValueView("provider").asString()) == Provider::Keyspace) {
 | 
			
		||||
            backend = std::make_shared<data::cassandra::KeyspaceBackend>(
 | 
			
		||||
                data::cassandra::SettingsProvider{cfg}, cache, readOnly
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            backend = std::make_shared<data::cassandra::CassandraBackend>(
 | 
			
		||||
                data::cassandra::SettingsProvider{cfg}, cache, readOnly
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!backend)
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user