mirror of
https://github.com/facebook/rocksdb.git
synced 2026-11-07 03:22:34 -05:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a908554251 | ||
|
|
c5af7e0de2 | ||
|
|
44f3e1d68d | ||
|
|
c31c3ef191 | ||
|
|
87832c60a2 | ||
|
|
2e5f177eeb | ||
|
|
5c9a51b2c2 | ||
|
|
6aa939b288 | ||
|
|
2e985ae69d | ||
|
|
d180f08a66 | ||
|
|
b7f2c73fc8 | ||
|
|
f96414d976 |
No files matched your search
+3
-1
@@ -17,7 +17,9 @@ Checks: "-*,\
|
||||
cert-err58-cpp,\
|
||||
cert-msc30-c,\
|
||||
cert-msc50-cpp,\
|
||||
clang-analyzer-*,\
|
||||
clang-analyzer-core.NullDereference,\
|
||||
clang-analyzer-core.StackAddressEscape,\
|
||||
clang-analyzer-deadcode.DeadStores,\
|
||||
clang-diagnostic-*,\
|
||||
-clang-diagnostic-missing-designated-field-initializers,\
|
||||
concurrency-mt-unsafe,\
|
||||
|
||||
@@ -9,16 +9,7 @@ runs:
|
||||
steps:
|
||||
- name: Build folly and dependencies
|
||||
if: ${{ inputs.cache-hit != 'true' }}
|
||||
run: |
|
||||
clean_path=()
|
||||
IFS=: read -ra path_entries <<< "$PATH"
|
||||
for entry in "${path_entries[@]}"; do
|
||||
if [[ "$entry" != "/usr/lib/ccache" ]]; then
|
||||
clean_path+=("$entry")
|
||||
fi
|
||||
done
|
||||
export PATH="$(IFS=:; echo "${clean_path[*]}")"
|
||||
make build_folly
|
||||
run: make build_folly
|
||||
shell: bash
|
||||
- name: Skip folly build (using cached version)
|
||||
if: ${{ inputs.cache-hit == 'true' }}
|
||||
|
||||
@@ -30,4 +30,4 @@ runs:
|
||||
# - The docker image, which may not always be specified/known
|
||||
# - Hash of folly.mk, which includes the folly repository commit hash
|
||||
# NOTE: this is still only intended for DEBUG folly builds
|
||||
key: folly-build-${{ runner.os }}-${{ runner.arch }}-${{ github.job_container.image }}-${{ steps.extract-folly-hash.outputs.hash }}-${{ env.PORTABLE == '1' && 'portable' || 'native' }}
|
||||
key: folly-build-${{ runner.os }}-${{ runner.arch }}-${{ github.job_container.image }}-${{ steps.extract-folly-hash.outputs.hash }}
|
||||
@@ -0,0 +1,9 @@
|
||||
name: install-jdk8-on-macos
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install JDK 8 on macos
|
||||
run: |-
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew tap bell-sw/liberica
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install --cask liberica-jdk8
|
||||
shell: bash
|
||||
@@ -2,16 +2,6 @@ name: pre-steps
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Dump ulimits for diagnostics
|
||||
run: |
|
||||
echo "=== ulimits (soft) ==="
|
||||
ulimit -a -S || true
|
||||
echo "=== ulimits (hard) ==="
|
||||
ulimit -a -H || true
|
||||
shell: bash
|
||||
- name: Install lld linker for faster builds
|
||||
run: apt-get update -y && apt-get install -y lld 2>/dev/null || true
|
||||
shell: bash
|
||||
- name: Setup Environment Variables
|
||||
run: |-
|
||||
echo "GTEST_THROW_ON_FAILURE=0" >> "$GITHUB_ENV"
|
||||
@@ -20,15 +10,9 @@ runs:
|
||||
echo "GTEST_COLOR=1" >> "$GITHUB_ENV"
|
||||
echo "CTEST_OUTPUT_ON_FAILURE=1" >> "$GITHUB_ENV"
|
||||
echo "CTEST_TEST_TIMEOUT=300" >> "$GITHUB_ENV"
|
||||
# These third-party sources are mirrored on the "third-party-deps" GitHub
|
||||
# release. To add one, upload the asset here (intentionally hidden):
|
||||
# https://github.com/facebook/rocksdb/releases/edit/third-party-deps
|
||||
# Note how file names are generated below (vs. from the original source)
|
||||
# before uploading. Removing or modifying files will break builds for
|
||||
# older releases/revisions (not found or checksum mismatch).
|
||||
echo "ZLIB_DOWNLOAD_PREFIX=https://github.com/facebook/rocksdb/releases/download/third-party-deps/zlib-" >> "$GITHUB_ENV"
|
||||
echo "BZIP2_DOWNLOAD_PREFIX=https://github.com/facebook/rocksdb/releases/download/third-party-deps/bzip2-" >> "$GITHUB_ENV"
|
||||
echo "SNAPPY_DOWNLOAD_PREFIX=https://github.com/facebook/rocksdb/releases/download/third-party-deps/snappy-" >> "$GITHUB_ENV"
|
||||
echo "LZ4_DOWNLOAD_PREFIX=https://github.com/facebook/rocksdb/releases/download/third-party-deps/lz4-" >> "$GITHUB_ENV"
|
||||
echo "ZSTD_DOWNLOAD_PREFIX=https://github.com/facebook/rocksdb/releases/download/third-party-deps/zstd-" >> "$GITHUB_ENV"
|
||||
echo "ZLIB_DOWNLOAD_BASE=https://rocksdb-deps.s3.us-west-2.amazonaws.com/pkgs/zlib" >> "$GITHUB_ENV"
|
||||
echo "BZIP2_DOWNLOAD_BASE=https://rocksdb-deps.s3.us-west-2.amazonaws.com/pkgs/bzip2" >> "$GITHUB_ENV"
|
||||
echo "SNAPPY_DOWNLOAD_BASE=https://rocksdb-deps.s3.us-west-2.amazonaws.com/pkgs/snappy" >> "$GITHUB_ENV"
|
||||
echo "LZ4_DOWNLOAD_BASE=https://rocksdb-deps.s3.us-west-2.amazonaws.com/pkgs/lz4" >> "$GITHUB_ENV"
|
||||
echo "ZSTD_DOWNLOAD_BASE=https://rocksdb-deps.s3.us-west-2.amazonaws.com/pkgs/zstd" >> "$GITHUB_ENV"
|
||||
shell: bash
|
||||
@@ -1,54 +0,0 @@
|
||||
name: setup-ccache
|
||||
description: Setup ccache for faster C++ compilation caching
|
||||
inputs:
|
||||
cache-key-prefix:
|
||||
description: Unique prefix for the cache key (e.g., 'build-linux')
|
||||
required: true
|
||||
portable:
|
||||
description: Set PORTABLE=1 to disable -march=native (set to "false" for jobs linking pre-built Folly)
|
||||
required: false
|
||||
default: "true"
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set ccache environment variables
|
||||
run: |
|
||||
echo "CCACHE_DIR=${{ github.workspace }}/.ccache" >> $GITHUB_ENV
|
||||
echo "CCACHE_BASEDIR=${{ github.workspace }}" >> $GITHUB_ENV
|
||||
echo "CCACHE_NOHASHDIR=true" >> $GITHUB_ENV
|
||||
echo "CCACHE_COMPILERCHECK=content" >> $GITHUB_ENV
|
||||
echo "CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros" >> $GITHUB_ENV
|
||||
echo "CCACHE_MAXSIZE=4G" >> $GITHUB_ENV
|
||||
if [ "${{ inputs.portable }}" = "true" ]; then
|
||||
echo "PORTABLE=1" >> $GITHUB_ENV
|
||||
fi
|
||||
shell: bash
|
||||
- name: Restore ccache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ github.workspace }}/.ccache
|
||||
key: ccache-${{ inputs.cache-key-prefix }}-${{ github.head_ref || github.ref }}-${{ github.sha }}
|
||||
restore-keys: |-
|
||||
ccache-${{ inputs.cache-key-prefix }}-${{ github.head_ref || github.ref }}-
|
||||
ccache-${{ inputs.cache-key-prefix }}-refs/heads/main-
|
||||
- name: Install ccache
|
||||
run: |
|
||||
if [ "$RUNNER_OS" = "macOS" ]; then
|
||||
which ccache || brew install ccache
|
||||
else
|
||||
which ccache || (apt-get update && apt-get install -y ccache)
|
||||
fi
|
||||
shell: bash
|
||||
- name: Add ccache to PATH
|
||||
run: |
|
||||
if [ "$RUNNER_OS" = "macOS" ]; then
|
||||
echo "$(brew --prefix ccache)/libexec" >> $GITHUB_PATH
|
||||
else
|
||||
echo "/usr/lib/ccache" >> $GITHUB_PATH
|
||||
fi
|
||||
shell: bash
|
||||
- name: Zero ccache stats and set build marker
|
||||
run: |
|
||||
ccache -z
|
||||
touch "$CCACHE_DIR/.build_marker"
|
||||
shell: bash
|
||||
@@ -1,17 +0,0 @@
|
||||
name: setup-jdk-on-macos
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set up JDK on macos
|
||||
run: |-
|
||||
set -euo pipefail
|
||||
|
||||
JAVA_HOME="$(/usr/libexec/java_home -v 21)"
|
||||
|
||||
echo "JAVA_HOME=${JAVA_HOME}" >> "$GITHUB_ENV"
|
||||
echo "JAVAC_ARGS=--release 8" >> "$GITHUB_ENV"
|
||||
echo "${JAVA_HOME}/bin" >> "$GITHUB_PATH"
|
||||
echo "Using JDK at ${JAVA_HOME}"
|
||||
"${JAVA_HOME}/bin/java" -version
|
||||
"${JAVA_HOME}/bin/javac" -version
|
||||
shell: bash
|
||||
@@ -1,15 +0,0 @@
|
||||
name: teardown-ccache
|
||||
description: Trim stale ccache entries and print stats
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Trim and print ccache stats
|
||||
run: |
|
||||
if [ -z "$CCACHE_DIR" ]; then
|
||||
echo "teardown-ccache: CCACHE_DIR not set, skipping (setup-ccache may not have run)"
|
||||
exit 0
|
||||
fi
|
||||
.github/scripts/ccache-trim.sh || true
|
||||
ccache -s || echo "teardown-ccache: ccache not found, skipping stats"
|
||||
if: always()
|
||||
shell: bash
|
||||
@@ -1,95 +1,34 @@
|
||||
name: windows-build-steps
|
||||
inputs:
|
||||
suite-run:
|
||||
description: Comma-separated list of test suites to run (empty to skip C++ tests)
|
||||
required: false
|
||||
default: arena_test,db_basic_test,db_test,db_etc2_test,db_merge_operand_test,bloom_test,c_test,coding_test,crc32c_test,dynamic_bloom_test,env_basic_test,env_test,hash_test,random_test
|
||||
run-java:
|
||||
description: Whether to run Java tests
|
||||
required: false
|
||||
default: "true"
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Detect Visual Studio generator
|
||||
id: detect_vs
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$vswhere = Join-Path ([Environment]::GetFolderPath("ProgramFilesX86")) "Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
if (!(Test-Path $vswhere)) {
|
||||
throw "vswhere.exe was not found at $vswhere"
|
||||
}
|
||||
|
||||
$vsInstallationsJson = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -format json -utf8
|
||||
$vsInstallations = @($vsInstallationsJson | ConvertFrom-Json)
|
||||
if ($vsInstallations.Count -eq 0) {
|
||||
throw "No Visual Studio instance with C++ tools was found."
|
||||
}
|
||||
|
||||
$vsInstallation = $vsInstallations[0]
|
||||
$vsMajor = [int]$vsInstallation.catalog.productLineVersion
|
||||
if ($vsMajor -eq 0) {
|
||||
$vsMajor = [int]($vsInstallation.installationVersion.Split(".")[0])
|
||||
}
|
||||
|
||||
$generatorLine = cmake --help | Where-Object {
|
||||
$_ -match "^\*?\s*Visual Studio $vsMajor\s+\d{4}\s*="
|
||||
} | Select-Object -First 1
|
||||
if (!$generatorLine) {
|
||||
throw "CMake does not support a Visual Studio generator for VS major version $vsMajor."
|
||||
}
|
||||
|
||||
$cmakeGenerator = ($generatorLine -replace "^\*?\s*", "" -replace "\s*=.*$", "").Trim()
|
||||
$vsVersionRange = "[{0}.0,{1}.0)" -f $vsMajor, ($vsMajor + 1)
|
||||
|
||||
echo "Detected Visual Studio at $($vsInstallation.installationPath)"
|
||||
echo "Using CMake generator: $cmakeGenerator"
|
||||
echo "Using setup-msbuild vs-version: $vsVersionRange"
|
||||
|
||||
"CMAKE_GENERATOR=$cmakeGenerator" >> $env:GITHUB_ENV
|
||||
"vs_version=$vsVersionRange" >> $env:GITHUB_OUTPUT
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v1.3.1
|
||||
- name: Cache ccache directory
|
||||
id: ccache-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
vs-version: ${{ steps.detect_vs.outputs.vs_version }}
|
||||
path: C:\a\rocksdb\rocksdb\.ccache
|
||||
key: rocksdb-build-${{ runner.os }}-${{ runner.arch }}-ccache-${{ hashFiles('CMakeLists.txt', 'cmake/**/*.cmake') }}-v1
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
max-size: "10GB"
|
||||
key: ccache-windows-${{ github.workflow }}
|
||||
restore-keys: |
|
||||
ccache-windows-
|
||||
- name: Configure ccache
|
||||
shell: pwsh
|
||||
run: |
|
||||
ccache --set-config=base_dir=C:\a\rocksdb\rocksdb
|
||||
ccache --set-config=hash_dir=false
|
||||
ccache --set-config=compiler_check=content
|
||||
- name: Custom steps
|
||||
env:
|
||||
THIRDPARTY_HOME: ${{ github.workspace }}/thirdparty
|
||||
CMAKE_HOME: C:/Program Files/CMake
|
||||
CMAKE_BIN: C:/Program Files/CMake/bin/cmake.exe
|
||||
CTEST_BIN: C:/Program Files/CMake/bin/ctest.exe
|
||||
JAVA_HOME: C:/Program Files/BellSoft/LibericaJDK-8
|
||||
SNAPPY_HOME: ${{ github.workspace }}/thirdparty/snappy-1.2.2
|
||||
SNAPPY_INCLUDE: ${{ github.workspace }}/thirdparty/snappy-1.2.2;${{ github.workspace }}/thirdparty/snappy-1.2.2/build
|
||||
SNAPPY_LIB_DEBUG: ${{ github.workspace }}/thirdparty/snappy-1.2.2/build/Debug/snappy.lib
|
||||
run: |-
|
||||
# NOTE: if ... Exit $LASTEXITCODE lines needed to exit and report failure
|
||||
echo ===================== Install Dependencies =====================
|
||||
if (!$env:JAVA_HOME -or !(Test-Path (Join-Path $env:JAVA_HOME "bin\javac.exe"))) {
|
||||
$javac = Get-Command javac -ErrorAction SilentlyContinue
|
||||
if (!$javac) {
|
||||
Write-Error "javac was not found on PATH and JAVA_HOME is not set."
|
||||
Exit 1
|
||||
}
|
||||
$env:JAVA_HOME = Split-Path (Split-Path $javac.Source -Parent) -Parent
|
||||
}
|
||||
echo "JAVA_HOME=$env:JAVA_HOME"
|
||||
& "$env:JAVA_HOME\bin\java.exe" -version
|
||||
& "$env:JAVA_HOME\bin\javac.exe" -version
|
||||
choco install liberica8jdk -y
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
mkdir $Env:THIRDPARTY_HOME
|
||||
cd $Env:THIRDPARTY_HOME
|
||||
echo "Building Snappy dependency..."
|
||||
@@ -102,11 +41,11 @@ runs:
|
||||
cd build
|
||||
& cmake -G "$Env:CMAKE_GENERATOR" .. -DSNAPPY_BUILD_TESTS=OFF -DSNAPPY_BUILD_BENCHMARKS=OFF
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
cmake --build . --config Debug --parallel 32 -- /p:Platform=x64
|
||||
msbuild Snappy.sln -maxCpuCount -property:Configuration=Debug -property:Platform=x64
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
echo ======================== Build RocksDB =========================
|
||||
cd ${{ github.workspace }}
|
||||
$env:Path = "$env:JAVA_HOME\bin;" + $env:Path
|
||||
$env:Path = $env:JAVA_HOME + ";" + $env:Path
|
||||
mkdir build
|
||||
cd build
|
||||
& cmake -G "$Env:CMAKE_GENERATOR" -DCMAKE_BUILD_TYPE=Debug -DWIN_CI=1 -DPORTABLE="$Env:CMAKE_PORTABLE" -DSNAPPY=1 -DXPRESS=1 -DJNI=1 ..
|
||||
@@ -114,25 +53,15 @@ runs:
|
||||
cd ..
|
||||
echo "Building with VS version: $Env:CMAKE_GENERATOR"
|
||||
# use more parallel processes than the number of processes available, as most of the compile command would be cache hit
|
||||
cmake --build build --config Debug --parallel 32 -- /p:LinkIncremental=false /p:Platform=x64
|
||||
msbuild build/rocksdb.sln /m:32 /p:LinkIncremental=false -property:Configuration=Debug -property:Platform=x64
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
echo ========================= Test RocksDB =========================
|
||||
$suiteRun = "${{ inputs.suite-run }}"
|
||||
if ($suiteRun -ne "") {
|
||||
$suiteArray = $suiteRun -split ','
|
||||
build_tools\run_ci_db_test.ps1 -SuiteRun $suiteArray -Concurrency 16
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
} else {
|
||||
echo "Skipping C++ tests (suite-run is empty)"
|
||||
}
|
||||
if ("${{ inputs.run-java }}" -eq "true") {
|
||||
echo ======================== Test RocksJava ========================
|
||||
cd build\java
|
||||
& ctest -C Debug -j 16
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
} else {
|
||||
echo "Skipping Java tests"
|
||||
}
|
||||
build_tools\run_ci_db_test.ps1 -SuiteRun arena_test,db_basic_test,db_test,db_test2,db_merge_operand_test,bloom_test,c_test,coding_test,crc32c_test,dynamic_bloom_test,env_basic_test,env_test,hash_test,random_test -Concurrency 16
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
echo ======================== Test RocksJava ========================
|
||||
cd build\java
|
||||
& ctest -C Debug -j 16
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
shell: pwsh
|
||||
- name: Show ccache stats
|
||||
shell: pwsh
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// Shared markdown builder for AI review comment bodies.
|
||||
//
|
||||
// Usage:
|
||||
// const build = require('./build-ai-review-comment.js');
|
||||
// return build({ icon, headerTitle, triggerLine, responseBody, footerLines
|
||||
// });
|
||||
|
||||
// GitHub rejects issue comments longer than this many characters. The model
|
||||
// response (responseBody) is the only unbounded input, so we trim it to fit
|
||||
// while keeping the fixed scaffolding (header, trigger, footer) intact.
|
||||
const MAX_COMMENT_LENGTH = 65536;
|
||||
const TRUNCATION_NOTE =
|
||||
'\n\n*[Truncated — full output in execution log artifact]*';
|
||||
|
||||
module.exports = function buildAiReviewComment(
|
||||
{icon, headerTitle, triggerLine, responseBody, footerLines}) {
|
||||
const assemble = (body) => [`## ${icon} ${headerTitle}`,
|
||||
'',
|
||||
triggerLine,
|
||||
'',
|
||||
'---',
|
||||
'',
|
||||
body,
|
||||
'',
|
||||
'---',
|
||||
'',
|
||||
'<details>',
|
||||
'<summary>ℹ️ About this response</summary>',
|
||||
'',
|
||||
...footerLines,
|
||||
'</details>',
|
||||
].join('\n');
|
||||
|
||||
const body = responseBody || '';
|
||||
const comment = assemble(body);
|
||||
if (comment.length <= MAX_COMMENT_LENGTH) {
|
||||
return comment;
|
||||
}
|
||||
// Drop only as much of the body as needed to fit, then re-assemble so the
|
||||
// footer/<details> block is preserved rather than cut off mid-comment.
|
||||
const overflow = comment.length - MAX_COMMENT_LENGTH;
|
||||
const keep = Math.max(0, body.length - overflow - TRUNCATION_NOTE.length);
|
||||
return assemble(body.substring(0, keep) + TRUNCATION_NOTE);
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Trim ccache to keep only entries accessed during the current build.
|
||||
#
|
||||
# Usage:
|
||||
# 1. Before build: touch "$CCACHE_DIR/.build_marker"
|
||||
# 2. Run build (ccache updates mtime on hits, creates new files for misses)
|
||||
# 3. After build: .github/scripts/ccache-trim.sh
|
||||
#
|
||||
# This removes cache files not accessed during the build (stale entries from
|
||||
# previous commits). Only intended for CI where each run builds one commit.
|
||||
# Do NOT use on local builds where multiple worktrees may share the cache.
|
||||
|
||||
set -e
|
||||
|
||||
CCACHE_DIR="${CCACHE_DIR:?CCACHE_DIR must be set}"
|
||||
MARKER="$CCACHE_DIR/.build_marker"
|
||||
|
||||
if [ ! -f "$MARKER" ]; then
|
||||
echo "ccache-trim: No .build_marker found, skipping (was the marker created before build?)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Count files before cleanup
|
||||
before=$(find "$CCACHE_DIR" -type f \( -name '*R' -o -name '*M' \) | wc -l)
|
||||
|
||||
# Delete cache files (results and manifests) older than the marker
|
||||
find "$CCACHE_DIR" -type f \( -name '*R' -o -name '*M' \) ! -newer "$MARKER" -delete
|
||||
|
||||
# Clean up empty directories
|
||||
find "$CCACHE_DIR" -mindepth 2 -type d -empty -delete 2>/dev/null || true
|
||||
|
||||
# Recalculate size counters
|
||||
ccache -c 2>/dev/null || true
|
||||
|
||||
after=$(find "$CCACHE_DIR" -type f \( -name '*R' -o -name '*M' \) | wc -l)
|
||||
echo "ccache-trim: $before -> $after cache files (removed $((before - after)) stale entries)"
|
||||
|
||||
# Clean up marker
|
||||
rm -f "$MARKER"
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Compute test shard for parallel CI execution.
|
||||
# Distributes tests round-robin across N shards for balanced load.
|
||||
# Outputs ROCKSDBTESTS_SUBSET — the list of test binaries for this shard.
|
||||
# The Makefile uses this to build and run only the assigned tests.
|
||||
#
|
||||
# Usage: compute-test-shard.sh <shard_index> <num_shards>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
shard=${1:?Usage: compute-test-shard.sh <shard_index> <num_shards>}
|
||||
nshards=${2:?Usage: compute-test-shard.sh <shard_index> <num_shards>}
|
||||
|
||||
# Get sorted test list (db_test first since it's the heaviest, then alpha)
|
||||
make -s list_all_tests 2>/dev/null | tr ' ' '\n' | grep '_test$' | sort -u > /tmp/sorted.txt
|
||||
(echo db_test; grep -v '^db_test$' /tmp/sorted.txt) > /tmp/all_tests.txt
|
||||
|
||||
total=$(wc -l < /tmp/all_tests.txt)
|
||||
|
||||
# Round-robin: assign test i to shard (i % nshards).
|
||||
# This spreads heavy tests (which are scattered alphabetically) evenly.
|
||||
awk -v s="$shard" -v n="$nshards" 'NR > 0 && (NR - 1) % n == s' /tmp/all_tests.txt > /tmp/include.txt
|
||||
|
||||
included=$(wc -l < /tmp/include.txt)
|
||||
first=$(head -1 /tmp/include.txt)
|
||||
last=$(tail -1 /tmp/include.txt)
|
||||
|
||||
# Output space-separated list for ROCKSDBTESTS_SUBSET
|
||||
subset=$(tr '\n' ' ' < /tmp/include.txt)
|
||||
echo "subset=${subset}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "Shard $shard/$nshards: $included tests (round-robin), first=$first last=$last (total $total)"
|
||||
@@ -1,118 +0,0 @@
|
||||
// Parse Claude Code execution log and produce a markdown review comment.
|
||||
//
|
||||
// Usage from actions/github-script:
|
||||
// const parse = require('./.github/scripts/parse-claude-review.js');
|
||||
// const markdown = parse({ executionFile, conclusion, meta });
|
||||
//
|
||||
// Parameters:
|
||||
// executionFile - path to the JSON execution log from claude-code-base-action
|
||||
// conclusion - 'success' or 'failure' from the action output
|
||||
// meta - { trigger, autoMode, headSha, reviewer, isQuery, isPartial
|
||||
// }
|
||||
|
||||
const fs = require('fs');
|
||||
const buildComment = require('./build-ai-review-comment.js');
|
||||
|
||||
module.exports = function parseClaude({executionFile, conclusion, meta}) {
|
||||
function getTriggerLine() {
|
||||
if (meta.trigger !== 'auto') {
|
||||
return `*Requested by @${meta.reviewer}*`;
|
||||
}
|
||||
const shortSha = meta.headSha ? meta.headSha.substring(0, 7) : 'unknown';
|
||||
if (meta.autoMode === 'early') {
|
||||
return `*Auto-triggered after CI reached the early-review threshold — reviewing commit ${
|
||||
shortSha}*`;
|
||||
}
|
||||
return `*Auto-triggered after CI passed — reviewing commit ${shortSha}*`;
|
||||
}
|
||||
|
||||
let responseBody = '';
|
||||
|
||||
try {
|
||||
const executionLog = JSON.parse(fs.readFileSync(executionFile, 'utf8'));
|
||||
|
||||
if (!Array.isArray(executionLog)) {
|
||||
throw new Error('Expected array format from claude-code-base-action');
|
||||
}
|
||||
|
||||
const resultMessage = executionLog.find(m => m.type === 'result');
|
||||
|
||||
// Helper: extract the last substantial assistant text from the log.
|
||||
// Used as a fallback when Claude ran out of turns and the recovery
|
||||
// session also failed to produce a result.
|
||||
function getLastAssistantText(log, minLength = 200) {
|
||||
for (let i = log.length - 1; i >= 0; i--) {
|
||||
const m = log[i];
|
||||
if (m.type !== 'assistant') continue;
|
||||
const content = m.message && m.message.content;
|
||||
if (!Array.isArray(content)) continue;
|
||||
for (let j = content.length - 1; j >= 0; j--) {
|
||||
if (content[j].type === 'text' && content[j].text &&
|
||||
content[j].text.trim().length >= minLength) {
|
||||
const text = content[j].text.trim();
|
||||
// Truncate to avoid enormous PR comments
|
||||
return text.length > 50000 ? text.substring(0, 50000) +
|
||||
'\n\n*[Truncated — full output in execution log artifact]*' :
|
||||
text;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!resultMessage) {
|
||||
responseBody = '⚠️ No result message found in execution log.';
|
||||
} else if (resultMessage.subtype === 'success' && resultMessage.result) {
|
||||
responseBody = resultMessage.result;
|
||||
} else if (resultMessage.is_error || resultMessage.subtype === 'error') {
|
||||
const errorInfo =
|
||||
resultMessage.result || resultMessage.error || 'Unknown error';
|
||||
responseBody = `❌ **Claude encountered an error:**\n\n${errorInfo}`;
|
||||
} else if (resultMessage.subtype === 'error_max_turns') {
|
||||
// The workflow runs a recovery session when this happens, so this
|
||||
// branch is typically only hit if recovery wasn't attempted (e.g.,
|
||||
// no findings file was written). Extract what we can.
|
||||
const partial = getLastAssistantText(executionLog);
|
||||
if (partial) {
|
||||
responseBody =
|
||||
`⚠️ **Review incomplete — Claude hit the turn limit.**\n\nBelow is the last partial output. You can request a fresh review with \`/claude-review\`.\n\n---\n\n${
|
||||
partial}`;
|
||||
} else {
|
||||
responseBody =
|
||||
'⚠️ **Review incomplete — Claude hit the turn limit before producing output.** You can request a fresh review with `/claude-review`.';
|
||||
}
|
||||
} else if (resultMessage.result) {
|
||||
responseBody = `⚠️ **Completed with status: ${
|
||||
resultMessage.subtype}**\n\n${resultMessage.result}`;
|
||||
} else {
|
||||
responseBody = '⚠️ Claude completed but produced no output.';
|
||||
}
|
||||
} catch (error) {
|
||||
responseBody = `❌ Error parsing Claude response: ${error.message}`;
|
||||
}
|
||||
|
||||
const isPartial = !!meta.isPartial;
|
||||
const icon = isPartial ? '🟡' : (conclusion === 'success' ? '✅' : '⚠️');
|
||||
const headerTitle = meta.isQuery ? 'Claude Response' : 'Claude Code Review';
|
||||
const triggerLine = getTriggerLine();
|
||||
|
||||
return buildComment({
|
||||
icon,
|
||||
headerTitle,
|
||||
triggerLine,
|
||||
responseBody,
|
||||
footerLines: [
|
||||
'Generated by [Claude Code](https://github.com/anthropics/claude-code-action).',
|
||||
'Review methodology: `claude_md/ci_review_prompt.md`',
|
||||
'',
|
||||
'**Limitations:**',
|
||||
'- Claude may miss context from files not in the diff',
|
||||
'- Large PRs may be truncated',
|
||||
'- Always apply human judgment to AI suggestions',
|
||||
'',
|
||||
'**Commands:**',
|
||||
'- `/claude-review [context]` — Request a code review',
|
||||
'- `/claude-query <question>` — Ask about the PR or codebase',
|
||||
],
|
||||
});
|
||||
};
|
||||
@@ -1,98 +0,0 @@
|
||||
// Parse Codex review artifacts and produce a markdown review comment.
|
||||
//
|
||||
// Usage from actions/github-script:
|
||||
// const parse = require('./.github/scripts/parse-codex-review.js');
|
||||
// const markdown = parse({ responseFile, recoveryFile, findingsFile, logFile,
|
||||
// exitCode, meta });
|
||||
//
|
||||
// Parameters:
|
||||
// responseFile - path to Codex final response output
|
||||
// recoveryFile - path to recovery output formatted from review-findings.md
|
||||
// findingsFile - path to incremental findings file written during review
|
||||
// logFile - path to Codex stdout/stderr log
|
||||
// exitCode - Codex process exit code
|
||||
// meta - { trigger, autoMode, headSha, reviewer, isQuery, isPartial }
|
||||
|
||||
const fs = require('fs');
|
||||
const buildComment = require('./build-ai-review-comment.js');
|
||||
|
||||
module.exports = function parseCodex(
|
||||
{responseFile, recoveryFile, findingsFile, logFile, exitCode, meta}) {
|
||||
function getTriggerLine() {
|
||||
if (meta.trigger !== 'auto') {
|
||||
return `*Requested by @${meta.reviewer}*`;
|
||||
}
|
||||
const shortSha = meta.headSha ? meta.headSha.substring(0, 7) : 'unknown';
|
||||
if (meta.autoMode === 'early') {
|
||||
return `*Auto-triggered after CI reached the early-review threshold — reviewing commit ${
|
||||
shortSha}*`;
|
||||
}
|
||||
return `*Auto-triggered after CI passed — reviewing commit ${shortSha}*`;
|
||||
}
|
||||
|
||||
function readIfPresent(path) {
|
||||
if (!path || !fs.existsSync(path)) {
|
||||
return '';
|
||||
}
|
||||
const text = fs.readFileSync(path, 'utf8').trim();
|
||||
return text;
|
||||
}
|
||||
|
||||
function tailFile(path, maxChars = 12000) {
|
||||
const text = readIfPresent(path);
|
||||
if (!text) {
|
||||
return '';
|
||||
}
|
||||
if (text.length <= maxChars) {
|
||||
return text;
|
||||
}
|
||||
return text.slice(text.length - maxChars);
|
||||
}
|
||||
|
||||
let responseBody = '';
|
||||
const recovered = readIfPresent(recoveryFile);
|
||||
const direct = readIfPresent(responseFile);
|
||||
const findings = readIfPresent(findingsFile);
|
||||
|
||||
if (recovered) {
|
||||
responseBody = recovered;
|
||||
} else if (direct) {
|
||||
responseBody = direct;
|
||||
} else if (findings) {
|
||||
responseBody =
|
||||
'⚠️ **Review incomplete — Codex did not produce a final response.**\n\n' +
|
||||
'Below are the incremental findings recovered from `review-findings.md`.\n\n---\n\n' +
|
||||
findings;
|
||||
} else {
|
||||
const logTail = tailFile(logFile);
|
||||
responseBody = logTail ?
|
||||
`❌ **Codex review failed before producing findings.**\n\n\`\`\`\n${
|
||||
logTail}\n\`\`\`` :
|
||||
'❌ Codex review failed before producing any output.';
|
||||
}
|
||||
|
||||
const isPartial = !!meta.isPartial;
|
||||
const code = Number.parseInt(exitCode || '1', 10);
|
||||
const icon = isPartial ? '🟡' : (code === 0 ? '✅' : '⚠️');
|
||||
const triggerLine = getTriggerLine();
|
||||
|
||||
return buildComment({
|
||||
icon,
|
||||
headerTitle: meta.isQuery ? 'Codex Response' : 'Codex Code Review',
|
||||
triggerLine,
|
||||
responseBody,
|
||||
footerLines: [
|
||||
'Generated by Codex CLI.',
|
||||
'Review methodology: `claude_md/ci_review_prompt.md`',
|
||||
'',
|
||||
'**Limitations:**',
|
||||
'- Codex may miss context from files not in the diff',
|
||||
'- Large PRs may be truncated',
|
||||
'- Always apply human judgment to AI suggestions',
|
||||
'',
|
||||
'**Commands:**',
|
||||
'- `/codex-review [context]` — Request a code review',
|
||||
'- `/codex-query <question>` — Ask about the PR or codebase',
|
||||
],
|
||||
});
|
||||
};
|
||||
@@ -1,204 +0,0 @@
|
||||
// Shared PR comment posting utility.
|
||||
// Used by both clang-tidy-comment.yml and claude-review-comment.yml.
|
||||
//
|
||||
// Usage from actions/github-script:
|
||||
// const post = require('./.github/scripts/post-pr-comment.js');
|
||||
// await post({ github, context, core, prNumber, body, marker });
|
||||
//
|
||||
// Parameters:
|
||||
// github - octokit instance from actions/github-script
|
||||
// context - GitHub Actions context
|
||||
// core - @actions/core for logging
|
||||
// prNumber - PR number to comment on
|
||||
// body - comment body (markdown string)
|
||||
// marker - HTML comment marker for dedup (e.g. '<!-- claude-review -->')
|
||||
// If an existing comment with this marker is found, it is updated.
|
||||
// If not found, a new comment is created.
|
||||
// legacyMarkers - optional list of legacy markers that should be migrated by
|
||||
// being considered part of the same comment family.
|
||||
// prunePrefix - optional marker prefix whose older comments should be
|
||||
// superseded. If obsoleteTitle is set, older comments are
|
||||
// collapsed instead of deleted.
|
||||
// preserveLatest - optional count of active comments to keep when
|
||||
// prunePrefix is set.
|
||||
// obsoleteMarker - optional HTML marker used to detect already-obsolete
|
||||
// comments.
|
||||
// obsoleteTitle - optional heading to use when collapsing superseded
|
||||
// comments into a details block.
|
||||
|
||||
module.exports = async function postPrComment({
|
||||
github,
|
||||
context,
|
||||
core,
|
||||
prNumber,
|
||||
body,
|
||||
marker,
|
||||
legacyMarkers = [],
|
||||
prunePrefix = '',
|
||||
preserveLatest = 0,
|
||||
obsoleteMarker = '',
|
||||
obsoleteTitle = '',
|
||||
}) {
|
||||
if (!prNumber || !body) {
|
||||
core.warning('Missing prNumber or body; skipping comment.');
|
||||
return;
|
||||
}
|
||||
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
|
||||
// Ensure marker is embedded in the body
|
||||
const markedBody = body.includes(marker) ? body : `${marker}\n${body}`;
|
||||
|
||||
async function listComments() {
|
||||
return await github.paginate(github.rest.issues.listComments, {
|
||||
owner,
|
||||
repo,
|
||||
issue_number: prNumber,
|
||||
per_page: 100,
|
||||
});
|
||||
}
|
||||
|
||||
function commentActivityTime(comment) {
|
||||
const timestamp =
|
||||
Date.parse(comment.updated_at || comment.created_at || '');
|
||||
return Number.isNaN(timestamp) ? 0 : timestamp;
|
||||
}
|
||||
|
||||
function commentSortDescending(left, right) {
|
||||
const timeDelta = commentActivityTime(right) - commentActivityTime(left);
|
||||
if (timeDelta !== 0) {
|
||||
return timeDelta;
|
||||
}
|
||||
return Number(right.id || 0) - Number(left.id || 0);
|
||||
}
|
||||
|
||||
function isObsoleteComment(comment) {
|
||||
return !!obsoleteMarker && typeof comment.body === 'string' &&
|
||||
comment.body.includes(obsoleteMarker);
|
||||
}
|
||||
|
||||
function buildObsoleteBody(comment) {
|
||||
const originalBody =
|
||||
typeof comment.body === 'string' && comment.body.trim() ?
|
||||
comment.body :
|
||||
'*No original review body preserved.*';
|
||||
const title = obsoleteTitle || 'AI Review - OBSOLETE';
|
||||
return `${obsoleteMarker}\n## ${
|
||||
title}\n\n<details>\n<summary>Superseded by a newer AI review. Expand to see the original review.</summary>\n\n${
|
||||
originalBody}\n\n</details>`;
|
||||
}
|
||||
|
||||
async function deleteCommentIfPresent(comment, reason) {
|
||||
try {
|
||||
await github.rest.issues.deleteComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: comment.id,
|
||||
});
|
||||
core.info(`${reason} ${comment.id}`);
|
||||
} catch (error) {
|
||||
if (error.status === 404) {
|
||||
core.info(`Comment ${comment.id} was already deleted by another run.`);
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function supersedeCommentIfPresent(comment, reason) {
|
||||
if (!obsoleteTitle) {
|
||||
await deleteCommentIfPresent(comment, reason);
|
||||
return;
|
||||
}
|
||||
if (isObsoleteComment(comment)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await github.rest.issues.updateComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: comment.id,
|
||||
body: buildObsoleteBody(comment),
|
||||
});
|
||||
core.info(`${reason} ${comment.id}`);
|
||||
} catch (error) {
|
||||
if (error.status === 404) {
|
||||
core.info(`Comment ${comment.id} was already deleted by another run.`);
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
let comments = await listComments();
|
||||
const existing = comments.find(
|
||||
comment =>
|
||||
typeof comment.body === 'string' && comment.body.includes(marker));
|
||||
let currentCommentId = null;
|
||||
|
||||
if (existing) {
|
||||
try {
|
||||
const response = await github.rest.issues.updateComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: existing.id,
|
||||
body: markedBody,
|
||||
});
|
||||
currentCommentId = existing.id;
|
||||
core.info(`Updated existing comment ${existing.id}`);
|
||||
} catch (error) {
|
||||
if (error.status !== 404) {
|
||||
throw error;
|
||||
}
|
||||
core.info(
|
||||
`Comment ${existing.id} disappeared before update; ` +
|
||||
'creating a fresh comment instead.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentCommentId) {
|
||||
const response = await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: prNumber,
|
||||
body: markedBody,
|
||||
});
|
||||
currentCommentId = response.data.id;
|
||||
core.info('Created new PR comment');
|
||||
}
|
||||
|
||||
if (prunePrefix || legacyMarkers.length > 0) {
|
||||
comments = await listComments();
|
||||
const relatedComments = comments.filter(
|
||||
comment => comment.id !== currentCommentId &&
|
||||
typeof comment.body === 'string' &&
|
||||
((prunePrefix && comment.body.includes(prunePrefix)) ||
|
||||
legacyMarkers.some(
|
||||
legacyMarker => comment.body.includes(legacyMarker))));
|
||||
const activeRelatedComments =
|
||||
comments
|
||||
.filter(
|
||||
comment => typeof comment.body === 'string' &&
|
||||
!isObsoleteComment(comment) &&
|
||||
(comment.id === currentCommentId ||
|
||||
relatedComments.some(
|
||||
relatedComment => relatedComment.id === comment.id)))
|
||||
.sort(commentSortDescending);
|
||||
|
||||
const keep =
|
||||
new Set(activeRelatedComments.slice(0, Math.max(preserveLatest, 1))
|
||||
.map(comment => comment.id));
|
||||
|
||||
const supersedeCandidates = obsoleteTitle ?
|
||||
activeRelatedComments.filter(comment => !keep.has(comment.id)) :
|
||||
relatedComments.filter(comment => !keep.has(comment.id));
|
||||
|
||||
for (const comment of supersedeCandidates) {
|
||||
if (keep.has(comment.id)) {
|
||||
continue;
|
||||
}
|
||||
await supersedeCommentIfPresent(comment, 'Superseded old AI review');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,347 +0,0 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
const postPrComment = require('./post-pr-comment.js');
|
||||
|
||||
const OBSOLETE_MARKER = '<!-- claude-review-obsolete -->';
|
||||
const OBSOLETE_TITLE = 'Claude Code Review - OBSOLETE';
|
||||
|
||||
function makeComment(id, body, createdAt, updatedAt) {
|
||||
return {
|
||||
id,
|
||||
body,
|
||||
created_at: createdAt,
|
||||
updated_at: updatedAt || createdAt,
|
||||
};
|
||||
}
|
||||
|
||||
function createHarness(initialComments, options = {}) {
|
||||
let comments = initialComments.map(comment => ({...comment}));
|
||||
let nextCommentId = options.nextCommentId || 1000;
|
||||
let paginateCount = 0;
|
||||
|
||||
const calls = {
|
||||
update: [],
|
||||
create: [],
|
||||
delete: [],
|
||||
};
|
||||
|
||||
const github = {
|
||||
paginate: async () => {
|
||||
paginateCount++;
|
||||
if (options.onPaginate) {
|
||||
const updated = options.onPaginate({
|
||||
paginateCount,
|
||||
comments: comments.map(comment => ({...comment})),
|
||||
});
|
||||
if (updated) {
|
||||
comments = updated.map(comment => ({...comment}));
|
||||
}
|
||||
}
|
||||
return comments.map(comment => ({...comment}));
|
||||
},
|
||||
rest: {
|
||||
issues: {
|
||||
listComments: () => {
|
||||
throw new Error('listComments should only be used through paginate');
|
||||
},
|
||||
updateComment: async ({comment_id, body}) => {
|
||||
calls.update.push({comment_id, body});
|
||||
const error =
|
||||
options.updateErrors && options.updateErrors[comment_id];
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
const index =
|
||||
comments.findIndex(comment => comment.id === comment_id);
|
||||
if (index === -1) {
|
||||
const notFound = new Error(`Comment ${comment_id} not found`);
|
||||
notFound.status = 404;
|
||||
throw notFound;
|
||||
}
|
||||
const updated = {
|
||||
...comments[index],
|
||||
body,
|
||||
updated_at: options.updateTimestamp || '2026-04-24T00:00:00Z',
|
||||
};
|
||||
comments[index] = updated;
|
||||
return {data: {...updated}};
|
||||
},
|
||||
createComment: async ({issue_number, body}) => {
|
||||
calls.create.push({issue_number, body});
|
||||
const created = makeComment(
|
||||
nextCommentId++, body,
|
||||
options.createTimestamp || '2026-04-24T00:00:00Z');
|
||||
comments.push(created);
|
||||
return {data: {id: created.id}};
|
||||
},
|
||||
deleteComment: async ({comment_id}) => {
|
||||
calls.delete.push({comment_id});
|
||||
const error =
|
||||
options.deleteErrors && options.deleteErrors[comment_id];
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
comments = comments.filter(comment => comment.id !== comment_id);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
github,
|
||||
calls,
|
||||
getComments: () => comments.map(comment => ({...comment})),
|
||||
};
|
||||
}
|
||||
|
||||
function createCore() {
|
||||
return {
|
||||
info: () => {},
|
||||
warning: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
function escapeRegExp(value) {
|
||||
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
function assertObsoleteComment(comment, originalBody) {
|
||||
assert.ok(comment);
|
||||
assert.match(comment.body, new RegExp(escapeRegExp(OBSOLETE_MARKER)));
|
||||
assert.match(comment.body, new RegExp(`## ${escapeRegExp(OBSOLETE_TITLE)}`));
|
||||
assert.match(comment.body, /<details>/);
|
||||
assert.match(comment.body, /Superseded by a newer AI review/);
|
||||
assert.match(comment.body, new RegExp(escapeRegExp(originalBody)));
|
||||
}
|
||||
|
||||
const context = {
|
||||
repo: {
|
||||
owner: 'facebook',
|
||||
repo: 'rocksdb',
|
||||
},
|
||||
};
|
||||
|
||||
test(
|
||||
'creates a fresh review comment and supersedes legacy comments',
|
||||
async () => {
|
||||
const harness = createHarness(
|
||||
[
|
||||
makeComment(
|
||||
1, '<!-- claude-review-auto -->\nold legacy', 'not-a-date'),
|
||||
makeComment(
|
||||
2, '<!-- claude-review-auto -->\nnew legacy',
|
||||
'2026-04-21T00:00:00Z'),
|
||||
],
|
||||
{
|
||||
updateTimestamp: '2026-04-24T00:00:00Z',
|
||||
});
|
||||
|
||||
await postPrComment({
|
||||
github: harness.github,
|
||||
context,
|
||||
core: createCore(),
|
||||
prNumber: 14659,
|
||||
body: 'review body',
|
||||
marker: '<!-- claude-review-auto-run-500 -->',
|
||||
legacyMarkers: ['<!-- claude-review-auto -->'],
|
||||
prunePrefix: '<!-- claude-review-auto-',
|
||||
preserveLatest: 1,
|
||||
obsoleteMarker: OBSOLETE_MARKER,
|
||||
obsoleteTitle: OBSOLETE_TITLE,
|
||||
});
|
||||
|
||||
assert.equal(harness.calls.create.length, 1);
|
||||
assert.deepEqual(
|
||||
harness.calls.update.map(call => call.comment_id), [2, 1]);
|
||||
assert.equal(harness.calls.delete.length, 0);
|
||||
|
||||
const comments = harness.getComments();
|
||||
assert.equal(comments.length, 3);
|
||||
assert.match(
|
||||
comments.find(comment => comment.id === 1000).body,
|
||||
/<!-- claude-review-auto-run-500 -->/);
|
||||
assertObsoleteComment(
|
||||
comments.find(comment => comment.id === 2),
|
||||
'<!-- claude-review-auto -->\nnew legacy');
|
||||
assertObsoleteComment(
|
||||
comments.find(comment => comment.id === 1),
|
||||
'<!-- claude-review-auto -->\nold legacy');
|
||||
});
|
||||
|
||||
test(
|
||||
'updates an exact-match comment and supersedes leftover legacy comments',
|
||||
async () => {
|
||||
const harness = createHarness(
|
||||
[
|
||||
makeComment(
|
||||
3, '<!-- claude-review-auto-abcdef0 -->\ncurrent body',
|
||||
'2026-04-24T00:00:00Z'),
|
||||
makeComment(
|
||||
4, '<!-- claude-review-auto -->\nlegacy body',
|
||||
'2026-04-20T00:00:00Z'),
|
||||
],
|
||||
{
|
||||
updateTimestamp: '2026-04-24T01:00:00Z',
|
||||
});
|
||||
|
||||
await postPrComment({
|
||||
github: harness.github,
|
||||
context,
|
||||
core: createCore(),
|
||||
prNumber: 14659,
|
||||
body: 'refreshed body',
|
||||
marker: '<!-- claude-review-auto-abcdef0 -->',
|
||||
legacyMarkers: ['<!-- claude-review-auto -->'],
|
||||
prunePrefix: '<!-- claude-review-auto-',
|
||||
preserveLatest: 1,
|
||||
obsoleteMarker: OBSOLETE_MARKER,
|
||||
obsoleteTitle: OBSOLETE_TITLE,
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
harness.calls.update.map(call => call.comment_id), [3, 4]);
|
||||
assert.equal(harness.calls.create.length, 0);
|
||||
assert.equal(harness.calls.delete.length, 0);
|
||||
|
||||
const comments = harness.getComments();
|
||||
assert.match(
|
||||
comments.find(comment => comment.id === 3).body,
|
||||
/<!-- claude-review-auto-abcdef0 -->\nrefreshed body/);
|
||||
assertObsoleteComment(
|
||||
comments.find(comment => comment.id === 4),
|
||||
'<!-- claude-review-auto -->\nlegacy body');
|
||||
});
|
||||
|
||||
test(
|
||||
'creates a new comment if the target disappears before update',
|
||||
async () => {
|
||||
const missing = new Error('gone');
|
||||
missing.status = 404;
|
||||
const harness = createHarness(
|
||||
[
|
||||
makeComment(
|
||||
10, '<!-- claude-review-auto-abcdef0 -->\nold body',
|
||||
'2026-04-20T00:00:00Z'),
|
||||
],
|
||||
{
|
||||
updateErrors: {
|
||||
10: missing,
|
||||
},
|
||||
});
|
||||
|
||||
await postPrComment({
|
||||
github: harness.github,
|
||||
context,
|
||||
core: createCore(),
|
||||
prNumber: 14659,
|
||||
body: 'replacement body',
|
||||
marker: '<!-- claude-review-auto-abcdef0 -->',
|
||||
});
|
||||
|
||||
assert.equal(harness.calls.update.length, 1);
|
||||
assert.equal(harness.calls.create.length, 1);
|
||||
assert.match(
|
||||
harness.calls.create[0].body, /<!-- claude-review-auto-abcdef0 -->/);
|
||||
});
|
||||
|
||||
test(
|
||||
'ignores 404 when superseding a comment already deleted by another run',
|
||||
async () => {
|
||||
const missing = new Error('gone');
|
||||
missing.status = 404;
|
||||
const harness = createHarness(
|
||||
[
|
||||
makeComment(
|
||||
20, '<!-- claude-review-auto-oldest -->\noldest',
|
||||
'2026-04-20T00:00:00Z'),
|
||||
makeComment(
|
||||
21, '<!-- claude-review-auto-newer -->\nnewer',
|
||||
'2026-04-21T00:00:00Z'),
|
||||
],
|
||||
{
|
||||
nextCommentId: 30,
|
||||
createTimestamp: '2026-04-24T00:00:00Z',
|
||||
deleteErrors: {
|
||||
20: missing,
|
||||
},
|
||||
});
|
||||
|
||||
await postPrComment({
|
||||
github: harness.github,
|
||||
context,
|
||||
core: createCore(),
|
||||
prNumber: 14659,
|
||||
body: 'fresh body',
|
||||
marker: '<!-- claude-review-auto-latest -->',
|
||||
prunePrefix: '<!-- claude-review-auto-',
|
||||
preserveLatest: 1,
|
||||
obsoleteMarker: OBSOLETE_MARKER,
|
||||
obsoleteTitle: OBSOLETE_TITLE,
|
||||
});
|
||||
|
||||
assert.equal(harness.calls.create.length, 1);
|
||||
assert.equal(harness.calls.delete.length, 0);
|
||||
assert.deepEqual(
|
||||
harness.calls.update.map(call => call.comment_id), [21, 20]);
|
||||
|
||||
const comments = harness.getComments();
|
||||
assertObsoleteComment(
|
||||
comments.find(comment => comment.id === 21),
|
||||
'<!-- claude-review-auto-newer -->\nnewer');
|
||||
});
|
||||
|
||||
test(
|
||||
'supersedes the current review when a newer concurrent one appears',
|
||||
async () => {
|
||||
const harness = createHarness(
|
||||
[
|
||||
makeComment(
|
||||
40, '<!-- claude-review-auto-current -->\ncurrent',
|
||||
'2026-04-20T00:00:00Z'),
|
||||
makeComment(
|
||||
41, '<!-- claude-review-auto-older -->\nolder',
|
||||
'2026-04-19T00:00:00Z'),
|
||||
],
|
||||
{
|
||||
updateTimestamp: '2026-04-24T00:00:00Z',
|
||||
onPaginate: ({paginateCount, comments}) => {
|
||||
if (paginateCount !== 2) {
|
||||
return comments;
|
||||
}
|
||||
return comments.concat([
|
||||
makeComment(
|
||||
42, '<!-- claude-review-auto-newer -->\nnewer',
|
||||
'2026-04-25T00:00:00Z'),
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
await postPrComment({
|
||||
github: harness.github,
|
||||
context,
|
||||
core: createCore(),
|
||||
prNumber: 14659,
|
||||
body: 'updated current body',
|
||||
marker: '<!-- claude-review-auto-current -->',
|
||||
prunePrefix: '<!-- claude-review-auto-',
|
||||
preserveLatest: 1,
|
||||
obsoleteMarker: OBSOLETE_MARKER,
|
||||
obsoleteTitle: OBSOLETE_TITLE,
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
harness.calls.update.map(call => call.comment_id), [40, 40, 41]);
|
||||
assert.equal(harness.calls.delete.length, 0);
|
||||
|
||||
const comments = harness.getComments();
|
||||
assert.match(
|
||||
comments.find(comment => comment.id === 42).body,
|
||||
/<!-- claude-review-auto-newer -->\nnewer/);
|
||||
assertObsoleteComment(
|
||||
comments.find(comment => comment.id === 40),
|
||||
'<!-- claude-review-auto-current -->\nupdated current body');
|
||||
assertObsoleteComment(
|
||||
comments.find(comment => comment.id === 41),
|
||||
'<!-- claude-review-auto-older -->\nolder');
|
||||
});
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,203 +0,0 @@
|
||||
# Shared comment-posting workflow for AI reviews.
|
||||
|
||||
name: AI Review Comment
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
provider:
|
||||
description: Provider key, for example "claude" or "codex"
|
||||
required: true
|
||||
type: string
|
||||
result_artifact_name:
|
||||
description: Artifact name produced by the analysis workflow
|
||||
required: true
|
||||
type: string
|
||||
comment_file:
|
||||
description: Markdown comment file produced by the analysis workflow
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
if: github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout scripts
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: .github/scripts
|
||||
sparse-checkout-cone-mode: true
|
||||
|
||||
- name: Download review artifact
|
||||
id: download
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ inputs.result_artifact_name }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path: _artifact
|
||||
continue-on-error: true
|
||||
|
||||
- name: Post or update PR comment
|
||||
if: steps.download.outcome == 'success'
|
||||
env:
|
||||
PROVIDER: ${{ inputs.provider }}
|
||||
COMMENT_FILE: ${{ inputs.comment_file }}
|
||||
RUN_ID: ${{ github.event.workflow_run.id }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const artifactDir = '_artifact';
|
||||
const commentFile = path.join(
|
||||
artifactDir,
|
||||
process.env.COMMENT_FILE
|
||||
);
|
||||
const prNumberFile = path.join(artifactDir, 'pr_number.txt');
|
||||
const triggerTypeFile = path.join(artifactDir, 'trigger_type.txt');
|
||||
const headShaFile = path.join(artifactDir, 'head_sha.txt');
|
||||
|
||||
if (!fs.existsSync(commentFile) ||
|
||||
!fs.existsSync(prNumberFile)) {
|
||||
core.info('No review results found; skipping.');
|
||||
return;
|
||||
}
|
||||
|
||||
const post = require('./.github/scripts/post-pr-comment.js');
|
||||
const provider = process.env.PROVIDER;
|
||||
const providerTitle = provider === 'codex' ? 'Codex' : 'Claude';
|
||||
const body = fs.readFileSync(commentFile, 'utf8');
|
||||
const prNumber = parseInt(
|
||||
fs.readFileSync(prNumberFile, 'utf8').trim(),
|
||||
10
|
||||
);
|
||||
const trigger = fs.existsSync(triggerTypeFile) ?
|
||||
fs.readFileSync(triggerTypeFile, 'utf8').trim() :
|
||||
'auto';
|
||||
const headSha = fs.existsSync(headShaFile) ?
|
||||
fs.readFileSync(headShaFile, 'utf8').trim() :
|
||||
'';
|
||||
const shortSha = headSha ? headSha.substring(0, 7) : '';
|
||||
const runId = process.env.RUN_ID;
|
||||
|
||||
let marker = '';
|
||||
let legacyMarkers = [];
|
||||
let prunePrefix = '';
|
||||
let preserveLatest = 0;
|
||||
let obsoleteMarker = '';
|
||||
let obsoleteTitle = '';
|
||||
|
||||
if (trigger === 'auto') {
|
||||
if (!shortSha) {
|
||||
core.warning(
|
||||
'Missing head_sha.txt for auto review; skipping comment.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
marker = `<!-- ${provider}-review-auto-run-${runId} -->`;
|
||||
legacyMarkers = [`<!-- ${provider}-review-auto -->`];
|
||||
prunePrefix = `<!-- ${provider}-review-auto-`;
|
||||
preserveLatest = 1;
|
||||
obsoleteMarker = `<!-- ${provider}-review-obsolete -->`;
|
||||
obsoleteTitle = `${providerTitle} Code Review - OBSOLETE`;
|
||||
} else {
|
||||
marker = `<!-- ${provider}-review-manual-run-${runId} -->`;
|
||||
}
|
||||
|
||||
await post({
|
||||
github,
|
||||
context,
|
||||
core,
|
||||
prNumber,
|
||||
body,
|
||||
marker,
|
||||
legacyMarkers,
|
||||
prunePrefix,
|
||||
preserveLatest,
|
||||
obsoleteMarker,
|
||||
obsoleteTitle,
|
||||
});
|
||||
|
||||
- name: Add reaction to trigger comment
|
||||
if: steps.download.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const artifactDir = '_artifact';
|
||||
const triggerTypeFile = path.join(artifactDir, 'trigger_type.txt');
|
||||
const commentIdFile = path.join(artifactDir, 'comment_id.txt');
|
||||
if (!fs.existsSync(triggerTypeFile)) return;
|
||||
const trigger = fs.readFileSync(triggerTypeFile, 'utf8').trim();
|
||||
if (trigger !== 'manual') return;
|
||||
if (!fs.existsSync(commentIdFile)) return;
|
||||
const commentId = parseInt(
|
||||
fs.readFileSync(commentIdFile, 'utf8').trim(),
|
||||
10
|
||||
);
|
||||
if (!commentId) return;
|
||||
|
||||
await github.rest.reactions.createForIssueComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: commentId,
|
||||
content: 'rocket'
|
||||
});
|
||||
|
||||
failure-notice:
|
||||
if: github.event.workflow_run.conclusion == 'failure'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifact for PR number
|
||||
id: download
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ inputs.result_artifact_name }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path: _artifact
|
||||
continue-on-error: true
|
||||
|
||||
- name: React with failure
|
||||
if: steps.download.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const commentIdFile = path.join('_artifact', 'comment_id.txt');
|
||||
if (!fs.existsSync(commentIdFile)) return;
|
||||
const commentId = parseInt(
|
||||
fs.readFileSync(commentIdFile, 'utf8').trim(),
|
||||
10
|
||||
);
|
||||
if (!commentId) return;
|
||||
|
||||
await github.rest.reactions.createForIssueComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: commentId,
|
||||
content: 'confused'
|
||||
});
|
||||
|
||||
unauthorized-notice:
|
||||
runs-on: ubuntu-latest
|
||||
if: >-
|
||||
github.event.workflow_run.event == 'issue_comment' &&
|
||||
github.event.workflow_run.conclusion == 'skipped'
|
||||
steps:
|
||||
- name: Log skipped unauthorized request
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.info(
|
||||
'Analysis workflow was skipped, which usually means the ' +
|
||||
'issue_comment requester was not in the authorized list.'
|
||||
);
|
||||
@@ -12,48 +12,47 @@ jobs:
|
||||
if: github.event.workflow_run.event == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout scripts
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: .github/scripts
|
||||
sparse-checkout-cone-mode: true
|
||||
|
||||
- name: Download clang-tidy results
|
||||
id: download
|
||||
uses: actions/download-artifact@v4.1.3
|
||||
uses: actions/download-artifact@v4.0.0
|
||||
with:
|
||||
name: clang-tidy-result
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path: _artifact
|
||||
continue-on-error: true
|
||||
|
||||
- name: Post or update PR comment
|
||||
if: steps.download.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
if (!fs.existsSync('_artifact/clang-tidy-comment.md') ||
|
||||
!fs.existsSync('_artifact/pr_number.txt')) {
|
||||
if (!fs.existsSync('clang-tidy-comment.md') || !fs.existsSync('pr_number.txt')) {
|
||||
core.info('No clang-tidy results found; skipping.');
|
||||
return;
|
||||
}
|
||||
const body = fs.readFileSync(
|
||||
'_artifact/clang-tidy-comment.md',
|
||||
'utf8'
|
||||
);
|
||||
const prNumber = parseInt(
|
||||
fs.readFileSync('_artifact/pr_number.txt', 'utf8').trim(),
|
||||
10
|
||||
);
|
||||
const post = require('./.github/scripts/post-pr-comment.js');
|
||||
|
||||
await post({
|
||||
github,
|
||||
context,
|
||||
core,
|
||||
prNumber,
|
||||
body,
|
||||
marker: '<!-- clang-tidy-bot -->',
|
||||
const body = fs.readFileSync('clang-tidy-comment.md', 'utf8');
|
||||
const prNumber = parseInt(fs.readFileSync('pr_number.txt', 'utf8').trim());
|
||||
const marker = '<!-- clang-tidy-bot -->';
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
});
|
||||
const existing = comments.find(c => c.body.includes(marker));
|
||||
if (existing) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: existing.id,
|
||||
body,
|
||||
});
|
||||
core.info(`Updated existing comment ${existing.id}`);
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
body,
|
||||
});
|
||||
core.info('Created new PR comment');
|
||||
}
|
||||
@@ -11,8 +11,7 @@ jobs:
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
options: --shm-size=8gb
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
with:
|
||||
@@ -37,14 +36,14 @@ jobs:
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
- name: Install clang-tidy
|
||||
if: steps.diff-base.outputs.skip != 'true'
|
||||
run: apt-get update && apt-get install -y clang-tidy-21 && ln -sf /usr/bin/clang-tidy-21 /usr/local/bin/clang-tidy
|
||||
run: apt-get update && apt-get install -y clang-tidy
|
||||
- name: Generate compile_commands.json
|
||||
if: steps.diff-base.outputs.skip != 'true'
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DCMAKE_C_COMPILER=clang-21 \
|
||||
-DCMAKE_CXX_COMPILER=clang++-21 ..
|
||||
-DCMAKE_C_COMPILER=clang-18 \
|
||||
-DCMAKE_CXX_COMPILER=clang++-18 ..
|
||||
cd ..
|
||||
ln -sf build/compile_commands.json compile_commands.json
|
||||
- name: Run clang-tidy on changed files
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# Claude Code Review — Comment Posting Workflow
|
||||
#
|
||||
# Thin wrapper around .github/workflows/ai-review-comment.yml so the provider
|
||||
# specific workflow name stays stable while the shared implementation lives in
|
||||
# one reusable workflow.
|
||||
|
||||
name: Post Claude Review Comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Claude Code Review"]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
review-comment:
|
||||
uses: ./.github/workflows/ai-review-comment.yml
|
||||
with:
|
||||
provider: claude
|
||||
result_artifact_name: claude-review-result
|
||||
comment_file: claude-review-comment.md
|
||||
@@ -1,69 +0,0 @@
|
||||
# Claude Code Review — Analysis Workflow
|
||||
#
|
||||
# Thin wrapper around .github/workflows/ai-review-analysis.yml so provider
|
||||
# specific triggers and workflow_dispatch inputs stay stable while the shared
|
||||
# implementation lives in one reusable workflow.
|
||||
|
||||
name: Claude Code Review
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["facebook/rocksdb/pr-jobs"]
|
||||
types: [completed]
|
||||
|
||||
# The early pull_request_target path is limited to same-repo PRs by the job
|
||||
# condition below. Fork PRs skip this path and rely on workflow_run instead.
|
||||
pull_request_target:
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: PR number to review
|
||||
required: true
|
||||
type: number
|
||||
model:
|
||||
description: Claude model to use (defaults to latest Opus)
|
||||
required: false
|
||||
type: choice
|
||||
options:
|
||||
- claude-opus-4-6
|
||||
- claude-sonnet-4-6
|
||||
default: claude-opus-4-6
|
||||
thinking_budget:
|
||||
description: Override MAX_THINKING_TOKENS (blank = auto-classify, capped at 24000)
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
# The shared analysis workflow polls check state, inspects prior runs, and
|
||||
# reads PR metadata. Keep those permissions read-only in the caller.
|
||||
actions: read
|
||||
checks: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
review:
|
||||
if: >-
|
||||
github.event_name != 'pull_request_target' ||
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: ./.github/workflows/ai-review-analysis.yml
|
||||
with:
|
||||
provider: claude
|
||||
display_name: Claude
|
||||
review_command: /claude-review
|
||||
query_command: /claude-query
|
||||
result_artifact_name: claude-review-result
|
||||
comment_file: claude-review-comment.md
|
||||
default_model: claude-opus-4-6
|
||||
selected_model: ${{ github.event_name == 'workflow_dispatch' && inputs.model || '' }}
|
||||
classifier_model: claude-sonnet-4-6
|
||||
recovery_model: claude-sonnet-4-6
|
||||
thinking_budget: ${{ github.event_name == 'workflow_dispatch' && inputs.thinking_budget || '' }}
|
||||
dispatch_pr_number: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || '' }}
|
||||
secrets: inherit
|
||||
@@ -1,24 +0,0 @@
|
||||
# Codex Code Review — Comment Posting Workflow
|
||||
#
|
||||
# Thin wrapper around .github/workflows/ai-review-comment.yml so the provider
|
||||
# specific workflow name stays stable while the shared implementation lives in
|
||||
# one reusable workflow.
|
||||
|
||||
name: Post Codex Review Comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Codex Code Review"]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
review-comment:
|
||||
uses: ./.github/workflows/ai-review-comment.yml
|
||||
with:
|
||||
provider: codex
|
||||
result_artifact_name: codex-review-result
|
||||
comment_file: codex-review-comment.md
|
||||
@@ -1,63 +0,0 @@
|
||||
# Codex Code Review — Analysis Workflow
|
||||
#
|
||||
# Thin wrapper around .github/workflows/ai-review-analysis.yml so provider
|
||||
# specific triggers and workflow_dispatch inputs stay stable while the shared
|
||||
# implementation lives in one reusable workflow.
|
||||
|
||||
name: Codex Code Review
|
||||
|
||||
on:
|
||||
# Automatic PR reviews are temporarily disabled while Codex authentication is
|
||||
# repaired. Manual review requests remain available through issue comments
|
||||
# and workflow_dispatch.
|
||||
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: PR number to review
|
||||
required: true
|
||||
type: number
|
||||
model:
|
||||
description: Codex model to use
|
||||
required: false
|
||||
type: choice
|
||||
options:
|
||||
- gpt-5.5
|
||||
- gpt-5.3-codex
|
||||
- gpt-5.2-codex
|
||||
default: gpt-5.5
|
||||
thinking_budget:
|
||||
description: Override MAX_THINKING_TOKENS (blank = auto-classify)
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
# The shared analysis workflow polls check state, inspects prior runs, and
|
||||
# reads PR metadata. Keep those permissions read-only in the caller.
|
||||
actions: read
|
||||
checks: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
review:
|
||||
if: >-
|
||||
github.event_name != 'pull_request_target' ||
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: ./.github/workflows/ai-review-analysis.yml
|
||||
with:
|
||||
provider: codex
|
||||
display_name: Codex
|
||||
review_command: /codex-review
|
||||
query_command: /codex-query
|
||||
result_artifact_name: codex-review-result
|
||||
comment_file: codex-review-comment.md
|
||||
default_model: gpt-5.5
|
||||
selected_model: ${{ github.event_name == 'workflow_dispatch' && inputs.model || '' }}
|
||||
thinking_budget: ${{ github.event_name == 'workflow_dispatch' && inputs.thinking_budget || '' }}
|
||||
dispatch_pr_number: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || '' }}
|
||||
secrets: inherit
|
||||
@@ -1,4 +1,4 @@
|
||||
name: facebook/rocksdb/nightly-candidate
|
||||
name: facebook/rocksdb/nightly
|
||||
on: workflow_dispatch
|
||||
permissions: {}
|
||||
jobs:
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
labels: arm64large
|
||||
container:
|
||||
image: ubuntu-2004:202111-02
|
||||
options: --shm-size=8gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
with:
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
env:
|
||||
TEST_TMPDIR: "/tmp/rocksdb_test_tmp"
|
||||
steps:
|
||||
@@ -41,41 +41,22 @@ jobs:
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: make V=1 -j32 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-clang-21-asan-ubsan-with-folly:
|
||||
build-linux-clang-18-asan-ubsan-with-folly:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
options: --shm-size=32gb
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
options: --shm-size=16gb
|
||||
env:
|
||||
CC: clang-21
|
||||
CXX: clang++-21
|
||||
CC: clang-18
|
||||
CXX: clang++-18
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/cache-getdeps-downloads"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- name: Build folly and dependencies
|
||||
run: |
|
||||
clean_path=()
|
||||
IFS=: read -ra path_entries <<< "$PATH"
|
||||
for entry in "${path_entries[@]}"; do
|
||||
if [[ "$entry" != "/usr/lib/ccache" ]]; then
|
||||
clean_path+=("$entry")
|
||||
fi
|
||||
done
|
||||
export PATH="$(IFS=:; echo "${clean_path[*]}")"
|
||||
ccache_bin="$(command -v ccache || true)"
|
||||
if [[ -n "$ccache_bin" && -x "$ccache_bin" ]]; then
|
||||
mv "$ccache_bin" "${ccache_bin}.disabled"
|
||||
fi
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
export USE_CCACHE=0
|
||||
export CCACHE_DISABLE=1
|
||||
make build_folly
|
||||
shell: bash
|
||||
- uses: "./.github/actions/build-folly"
|
||||
- run: LIB_MODE=static USE_CLANG=1 USE_FOLLY=1 COMPILE_WITH_UBSAN=1 COMPILE_WITH_ASAN=1 make -j32 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-cmake-with-folly:
|
||||
@@ -84,7 +65,7 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
@@ -103,7 +84,7 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
@@ -113,10 +94,11 @@ jobs:
|
||||
- run: "USE_FOLLY=1 LIB_MODE=static DEBUG_LEVEL=0 V=1 make -j20 release"
|
||||
- run: "(mkdir build && cd build && cmake -DUSE_FOLLY=1 -DWITH_GFLAGS=1 -DROCKSDB_BUILD_SHARED=0 -DCMAKE_BUILD_TYPE=Release .. && make VERBOSE=1 -j20 && ctest -j20)"
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-windows-msvc-avx2:
|
||||
build-windows-vs2022-avx2:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: windows-8-core
|
||||
runs-on: windows-2022
|
||||
env:
|
||||
CMAKE_GENERATOR: Visual Studio 17 2022
|
||||
CMAKE_PORTABLE: AVX2
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
@@ -140,17 +122,7 @@ jobs:
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: sudo apt-get update && sudo apt-get install -y build-essential libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev
|
||||
- run: sudo mount -o remount,size=16G /dev/shm
|
||||
- name: Ensure swap space
|
||||
run: |-
|
||||
if sudo swapon --show=NAME --noheadings --raw | grep -Fxq /swapfile; then
|
||||
echo "/swapfile is already active"
|
||||
else
|
||||
sudo dd bs=1048576 count=4096 if=/dev/zero of=/swapfile
|
||||
sudo chmod 600 /swapfile
|
||||
sudo mkswap /swapfile
|
||||
sudo swapon /swapfile
|
||||
fi
|
||||
sudo swapon --show
|
||||
- run: sudo dd bs=1048576 count=4096 if=/dev/zero of=/swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile
|
||||
- run: ulimit -S -n `ulimit -H -n` && make V=1 -j8 CRASH_TEST_EXT_ARGS='--duration=1800 --max_key=2500000' blackbox_crash_test_with_atomic_flush
|
||||
- run: rm -rf /dev/shm/rocksdb.*
|
||||
- run: ulimit -S -n `ulimit -H -n` && make V=1 -j8 CRASH_TEST_EXT_ARGS='--duration=1800 --max_key=2500000' blackbox_crash_test_with_multiops_wc_txn
|
||||
@@ -161,7 +133,7 @@ jobs:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=8gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
@@ -173,13 +145,13 @@ jobs:
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
options: --shm-size=8gb
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- name: Build rocksdb lib
|
||||
run: CC=clang-21 CXX=clang++-21 USE_CLANG=1 make -j4 static_lib
|
||||
run: CC=clang-18 CXX=clang++-18 USE_CLANG=1 make -j4 static_lib
|
||||
- name: Build fuzzers
|
||||
run: cd fuzz && make sst_file_writer_fuzzer db_fuzzer db_map_fuzzer
|
||||
- uses: "./.github/actions/post-steps"
|
||||
@@ -189,7 +161,7 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
|
||||
+102
-284
@@ -65,17 +65,13 @@ jobs:
|
||||
pip install https://files.pythonhosted.org/packages/fb/ac/3c04772acc0257f5730e83adb542b2603c1a62d1315010ab593a980af404/clang_format-21.1.2-py2.py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
|
||||
clang-format --version
|
||||
- name: Download clang-format-diff.py
|
||||
# Mirrored on the "third-party-deps" GitHub release; add/update via
|
||||
# https://github.com/facebook/rocksdb/releases/edit/third-party-deps
|
||||
run: wget --tries=3 --retry-on-host-error https://github.com/facebook/rocksdb/releases/download/third-party-deps/clang-format-diff.py
|
||||
run: wget https://rocksdb-deps.s3.us-west-2.amazonaws.com/llvm/llvm-project/release/12.x/clang/tools/clang-format/clang-format-diff.py
|
||||
- name: Check format
|
||||
run: VERBOSE_CHECK=1 make check-format
|
||||
- name: Compare buckify output
|
||||
run: make check-buck-targets
|
||||
- name: Simple source code checks
|
||||
run: make check-sources
|
||||
- name: Validate GitHub Actions YAML
|
||||
run: make check-workflow-yaml
|
||||
- name: Sanity check check_format_compatible.sh
|
||||
run: |-
|
||||
export TEST_TMPDIR=/dev/shm/rocksdb
|
||||
@@ -92,16 +88,11 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: build-linux
|
||||
- run: make V=1 J=32 -j32 check
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-cmake-mingw:
|
||||
if: needs.config.outputs.only_job == 'build-linux-cmake-mingw' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
@@ -109,14 +100,11 @@ jobs:
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
options: --shm-size=8gb
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: cmake-mingw
|
||||
- run: update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
|
||||
- name: Build cmake-mingw
|
||||
run: |-
|
||||
@@ -125,33 +113,26 @@ jobs:
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
mkdir build && cd build && cmake -DJNI=1 -DWITH_GFLAGS=OFF .. -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ -DCMAKE_SYSTEM_NAME=Windows && make -j4 rocksdb rocksdbjni
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-make-with-folly:
|
||||
if: needs.config.outputs.only_job == 'build-linux-make-with-folly' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on:
|
||||
labels: 32-core-ubuntu
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=64gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/cache-getdeps-downloads"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: make-with-folly
|
||||
- uses: "./.github/actions/cache-folly"
|
||||
id: cache-folly
|
||||
- uses: "./.github/actions/build-folly"
|
||||
with:
|
||||
cache-hit: ${{ steps.cache-folly.outputs.cache-hit }}
|
||||
- run: USE_FOLLY=1 LIB_MODE=static V=1 make -j64 check
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- run: USE_FOLLY=1 LIB_MODE=static V=1 make -j32 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-make-with-folly-lite-no-test:
|
||||
if: needs.config.outputs.only_job == 'build-linux-make-with-folly-lite-no-test' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
@@ -160,71 +141,47 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/cache-getdeps-downloads"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: make-folly-lite
|
||||
- run: USE_FOLLY_LITE=1 EXTRA_CXXFLAGS=-DGLOG_USE_GLOG_EXPORT V=1 make -j32 all
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-cmake-with-folly-coroutines:
|
||||
if: needs.config.outputs.only_job == 'build-linux-cmake-with-folly-coroutines' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on:
|
||||
labels: 32-core-ubuntu
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=64gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/cache-getdeps-downloads"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: cmake-folly-coroutines
|
||||
- uses: "./.github/actions/cache-folly"
|
||||
id: cache-folly
|
||||
- uses: "./.github/actions/build-folly"
|
||||
with:
|
||||
cache-hit: ${{ steps.cache-folly.outputs.cache-hit }}
|
||||
- run: "(mkdir build && cd build && cmake -DUSE_COROUTINES=1 -DWITH_GFLAGS=1 -DROCKSDB_BUILD_SHARED=0 -DPORTABLE=ON .. && make VERBOSE=1 -j64 && ctest -j64)"
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- run: "(mkdir build && cd build && cmake -DUSE_COROUTINES=1 -DWITH_GFLAGS=1 -DROCKSDB_BUILD_SHARED=0 .. && make VERBOSE=1 -j20 && ctest -j20)"
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-cmake-with-benchmark-no-thread-status:
|
||||
if: needs.config.outputs.only_job == 'build-linux-cmake-with-benchmark-no-thread-status' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shard: [0, 1, 2, 3]
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: cmake-benchmark
|
||||
- name: Build
|
||||
run: mkdir build && cd build && cmake -DWITH_GFLAGS=1 -DWITH_BENCHMARK=1 -DPORTABLE=ON -DCMAKE_CXX_FLAGS=-DNROCKSDB_THREAD_STATUS .. && make VERBOSE=1 -j20
|
||||
- name: Test shard ${{ matrix.shard }} of 4
|
||||
run: cd build && ctest -j20 -I ${{ matrix.shard }},,4
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- run: mkdir build && cd build && cmake -DWITH_GFLAGS=1 -DWITH_BENCHMARK=1 -DCMAKE_CXX_FLAGS=-DNROCKSDB_THREAD_STATUS .. && make VERBOSE=1 -j20 && ctest -j20
|
||||
- uses: "./.github/actions/post-steps"
|
||||
with:
|
||||
artifact-prefix: "${{ github.job }}-shard${{ matrix.shard }}"
|
||||
build-linux-encrypted_env-no_compression:
|
||||
if: needs.config.outputs.only_job == 'build-linux-encrypted_env-no_compression' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
@@ -232,17 +189,12 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: encrypted-env-no-compression
|
||||
- run: ENCRYPTED_ENV=1 ROCKSDB_DISABLE_SNAPPY=1 ROCKSDB_DISABLE_ZLIB=1 ROCKSDB_DISABLE_BZIP=1 ROCKSDB_DISABLE_LZ4=1 ROCKSDB_DISABLE_ZSTD=1 make V=1 J=32 -j32 check
|
||||
- run: "./sst_dump --help | grep -E -q 'Supported built-in compression types: kNoCompression$' # Verify no compiled in compression\n"
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ======================== Linux No Test Runs ======================= #
|
||||
build-linux-release:
|
||||
@@ -252,12 +204,9 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: release
|
||||
- run: make V=1 -j32 LIB_MODE=shared release
|
||||
- run: ls librocksdb.so
|
||||
- run: "./trace_analyzer --version" # A tool dependent on gflags that can run in release build
|
||||
@@ -274,8 +223,6 @@ jobs:
|
||||
- run: USE_RTTI=1 make V=1 -j32 release
|
||||
- run: ls librocksdb.a
|
||||
- run: if ./trace_analyzer --version; then false; else true; fi
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-clang-13-no_test_run:
|
||||
if: needs.config.outputs.only_job == 'build-linux-clang-13-no_test_run' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
@@ -288,83 +235,26 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: clang-13
|
||||
# FIXME: get back to "all microbench" targets
|
||||
- run: CC=clang-13 CXX=clang++-13 USE_CLANG=1 EXTRA_CXXFLAGS=-stdlib=libc++ EXTRA_LDFLAGS=-stdlib=libc++ make -j32 shared_lib
|
||||
- run: make clean
|
||||
# FIXME: get back to "release" target
|
||||
- run: CC=clang-13 CXX=clang++-13 USE_CLANG=1 EXTRA_CXXFLAGS=-stdlib=libc++ EXTRA_LDFLAGS=-stdlib=libc++ DEBUG_LEVEL=0 make -j32 shared_lib
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-clang-21-no_test_run:
|
||||
if: needs.config.outputs.only_job == 'build-linux-clang-21-no_test_run' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
build-linux-clang-18-no_test_run:
|
||||
if: needs.config.outputs.only_job == 'build-linux-clang-18-no_test_run' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
options: --shm-size=32gb
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: clang-21
|
||||
- run: CC=clang-21 CXX=clang++-21 USE_CLANG=1 make -j32 all microbench
|
||||
- run: CC=clang-18 CXX=clang++-18 USE_CLANG=1 make -j32 all microbench
|
||||
- run: make clean
|
||||
- run: CC=clang-21 CXX=clang++-21 USE_CLANG=1 DEBUG_LEVEL=0 make -j32 release
|
||||
- name: Install clang-format-21 for C API gen checks
|
||||
run: apt-get update && apt-get install -y clang-format-21
|
||||
- name: Check C API codegen (link-complete, backward-compatible, up to date)
|
||||
# Run the make target in STRICT mode so this core CI job HARD-FAILS rather
|
||||
# than silently skipping if a prerequisite (clang++, clang-format, or the
|
||||
# compat baseline ref) is ever missing. See `make check-c-api-gen`.
|
||||
env:
|
||||
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
PUSH_BEFORE_SHA: ${{ github.event.before }}
|
||||
run: |
|
||||
# The container checkout is owned by a different user, so git refuses to
|
||||
# operate on it ("dubious ownership") -- mark it safe for the `git fetch`
|
||||
# and the `git show` the compat checker runs.
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
git config --global --add safe.directory '*'
|
||||
|
||||
# A PR must preserve the API of its merge target, while a push must
|
||||
# preserve the API of the branch before the push. Comparing every event
|
||||
# with main produces false removals when a release branch predates APIs
|
||||
# added to main.
|
||||
case "$GITHUB_EVENT_NAME" in
|
||||
pull_request) api_compat_ref="$PR_BASE_SHA" ;;
|
||||
push) api_compat_ref="$PUSH_BEFORE_SHA" ;;
|
||||
*)
|
||||
echo "ERROR: unsupported event for C API compatibility: $GITHUB_EVENT_NAME" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$api_compat_ref" ]; then
|
||||
echo "ERROR: C API compatibility baseline is empty" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
zero_sha=0000000000000000000000000000000000000000
|
||||
if [ "$api_compat_ref" = "$zero_sha" ]; then
|
||||
# A newly created branch or tag has no prior ref state to preserve.
|
||||
api_compat_ref=HEAD
|
||||
else
|
||||
git fetch --no-tags --depth=1 origin "$api_compat_ref"
|
||||
api_compat_ref=FETCH_HEAD
|
||||
fi
|
||||
|
||||
CXX=clang++-21 make check-c-api-gen \
|
||||
CHECK_C_API_GEN_STRICT=1 \
|
||||
API_COMPAT_REF="$api_compat_ref" \
|
||||
CLANG_FORMAT_BINARY=clang-format-21
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- run: CC=clang-18 CXX=clang++-18 USE_CLANG=1 DEBUG_LEVEL=0 make -j32 release
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-gcc-14-no_test_run:
|
||||
if: needs.config.outputs.only_job == 'build-linux-gcc-14-no_test_run' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
@@ -372,20 +262,35 @@ jobs:
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
options: --shm-size=32gb
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: gcc-14
|
||||
- run: CC=gcc-14 CXX=g++-14 V=1 make -j32 all microbench
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
|
||||
# ======================== Linux Other Checks ======================= #
|
||||
build-linux-clang18-clang-analyze:
|
||||
if: needs.config.outputs.only_job == 'build-linux-clang18-clang-analyze' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: CC=clang-18 CXX=clang++-18 ROCKSDB_DISABLE_ALIGNED_NEW=1 CLANG_ANALYZER="/usr/bin/clang++-18" CLANG_SCAN_BUILD=scan-build-18 USE_CLANG=1 make V=1 -j32 analyze
|
||||
- uses: "./.github/actions/post-steps"
|
||||
- name: compress test report
|
||||
run: tar -cvzf scan_build_report.tar.gz scan_build_report
|
||||
if: failure()
|
||||
- uses: actions/upload-artifact@v4.0.0
|
||||
with:
|
||||
name: scan-build-report
|
||||
path: scan_build_report.tar.gz
|
||||
|
||||
build-linux-unity-and-headers:
|
||||
if: needs.config.outputs.only_job == 'build-linux-unity-and-headers' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
@@ -394,112 +299,54 @@ jobs:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: gcc:latest
|
||||
options: --shm-size=8gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- run: apt-get update -y && apt-get install -y libgflags-dev
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: unity-headers
|
||||
- name: Unity build
|
||||
run: make V=1 -j8 unity_test
|
||||
- run: make V=1 -j8 -k check-headers
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-mini-crashtest:
|
||||
if: needs.config.outputs.only_job == 'build-linux-mini-crashtest' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- crash_test_target: blackbox_crash_test_with_atomic_flush
|
||||
crash_duration: 480
|
||||
- crash_test_target: blackbox_crash_test
|
||||
crash_duration: 240
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=8gb --ulimit nofile=1048576:1048576
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/cache-getdeps-downloads"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: mini-crashtest
|
||||
- uses: "./.github/actions/cache-folly"
|
||||
id: cache-folly
|
||||
- uses: "./.github/actions/build-folly"
|
||||
with:
|
||||
cache-hit: ${{ steps.cache-folly.outputs.cache-hit }}
|
||||
- run: |
|
||||
ulimit -S -n $(ulimit -Hn) # Raise open files soft limit to hard limit
|
||||
echo "Updated ulimit -Hn: $(ulimit -Hn) -Sn: $(ulimit -Sn)"
|
||||
USE_COROUTINES=1 USE_FOLLY=1 LIB_MODE=static make V=1 -j8 CRASH_TEST_EXT_ARGS='--duration=${{ matrix.crash_duration }} --max_key=2500000' ${{ matrix.crash_test_target }}
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- run: ulimit -S -n `ulimit -H -n` && make V=1 -j8 CRASH_TEST_EXT_ARGS='--duration=960 --max_key=2500000' blackbox_crash_test_with_atomic_flush
|
||||
- uses: "./.github/actions/post-steps"
|
||||
with:
|
||||
artifact-prefix: "${{ github.job }}-${{ matrix.crash_test_target }}"
|
||||
# ======================= Linux with Sanitizers ===================== #
|
||||
build-linux-clang21-asan-ubsan:
|
||||
if: needs.config.outputs.only_job == 'build-linux-clang21-asan-ubsan' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
build-linux-clang18-asan-ubsan:
|
||||
if: needs.config.outputs.only_job == 'build-linux-clang18-asan-ubsan' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on:
|
||||
labels: 32-core-ubuntu
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shard: [0, 1, 2]
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
options: --shm-size=64gb
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: clang21-asan-ubsan
|
||||
- run: COMPILE_WITH_ASAN=1 COMPILE_WITH_UBSAN=1 CC=clang-21 CXX=clang++-21 ROCKSDB_DISABLE_ALIGNED_NEW=1 USE_CLANG=1 make V=1 -j40 check
|
||||
env:
|
||||
CI_SHARD_INDEX: ${{ matrix.shard }}
|
||||
CI_TOTAL_SHARDS: 3
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- run: COMPILE_WITH_ASAN=1 COMPILE_WITH_UBSAN=1 CC=clang-18 CXX=clang++-18 ROCKSDB_DISABLE_ALIGNED_NEW=1 USE_CLANG=1 make V=1 -j40 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
with:
|
||||
artifact-prefix: "${{ github.job }}-shard${{ matrix.shard }}"
|
||||
build-linux-clang21-mini-tsan:
|
||||
if: needs.config.outputs.only_job == 'build-linux-clang21-mini-tsan' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
build-linux-clang18-mini-tsan:
|
||||
if: needs.config.outputs.only_job == 'build-linux-clang18-mini-tsan' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on:
|
||||
labels: 32-core-ubuntu
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shard: [0, 1, 2]
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
options: --shm-size=64gb
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: clang21-tsan
|
||||
- run: COMPILE_WITH_TSAN=1 CC=clang-21 CXX=clang++-21 ROCKSDB_DISABLE_ALIGNED_NEW=1 USE_CLANG=1 make V=1 -j32 check
|
||||
env:
|
||||
CI_SHARD_INDEX: ${{ matrix.shard }}
|
||||
CI_TOTAL_SHARDS: 3
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- run: COMPILE_WITH_TSAN=1 CC=clang-18 CXX=clang++-18 ROCKSDB_DISABLE_ALIGNED_NEW=1 USE_CLANG=1 make V=1 -j32 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
with:
|
||||
artifact-prefix: "${{ github.job }}-shard${{ matrix.shard }}"
|
||||
build-linux-static_lib-alt_namespace-status_checked:
|
||||
if: needs.config.outputs.only_job == 'build-linux-static_lib-alt_namespace-status_checked' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
@@ -507,16 +354,11 @@ jobs:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: static-alt-namespace
|
||||
- run: ASSERT_STATUS_CHECKED=1 TEST_UINT128_COMPAT=1 ROCKSDB_MODIFY_NPHASH=1 LIB_MODE=static OPT="-DROCKSDB_USE_STD_SEMAPHORES -DROCKSDB_NAMESPACE=alternative_rocksdb_ns" make V=1 -j24 check
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ========================= MacOS build only ======================== #
|
||||
build-macos:
|
||||
@@ -530,16 +372,11 @@ jobs:
|
||||
- uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: 16.4.0
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: macos
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
- name: Build
|
||||
run: ulimit -S -n `ulimit -H -n` && make V=1 J=16 -j8 all
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ========================= MacOS with Tests ======================== #
|
||||
build-macos-cmake:
|
||||
@@ -554,9 +391,6 @@ jobs:
|
||||
- uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: 16.4.0
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: macos-cmake
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
@@ -576,36 +410,19 @@ jobs:
|
||||
- name: Run shard 3 out of 4 test shards
|
||||
run: ulimit -S -n `ulimit -H -n` && cd build && ctest -j8 -I 3,,4
|
||||
if: ${{ matrix.run_sharded_tests == 3 }}
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ======================== Windows with Tests ======================= #
|
||||
# NOTE: some windows jobs are in "nightly" to save resources
|
||||
build-windows-msvc:
|
||||
if: needs.config.outputs.only_job == 'build-windows-msvc' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
build-windows-vs2022:
|
||||
if: needs.config.outputs.only_job == 'build-windows-vs2022' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on: windows-8-core
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- test_shard: db_test
|
||||
suite_run: db_test
|
||||
run_java: "false"
|
||||
- test_shard: other
|
||||
suite_run: arena_test,db_basic_test,db_etc2_test,db_merge_operand_test,bloom_test,c_test,coding_test,crc32c_test,dynamic_bloom_test,env_basic_test,env_test,hash_test,random_test
|
||||
run_java: "false"
|
||||
- test_shard: java
|
||||
suite_run: ""
|
||||
run_java: "true"
|
||||
env:
|
||||
CMAKE_GENERATOR: Visual Studio 17 2022
|
||||
CMAKE_PORTABLE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/windows-build-steps"
|
||||
with:
|
||||
suite-run: ${{ matrix.suite_run }}
|
||||
run-java: ${{ matrix.run_java }}
|
||||
# ============================ Java Jobs ============================ #
|
||||
build-linux-java:
|
||||
if: needs.config.outputs.only_job == 'build-linux-java' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
@@ -614,22 +431,31 @@ jobs:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=8gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
# The docker image is intentionally based on an OS that has an older GLIBC version.
|
||||
# That GLIBC is incompatibile with GitHub's actions/checkout. Thus we implement a manual checkout step.
|
||||
# NOTE: replaced evolvedbinary/rocksjava:centos7_x64-be with ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
# until a more appropriate docker image with C++20 support is made.
|
||||
- name: Checkout
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
chown `whoami` . || true
|
||||
git clone --no-checkout https://oath2:$GH_TOKEN@github.com/${{ github.repository }}.git .
|
||||
git -c protocol.version=2 fetch --update-head-ok --no-tags --prune --no-recurse-submodules --depth=1 origin +${{ github.sha }}:${{ github.ref }}
|
||||
git checkout --progress --force ${{ github.ref }}
|
||||
git log -1 --format='%H'
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: java
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- name: Test RocksDBJava
|
||||
# NOTE: replaced scl enable devtoolset-7 'make V=1 J=8 -j8 jtest'
|
||||
run: make V=1 J=8 -j8 jtest
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
# post-steps skipped because of compatibility issues with docker image
|
||||
build-linux-java-static:
|
||||
if: needs.config.outputs.only_job == 'build-linux-java-static' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
@@ -637,39 +463,46 @@ jobs:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=8gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
# The docker image is intentionally based on an OS that has an older GLIBC version.
|
||||
# That GLIBC is incompatibile with GitHub's actions/checkout. Thus we implement a manual checkout step.
|
||||
# NOTE: replaced evolvedbinary/rocksjava:centos7_x64-be with ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
# until a more appropriate docker image with C++20 support is made.
|
||||
- name: Checkout
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
chown `whoami` . || true
|
||||
git clone --no-checkout https://oath2:$GH_TOKEN@github.com/${{ github.repository }}.git .
|
||||
git -c protocol.version=2 fetch --update-head-ok --no-tags --prune --no-recurse-submodules --depth=1 origin +${{ github.sha }}:${{ github.ref }}
|
||||
git checkout --progress --force ${{ github.ref }}
|
||||
git log -1 --format='%H'
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: java-static
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- name: Build RocksDBJava Static Library
|
||||
# NOTE: replaced scl enable devtoolset-7 'make V=1 J=8 -j8 rocksdbjavastatic'
|
||||
run: make V=1 J=8 -j8 rocksdbjavastatic
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
# post-steps skipped because of compatibility issues with docker image
|
||||
build-macos-java:
|
||||
if: needs.config.outputs.only_job == 'build-macos-java' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on: macos-15-xlarge
|
||||
env:
|
||||
JAVA_HOME: "/Library/Java/JavaVirtualMachines/liberica-jdk-8.jdk/Contents/Home"
|
||||
ROCKSDB_DISABLE_JEMALLOC: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: 16.4.0
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: macos-java
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/setup-jdk-on-macos"
|
||||
- uses: "./.github/actions/install-jdk8-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
@@ -678,24 +511,21 @@ jobs:
|
||||
which javac && javac -version
|
||||
- name: Test RocksDBJava
|
||||
run: make V=1 J=16 -j16 jtest
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-macos-java-static:
|
||||
if: needs.config.outputs.only_job == 'build-macos-java-static' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on: macos-15-xlarge
|
||||
env:
|
||||
JAVA_HOME: "/Library/Java/JavaVirtualMachines/liberica-jdk-8.jdk/Contents/Home"
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: 16.4.0
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: macos-java-static
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/setup-jdk-on-macos"
|
||||
- uses: "./.github/actions/install-jdk8-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
@@ -704,24 +534,21 @@ jobs:
|
||||
which javac && javac -version
|
||||
- name: Build RocksDBJava x86 and ARM Static Libraries
|
||||
run: make V=1 J=16 -j16 rocksdbjavastaticosx
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-macos-java-static-universal:
|
||||
if: needs.config.outputs.only_job == 'build-macos-java-static-universal' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
needs: config
|
||||
runs-on: macos-15-xlarge
|
||||
env:
|
||||
JAVA_HOME: "/Library/Java/JavaVirtualMachines/liberica-jdk-8.jdk/Contents/Home"
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: 16.4.0
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: macos-java-static-universal
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/setup-jdk-on-macos"
|
||||
- uses: "./.github/actions/install-jdk8-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
@@ -730,8 +557,6 @@ jobs:
|
||||
which javac && javac -version
|
||||
- name: Build RocksDBJava Universal Binary Static Library
|
||||
run: make V=1 J=16 -j16 rocksdbjavastaticosx_ub
|
||||
- uses: "./.github/actions/teardown-ccache"
|
||||
if: always()
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-java-pmd:
|
||||
if: needs.config.outputs.only_job == 'build-linux-java-pmd' || (needs.config.outputs.only_job == '' && github.repository_owner == 'facebook')
|
||||
@@ -740,7 +565,7 @@ jobs:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: evolvedbinary/rocksjava:alpine3_x64-be
|
||||
options: --shm-size=8gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/install-maven"
|
||||
@@ -768,13 +593,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: sudo apt-get update && sudo apt-get install -y build-essential ccache
|
||||
- uses: "./.github/actions/setup-ccache"
|
||||
with:
|
||||
cache-key-prefix: arm
|
||||
- run: sudo apt-get update && sudo apt-get install -y build-essential
|
||||
- run: ROCKSDBTESTS_PLATFORM_DEPENDENT=only make V=1 J=4 -j4 all_but_some_tests check_some
|
||||
- name: Print ccache stats
|
||||
run: ccache -s
|
||||
if: always()
|
||||
shell: bash
|
||||
- uses: "./.github/actions/post-steps"
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
timeout-minutes: 840
|
||||
container:
|
||||
image: ghcr.io/facebook/rocksdb_ubuntu:22.1
|
||||
options: --shm-size=32gb
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
|
||||
+1
-13
@@ -1,7 +1,5 @@
|
||||
make_config.mk
|
||||
rocksdb.pc
|
||||
.build_signature
|
||||
build_tools/__pycache__/
|
||||
|
||||
*.a
|
||||
*.arc
|
||||
@@ -54,7 +52,7 @@ GRTAGS
|
||||
GTAGS
|
||||
rocksdb_dump
|
||||
rocksdb_undump
|
||||
db_etc2_test
|
||||
db_test2
|
||||
trace_analyzer
|
||||
block_cache_trace_analyzer
|
||||
io_tracer_parser
|
||||
@@ -90,8 +88,6 @@ fbcode/
|
||||
fbcode
|
||||
buckifier/*.pyc
|
||||
buckifier/__pycache__
|
||||
tools/__pycache__/
|
||||
tools/c_api_gen/__pycache__/
|
||||
.arcconfig
|
||||
|
||||
compile_commands.json
|
||||
@@ -106,11 +102,3 @@ cmake-build-*
|
||||
third-party/folly/
|
||||
.cache
|
||||
*.sublime-*
|
||||
|
||||
# Claude Code local settings
|
||||
.claude/settings.local.json
|
||||
|
||||
tools/__pycache__/
|
||||
# Keep documentation trackable even if broader ignores match names like "*_test".
|
||||
!docs/
|
||||
!docs/**
|
||||
@@ -1,9 +0,0 @@
|
||||
# Agent Instructions
|
||||
|
||||
This repository's authoritative agent instructions live in `CLAUDE.md`.
|
||||
|
||||
Read and follow [`CLAUDE.md`](./CLAUDE.md) in full before making changes or
|
||||
reviewing code in this checkout.
|
||||
|
||||
If there is any ambiguity between this file and `CLAUDE.md`, `CLAUDE.md` takes
|
||||
precedence.
|
||||
@@ -32,15 +32,12 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"db/blob/blob_file_cache.cc",
|
||||
"db/blob/blob_file_garbage.cc",
|
||||
"db/blob/blob_file_meta.cc",
|
||||
"db/blob/blob_file_partition_manager.cc",
|
||||
"db/blob/blob_file_reader.cc",
|
||||
"db/blob/blob_garbage_meter.cc",
|
||||
"db/blob/blob_gen2_format.cc",
|
||||
"db/blob/blob_log_format.cc",
|
||||
"db/blob/blob_log_sequential_reader.cc",
|
||||
"db/blob/blob_log_writer.cc",
|
||||
"db/blob/blob_source.cc",
|
||||
"db/blob/blob_write_batch_transformer.cc",
|
||||
"db/blob/prefetch_buffer_collection.cc",
|
||||
"db/builder.cc",
|
||||
"db/c.cc",
|
||||
@@ -59,7 +56,6 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"db/compaction/sst_partitioner.cc",
|
||||
"db/compaction/subcompaction_state.cc",
|
||||
"db/convenience.cc",
|
||||
"db/coro_db.cc",
|
||||
"db/db_filesnapshot.cc",
|
||||
"db/db_impl/compacted_db_impl.cc",
|
||||
"db/db_impl/db_impl.cc",
|
||||
@@ -96,7 +92,6 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"db/merge_operator.cc",
|
||||
"db/multi_scan.cc",
|
||||
"db/output_validator.cc",
|
||||
"db/periodic_compaction_phaser.cc",
|
||||
"db/periodic_task_scheduler.cc",
|
||||
"db/range_del_aggregator.cc",
|
||||
"db/range_tombstone_fragmenter.cc",
|
||||
@@ -105,17 +100,14 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"db/snapshot_impl.cc",
|
||||
"db/table_cache.cc",
|
||||
"db/table_properties_collector.cc",
|
||||
"db/transaction_log_impl.cc",
|
||||
"db/trim_history_scheduler.cc",
|
||||
"db/version_builder.cc",
|
||||
"db/version_edit.cc",
|
||||
"db/version_edit_handler.cc",
|
||||
"db/version_set.cc",
|
||||
"db/version_util.cc",
|
||||
"db/wal_edit.cc",
|
||||
"db/wal_iterator_impl.cc",
|
||||
"db/wal_manager.cc",
|
||||
"db/wide/lazy_wide_columns.cc",
|
||||
"db/wide/read_path_blob_resolver.cc",
|
||||
"db/wide/wide_column_serialization.cc",
|
||||
"db/wide/wide_columns.cc",
|
||||
"db/wide/wide_columns_helper.cc",
|
||||
@@ -206,7 +198,6 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"table/block_based/block_cache.cc",
|
||||
"table/block_based/block_prefetcher.cc",
|
||||
"table/block_based/block_prefix_index.cc",
|
||||
"table/block_based/builtin_index_factory.cc",
|
||||
"table/block_based/data_block_footer.cc",
|
||||
"table/block_based/data_block_hash_index.cc",
|
||||
"table/block_based/filter_block_reader_common.cc",
|
||||
@@ -216,7 +207,6 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"table/block_based/hash_index_reader.cc",
|
||||
"table/block_based/index_builder.cc",
|
||||
"table/block_based/index_reader_common.cc",
|
||||
"table/block_based/multi_scan_index_iterator.cc",
|
||||
"table/block_based/parsed_full_filter_block.cc",
|
||||
"table/block_based/partitioned_filter_block.cc",
|
||||
"table/block_based/partitioned_index_iterator.cc",
|
||||
@@ -241,7 +231,6 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"table/plain/plain_table_index.cc",
|
||||
"table/plain/plain_table_key_coding.cc",
|
||||
"table/plain/plain_table_reader.cc",
|
||||
"table/range_del_block.cc",
|
||||
"table/sst_file_dumper.cc",
|
||||
"table/sst_file_reader.cc",
|
||||
"table/sst_file_writer.cc",
|
||||
@@ -273,7 +262,6 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"util/compression.cc",
|
||||
"util/compression_context_cache.cc",
|
||||
"util/concurrent_task_limiter_impl.cc",
|
||||
"util/coro_stats_util.cc",
|
||||
"util/crc32c.cc",
|
||||
"util/crc32c_arm64.cc",
|
||||
"util/data_structure.cc",
|
||||
@@ -312,7 +300,6 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"utilities/compaction_filters.cc",
|
||||
"utilities/compaction_filters/remove_emptyvalue_compactionfilter.cc",
|
||||
"utilities/convenience/info_log_finder.cc",
|
||||
"utilities/copy_engine/copy_engine.cc",
|
||||
"utilities/counted_fs.cc",
|
||||
"utilities/debug.cc",
|
||||
"utilities/env_mirror.cc",
|
||||
@@ -342,7 +329,6 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"utilities/secondary_index/simple_secondary_index.cc",
|
||||
"utilities/simulator_cache/cache_simulator.cc",
|
||||
"utilities/simulator_cache/sim_cache.cc",
|
||||
"utilities/sorted_run_builder/sorted_run_builder.cc",
|
||||
"utilities/table_properties_collectors/compact_for_tiering_collector.cc",
|
||||
"utilities/table_properties_collectors/compact_on_deletion_collector.cc",
|
||||
"utilities/trace/file_trace_reader_writer.cc",
|
||||
@@ -376,9 +362,6 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"utilities/transactions/write_prepared_txn_db.cc",
|
||||
"utilities/transactions/write_unprepared_txn.cc",
|
||||
"utilities/transactions/write_unprepared_txn_db.cc",
|
||||
"utilities/trie_index/bitvector.cc",
|
||||
"utilities/trie_index/louds_trie.cc",
|
||||
"utilities/trie_index/trie_index_factory.cc",
|
||||
"utilities/ttl/db_ttl_impl.cc",
|
||||
"utilities/types_util.cc",
|
||||
"utilities/wal_filter.cc",
|
||||
@@ -386,21 +369,11 @@ cpp_library_wrapper(name="rocksdb_lib", srcs=[
|
||||
"utilities/write_batch_with_index/write_batch_with_index_internal.cc",
|
||||
], deps=[
|
||||
"//folly/container:f14_hash",
|
||||
"//folly/coro:baton",
|
||||
"//folly/coro:blocking_wait",
|
||||
"//folly/coro:collect",
|
||||
"//folly/coro:coroutine",
|
||||
"//folly/coro:nothrow",
|
||||
"//folly/coro:task",
|
||||
"//folly/executors/thread_factory:named_thread_factory",
|
||||
"//folly/executors:io_executor",
|
||||
"//folly/executors:io_thread_pool_executor",
|
||||
"//folly/io/async:async_base",
|
||||
"//folly/io/async:event_base_manager",
|
||||
"//folly/io/async:io_uring_backend",
|
||||
"//folly/io/async:request_context",
|
||||
"//folly/experimental/coro:blocking_wait",
|
||||
"//folly/experimental/coro:collect",
|
||||
"//folly/experimental/coro:coroutine",
|
||||
"//folly/experimental/coro:task",
|
||||
"//folly/synchronization:distributed_mutex",
|
||||
"//folly:executor",
|
||||
], headers=glob(["**/*.h"]), link_whole=False, extra_test_libs=False)
|
||||
|
||||
cpp_library_wrapper(name="rocksdb_whole_archive_lib", srcs=[], deps=[":rocksdb_lib"], headers=[], link_whole=True, extra_test_libs=False)
|
||||
@@ -416,27 +389,13 @@ cpp_library_wrapper(name="rocksdb_test_lib", srcs=[
|
||||
"table/mock_table.cc",
|
||||
"test_util/mock_time_env.cc",
|
||||
"test_util/secondary_cache_test_util.cc",
|
||||
"test_util/simple_external_table_factory.cc",
|
||||
"test_util/testharness.cc",
|
||||
"test_util/testutil.cc",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.cc",
|
||||
"tools/trace_analyzer_tool.cc",
|
||||
"utilities/agg_merge/test_agg_merge.cc",
|
||||
"utilities/cassandra/test_utils.cc",
|
||||
], deps=[":rocksdb_lib"], headers=[
|
||||
"db/db_test_util.h",
|
||||
"db/db_with_timestamp_test_util.h",
|
||||
"table/mock_table.h",
|
||||
"test_util/mock_time_env.h",
|
||||
"test_util/secondary_cache_test_util.h",
|
||||
"test_util/simple_external_table_factory.h",
|
||||
"test_util/testharness.h",
|
||||
"test_util/testutil.h",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.h",
|
||||
"tools/trace_analyzer_tool.h",
|
||||
"utilities/agg_merge/test_agg_merge.h",
|
||||
"utilities/cassandra/test_utils.h",
|
||||
], link_whole=False, extra_test_libs=True)
|
||||
], deps=[":rocksdb_lib"], headers=[], link_whole=False, extra_test_libs=True)
|
||||
|
||||
cpp_library_wrapper(name="rocksdb_with_faiss_test_lib", srcs=[
|
||||
"db/db_test_util.cc",
|
||||
@@ -444,27 +403,13 @@ cpp_library_wrapper(name="rocksdb_with_faiss_test_lib", srcs=[
|
||||
"table/mock_table.cc",
|
||||
"test_util/mock_time_env.cc",
|
||||
"test_util/secondary_cache_test_util.cc",
|
||||
"test_util/simple_external_table_factory.cc",
|
||||
"test_util/testharness.cc",
|
||||
"test_util/testutil.cc",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.cc",
|
||||
"tools/trace_analyzer_tool.cc",
|
||||
"utilities/agg_merge/test_agg_merge.cc",
|
||||
"utilities/cassandra/test_utils.cc",
|
||||
], deps=[":rocksdb_with_faiss_lib"], headers=[
|
||||
"db/db_test_util.h",
|
||||
"db/db_with_timestamp_test_util.h",
|
||||
"table/mock_table.h",
|
||||
"test_util/mock_time_env.h",
|
||||
"test_util/secondary_cache_test_util.h",
|
||||
"test_util/simple_external_table_factory.h",
|
||||
"test_util/testharness.h",
|
||||
"test_util/testutil.h",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.h",
|
||||
"tools/trace_analyzer_tool.h",
|
||||
"utilities/agg_merge/test_agg_merge.h",
|
||||
"utilities/cassandra/test_utils.h",
|
||||
], link_whole=False, extra_test_libs=True)
|
||||
], deps=[":rocksdb_with_faiss_lib"], headers=[], link_whole=False, extra_test_libs=True)
|
||||
|
||||
cpp_library_wrapper(name="rocksdb_tools_lib", srcs=[
|
||||
"test_util/testutil.cc",
|
||||
@@ -473,12 +418,7 @@ cpp_library_wrapper(name="rocksdb_tools_lib", srcs=[
|
||||
"tools/simulated_hybrid_file_system.cc",
|
||||
"tools/tool_hooks.cc",
|
||||
"tools/trace_analyzer_tool.cc",
|
||||
], deps=[":rocksdb_lib"], headers=[
|
||||
"test_util/testutil.h",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.h",
|
||||
"tools/simulated_hybrid_file_system.h",
|
||||
"tools/trace_analyzer_tool.h",
|
||||
], link_whole=False, extra_test_libs=False)
|
||||
], deps=[":rocksdb_lib"], headers=[], link_whole=False, extra_test_libs=False)
|
||||
|
||||
cpp_library_wrapper(name="rocksdb_cache_bench_tools_lib", srcs=["cache/cache_bench_tool.cc"], deps=[":rocksdb_lib"], headers=[], link_whole=False, extra_test_libs=False)
|
||||
|
||||
@@ -502,28 +442,10 @@ rocks_cpp_library_wrapper(name="rocksdb_stress_lib", srcs=[
|
||||
"db_stress_tool/expected_value.cc",
|
||||
"db_stress_tool/multi_ops_txns_stress.cc",
|
||||
"db_stress_tool/no_batched_ops_stress.cc",
|
||||
"test_util/simple_external_table_factory.cc",
|
||||
"test_util/testutil.cc",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.cc",
|
||||
"tools/trace_analyzer_tool.cc",
|
||||
], headers=[
|
||||
"db_stress_tool/db_stress_common.h",
|
||||
"db_stress_tool/db_stress_compaction_service.h",
|
||||
"db_stress_tool/db_stress_compression_manager.h",
|
||||
"db_stress_tool/db_stress_driver.h",
|
||||
"db_stress_tool/db_stress_filters.h",
|
||||
"db_stress_tool/db_stress_listener.h",
|
||||
"db_stress_tool/db_stress_shared_state.h",
|
||||
"db_stress_tool/db_stress_test_base.h",
|
||||
"db_stress_tool/db_stress_wide_merge_operator.h",
|
||||
"db_stress_tool/expected_state.h",
|
||||
"db_stress_tool/expected_value.h",
|
||||
"db_stress_tool/multi_ops_txns_stress.h",
|
||||
"test_util/simple_external_table_factory.h",
|
||||
"test_util/testutil.h",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.h",
|
||||
"tools/trace_analyzer_tool.h",
|
||||
])
|
||||
], headers=[])
|
||||
|
||||
|
||||
cpp_binary_wrapper(name="ldb", srcs=["tools/ldb.cc"], deps=[":rocksdb_tools_lib"], extra_preprocessor_flags=[], extra_bench_libs=False)
|
||||
@@ -4667,12 +4589,6 @@ cpp_unittest_wrapper(name="bloom_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="builtin_index_factory_test",
|
||||
srcs=["table/block_based/builtin_index_factory_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="cache_reservation_manager_test",
|
||||
srcs=["cache/cache_reservation_manager_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
@@ -4813,13 +4729,6 @@ cpp_unittest_wrapper(name="compression_test",
|
||||
|
||||
cpp_unittest_wrapper(name="configurable_test",
|
||||
srcs=["options/configurable_test.cc"],
|
||||
source_headers=["options/configurable_test.h"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="copy_engine_test",
|
||||
srcs=["utilities/copy_engine/copy_engine_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
@@ -4890,12 +4799,6 @@ cpp_unittest_wrapper(name="db_blob_corruption_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_blob_direct_write_test",
|
||||
srcs=["db/blob/db_blob_direct_write_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_blob_index_test",
|
||||
srcs=["db/blob/db_blob_index_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
@@ -4950,12 +4853,6 @@ cpp_unittest_wrapper(name="db_encryption_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_etc2_test",
|
||||
srcs=["db/db_etc2_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_etc3_test",
|
||||
srcs=["db/db_etc3_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
@@ -5010,12 +4907,6 @@ cpp_unittest_wrapper(name="db_kv_checksum_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_lazy_entity_test",
|
||||
srcs=["db/wide/db_lazy_entity_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_log_iter_test",
|
||||
srcs=["db/db_log_iter_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
@@ -5046,12 +4937,6 @@ cpp_unittest_wrapper(name="db_merge_operator_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_open_with_config_test",
|
||||
srcs=["db/db_open_with_config_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_options_test",
|
||||
srcs=["db/db_options_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
@@ -5118,6 +5003,12 @@ cpp_unittest_wrapper(name="db_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_test2",
|
||||
srcs=["db/db_test2.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_universal_compaction_test",
|
||||
srcs=["db/db_universal_compaction_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
@@ -5136,12 +5027,6 @@ cpp_unittest_wrapper(name="db_wide_basic_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_wide_blob_direct_write_test",
|
||||
srcs=["db/wide/db_wide_blob_direct_write_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="db_with_timestamp_basic_test",
|
||||
srcs=["db/db_with_timestamp_basic_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
@@ -5252,12 +5137,6 @@ cpp_unittest_wrapper(name="faiss_ivf_index_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="fault_injection_fs_test",
|
||||
srcs=["utilities/fault_injection_fs_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="fault_injection_test",
|
||||
srcs=["db/fault_injection_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
@@ -5518,7 +5397,6 @@ cpp_unittest_wrapper(name="periodic_task_scheduler_test",
|
||||
|
||||
cpp_unittest_wrapper(name="persistent_cache_test",
|
||||
srcs=["utilities/persistent_cache/persistent_cache_test.cc"],
|
||||
source_headers=["utilities/persistent_cache/persistent_cache_test.h"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
@@ -5537,7 +5415,6 @@ cpp_unittest_wrapper(name="point_lock_manager_stress_test",
|
||||
|
||||
cpp_unittest_wrapper(name="point_lock_manager_test",
|
||||
srcs=["utilities/transactions/lock/point/point_lock_manager_test.cc"],
|
||||
source_headers=["utilities/transactions/lock/point/point_lock_manager_test.h"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
@@ -5644,12 +5521,6 @@ cpp_unittest_wrapper(name="slice_transform_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="sorted_run_builder_test",
|
||||
srcs=["utilities/sorted_run_builder/sorted_run_builder_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="sst_dump_test",
|
||||
srcs=["tools/sst_dump_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
@@ -5748,19 +5619,6 @@ cpp_unittest_wrapper(name="trace_analyzer_test",
|
||||
|
||||
cpp_unittest_wrapper(name="transaction_test",
|
||||
srcs=["utilities/transactions/transaction_test.cc"],
|
||||
source_headers=["utilities/transactions/transaction_test.h"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="trie_index_db_test",
|
||||
srcs=["utilities/trie_index/trie_index_db_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="trie_index_test",
|
||||
srcs=["utilities/trie_index/trie_index_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
@@ -5867,14 +5725,14 @@ cpp_unittest_wrapper(name="write_controller_test",
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="write_prepared_transaction_seqno_test",
|
||||
srcs=["utilities/transactions/write_prepared_transaction_seqno_test.cc"],
|
||||
cpp_unittest_wrapper(name="write_prepared_transaction_test",
|
||||
srcs=["utilities/transactions/write_prepared_transaction_test.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
|
||||
cpp_unittest_wrapper(name="write_prepared_transaction_test",
|
||||
srcs=["utilities/transactions/write_prepared_transaction_test.cc"],
|
||||
cpp_unittest_wrapper(name="write_prepared_transaction_test_seqno",
|
||||
srcs=["utilities/transactions/write_prepared_transaction_test_seqno.cc"],
|
||||
deps=[":rocksdb_test_lib"],
|
||||
extra_compiler_flags=[])
|
||||
|
||||
@@ -5886,5 +5744,3 @@ cpp_unittest_wrapper(name="write_unprepared_transaction_test",
|
||||
|
||||
|
||||
export_file(name = "tools/db_crashtest.py")
|
||||
|
||||
export_file(name = "tools/fault_injection_log_parser.py")
|
||||
@@ -14,12 +14,6 @@ This document provides guidance for generating and reviewing code in the RocksDB
|
||||
|
||||
**Error Handling:** Ensure robust error handling throughout the codebase. Use RocksDB's `Status` type consistently, propagate errors appropriately, and avoid silently ignoring failures. Reviewers pay close attention to edge cases and failure modes.
|
||||
|
||||
**Refactoring traps:** At least in production code, avoid constructs that could allow existing code to unexpectedly, quietly change meaning.
|
||||
Specifically:
|
||||
* Avoid new defaulted parameters. This is the #1 trap on refactoring!
|
||||
* Avoid static_cast, reinterpret_cast, and C-style casts; static_cast_with_check, up_cast, and lossless_cast from cast_util.h are preferred.
|
||||
* Avoid declared type `auto` (`auto&`, `auto*` OK).
|
||||
|
||||
### Testing Philosophy
|
||||
|
||||
**Comprehensive Coverage:** Every change should include appropriate test coverage. This includes unit tests for isolated functionality, integration tests for component interactions, and stress tests for concurrency and performance validation. Reviewers will ask for additional tests if coverage is insufficient.
|
||||
@@ -38,13 +32,13 @@ Specifically:
|
||||
|
||||
**Memory Copy:** Avoid unnecessary memory copies. Use move semantics, `std::string_view`, `Slice`, and pass-by-reference where appropriate. Be aware of implicit copies in STL containers and function returns. Prefer in-place operations over copy-and-modify patterns.
|
||||
|
||||
**CPU Cache Efficiency:** Design data structures and access patterns to be cache-friendly. Keep frequently accessed data together (data locality). Prefer sequential memory access over random access. Be mindful of cache line sizes (CACHE_LINE_SIZE, typically 64 bytes) and avoid false sharing in concurrent code (see CacheAlignedWrapper). Especially when adding new data members, be mindful of ordering within structs and classes to reduce unnecessary padding (special care with bool members) and avoid larger-than-necessary types (e.g. prefer OptSlice to std::optional<Slice>).
|
||||
**CPU Cache Efficiency:** Design data structures and access patterns to be cache-friendly. Keep frequently accessed data together (data locality). Prefer sequential memory access over random access. Be mindful of cache line sizes (typically 64 bytes) and avoid false sharing in concurrent code. Consider struct packing and field ordering to improve cache utilization.
|
||||
|
||||
**Loop Optimization:** Look for opportunities to collapse nested loops, reduce loop overhead, and minimize branch mispredictions. Hoist invariant computations out of loops. Consider loop unrolling for tight inner loops. Batch operations when possible to amortize per-operation overhead.
|
||||
|
||||
**SIMD and Vectorization:** Leverage SIMD instructions (SSE, AVX) for data-parallel operations when appropriate. Structure data to enable auto-vectorization by the compiler. Consider explicit SIMD intrinsics for critical hot paths like checksum computation, encoding/decoding, and bulk data processing.
|
||||
|
||||
**Branch Prediction:** Minimize unpredictable branches in hot paths. Use `LIKELY`/`UNLIKELY` macros to hint branch prediction, e.g. for error cases and other rare or otherwise costly cases, but NOT for predicting popular configurations. Consider branchless alternatives for simple conditionals. Order switch cases and if-else chains by frequency.
|
||||
**Branch Prediction:** Minimize unpredictable branches in hot paths. Use `LIKELY`/`UNLIKELY` macros to hint branch prediction. Consider branchless alternatives for simple conditionals. Order switch cases and if-else chains by frequency.
|
||||
|
||||
**Memory and Resource Management:** Be mindful of memory allocations, especially in hot paths. Use RAII patterns, smart pointers, and RocksDB's memory management utilities appropriately.
|
||||
|
||||
@@ -53,17 +47,15 @@ Specifically:
|
||||
- **Cold path** (executed rarely, e.g., DB open, configuration parsing, error handling): Maintainability and clarity are more important. Prefer readable code over micro-optimizations. Complex optimizations here add maintenance burden with negligible performance benefit.
|
||||
- **Warm path** (moderate frequency): Balance both concerns. Use profiling data to guide optimization decisions.
|
||||
|
||||
**Avoid Premature Optimization:** Performance is known critical in places like inner loops of compaction, read path and write path. Elsewhere, try to find a "holy trinity" solution of *correct, simple, and reasonably efficient*. More complex solutions are only appropriate when profiling/benchmarking data shows a measurable payoff.
|
||||
**Avoid Premature Optimization:** While performance is critical, focus on correctness first, then optimize based on profiling data. However, be performance-aware from the start—choosing the right algorithm and data structure upfront is not premature optimization. Use the hot path analysis above to decide how much optimization effort is warranted.
|
||||
|
||||
### API Design and Compatibility
|
||||
|
||||
**Backwards Compatibility:** RocksDB maintains strong backwards compatibility guarantees. Breaking changes are rare and require extensive justification. When deprecating features, follow the project's deprecation policy (typically spanning multiple releases).
|
||||
|
||||
**Behavioral Compatibility:** Behavior changes are human judgment calls that must be intentional, well-documented (including release notes), and well researched for potential downstream production impact. Agents and reviewers must call out potential gaps, ambiguity, or adverse impacts in intentionality, documentation, and production impact. For an existing accepted input—including an undocumented, discouraged, or historically ignored value—the analysis should compare old and new observable behavior, including performance and resource impact, identify known direct callers and stored configurations, and add or update regression coverage as appropriate.
|
||||
|
||||
**API Consistency:** New APIs should be consistent with existing patterns. Use similar naming conventions, parameter ordering, and return types. Reviewers will suggest changes to improve consistency with the broader codebase.
|
||||
|
||||
**Documentation:** Public APIs must be thoroughly documented, without unnecessary embelishment nor dwelling on implementation details nor project planning. When non-obvious, include usage examples, parameter descriptions, known bugs or limitations, notes on thread safety, performance characteristics, and compatibility considerations. Re-read comments for ambiguous terminology and phrasing, such as ambiguously re-purposed programming jargon.
|
||||
**Documentation:** Public APIs must be thoroughly documented. Include usage examples, parameter descriptions, and notes on thread safety, performance characteristics, and compatibility considerations.
|
||||
|
||||
---
|
||||
|
||||
@@ -81,7 +73,7 @@ The database core handles write-ahead logging (WAL), memtables, compaction, and
|
||||
|
||||
**Testing:** Database core changes require extensive testing, including unit tests, integration tests, and stress tests. Test with various configurations, compaction styles, and concurrent workloads.
|
||||
|
||||
### Public Headers / "Public API" (`include/rocksdb/`)
|
||||
### Public Headers (`include`)
|
||||
|
||||
Public headers define RocksDB's API surface. Changes here have the highest compatibility impact.
|
||||
|
||||
@@ -157,26 +149,6 @@ Cache management is critical for RocksDB's performance.
|
||||
|
||||
When reviewing RocksDB code (or preparing code for review), use this checklist:
|
||||
|
||||
### Contract Boundaries
|
||||
- [ ] Is each behavior owned by the right layer? High-level policy (for example,
|
||||
"compaction wants this I/O mode") should live at the caller/policy layer, while
|
||||
lower layers should expose generic mechanisms (for example, "open a fresh
|
||||
reader", "skip shared cache insertion", or "use these FileOptions").
|
||||
- [ ] Do comments and names describe local contracts rather than leaking a
|
||||
specific caller's rationale into reusable APIs? Generic code should not need to
|
||||
know about one current use case unless the API itself is intentionally
|
||||
use-case-specific.
|
||||
- [ ] Does each flag or parameter control one coherent behavior? If one boolean
|
||||
starts implying ownership, cache policy, I/O mode, prefetching, and caller
|
||||
identity, split it into explicit flags or an options struct.
|
||||
- [ ] Could a future caller use this lower-level API without accidentally
|
||||
inheriting assumptions from compaction, backup, user reads, or a particular
|
||||
table format? If not, tighten the contract with assertions, clearer names, or
|
||||
a narrower API.
|
||||
- [ ] Are implementation details not being used as policy signals? Prefer an
|
||||
explicit contract over inferring behavior from incidental fields such as file
|
||||
options, cache handles, or current table-reader state.
|
||||
|
||||
### Correctness
|
||||
- [ ] Does the change preserve database semantics (e.g., snapshot isolation, key ordering)?
|
||||
- [ ] Are all error cases handled appropriately?
|
||||
@@ -232,109 +204,18 @@ The following patterns emerged as frequent sources of review feedback:
|
||||
|
||||
10. **Platform Compatibility:** Ensure changes work correctly on all supported platforms (Linux, Windows, macOS) and with all supported compilers (GCC, Clang, MSVC).
|
||||
|
||||
11. **Contract Boundary Leaks:** When a change plumbs a new option or use-case
|
||||
specific behavior through multiple subsystems, review the call chain for
|
||||
contract leaks. Caller-specific rationale belongs at the call site or public API
|
||||
documentation; reusable layers should expose precise, layer-local capabilities.
|
||||
Watch especially for comments mentioning one caller in generic code, booleans
|
||||
that silently bundle several behaviors, and downstream code inferring policy
|
||||
from an implementation detail instead of an explicit option.
|
||||
|
||||
---
|
||||
|
||||
## Important tips
|
||||
|
||||
### Pull request and diff summaries
|
||||
* Before writing or updating an external RocksDB pull request summary or its
|
||||
corresponding internal Phabricator diff summary, read and follow
|
||||
`claude_md/pull_request_summary_guideline.md`.
|
||||
|
||||
### Build system
|
||||
* There are 3 build system. Make for git clones, BUCK (meta internal) for hg
|
||||
clones, and CMake for some special cases.
|
||||
* There are 3 build system. Make, CMake, BUCK(meta internal).
|
||||
* When a new .cc file is added, update Makefile, CMakeLists.txt, src.mk, BUCK.
|
||||
* Don't manually edit BUCK file, after updating src.mk, run
|
||||
/usr/local/bin/python3 buckifier/buckify_rocksdb.py to update it
|
||||
* Use make to build and run the test. CMake and BUCK are not used locally.
|
||||
* Use `make dbg` command to build all of the unit test in debug mode.
|
||||
* For -j in make command, use the number of CPU cores to decide it.
|
||||
* When searching for references to something (a symbol, library, etc.), do not
|
||||
restrict or truncate your search based on presumed relevance or scope. It is
|
||||
important and time-saving to keep the repo reasonably consistent across
|
||||
different build systems, programming languages, and even between
|
||||
documentation and implementation.
|
||||
|
||||
### Avoiding mixed build modes with Make (use `AUTO_CLEAN=1`)
|
||||
|
||||
Object files are written to the same paths regardless of build flags, so
|
||||
reusing objects from a prior build with different flags causes confusing
|
||||
linker errors, etc. This problem is essentially avoidable by ALWAYS using
|
||||
`AUTO_CLEAN=1 make -j<n> <something>` for manual make invocations. This
|
||||
will automatically clean object files if the build parameters/flavor have
|
||||
changed. The `build_tools/rockstest.sh` / `rocksptest.sh` helpers described
|
||||
below set `AUTO_CLEAN=1` for you.
|
||||
|
||||
`AUTO_CLEAN=1` does not fix Make failures associated with stale .d files
|
||||
referring to removed files. Resolve that manually or with `make clean`
|
||||
without complaining to the user.
|
||||
|
||||
### Source checks
|
||||
* Run `make check-sources` before committing. This catches non-ASCII
|
||||
characters in source files and other source-level issues that CI will
|
||||
reject. In particular, **do not use Unicode characters** (em dashes,
|
||||
smart quotes, etc.) in comments or strings -- use ASCII equivalents
|
||||
(`--` instead of em dash, `'` instead of smart quote, etc.).
|
||||
|
||||
### License headers
|
||||
* Every new source file needs a license header. For a file that does **not**
|
||||
carry an outside/third-party copyright, use the standard Meta dual-licensed
|
||||
header (the dual-license designation is required -- a bare
|
||||
"All Rights Reserved" copyright is not an acceptable open-source header):
|
||||
```
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
```
|
||||
Use a `#` comment prefix instead of `//` for shell, Python, and Makefile
|
||||
fragments.
|
||||
* Files derived from an external source (e.g. LevelDB) keep their original
|
||||
upstream copyright line in addition to the header above.
|
||||
|
||||
### RTTI and dynamic_cast
|
||||
* Production code and `db_stress` must build in **release mode
|
||||
(`-fno-rtti`)**. Do not use `dynamic_cast` anywhere except unit tests.
|
||||
Use `static_cast_with_check` from `util/cast_util.h` (validates with
|
||||
`dynamic_cast` in debug builds, plain `static_cast` in release).
|
||||
* Unit tests (`*_test.cc`) are built in debug mode with RTTI enabled.
|
||||
|
||||
### Cross-platform / portability
|
||||
Local `make` only exercises Linux with GCC/Clang, but CI
|
||||
(`.github/workflows/pr-jobs.yml` and `nightly.yml`) gates on a much wider
|
||||
matrix, so portability breaks are invisible locally until CI fails. Code must
|
||||
build (and where noted, run tests) across:
|
||||
|
||||
| Axis | Must support |
|
||||
|------|--------------|
|
||||
| OS | Linux (x86_64 + ARM), macOS, Windows |
|
||||
| Architecture | Little-endian and big-endian targets, including Linux on s390x |
|
||||
| Compiler | GCC, Clang (libstdc++ **and** libc++), AppleClang, **MSVC (VS2022)**, MinGW (Linux cross-compile, build-only, no gflags) |
|
||||
| Build system | Make, CMake, and BUCK (internal) -- keep all in sync (see "Build system" above) |
|
||||
| Config | release (`-fno-rtti`), `ASSERT_STATUS_CHECKED`, ASAN/UBSAN/TSAN, folly, unity build, JNI/Java |
|
||||
|
||||
Treat these as constraints to satisfy and infer the specifics from them before
|
||||
adding any system header, libc call, or compiler-specific construct. The most
|
||||
common trap: anything that compiles under GCC/Clang on Linux but not under
|
||||
**MSVC/MinGW** -- e.g. unguarded POSIX-only headers/functions (`<unistd.h>`,
|
||||
`<sys/*.h>`, `getpid`, `_exit`, ...) or GCC/Clang extensions
|
||||
(`__attribute__`, `__builtin_*`, VLAs, `alloca`). Prefer the `port::`/`Env`
|
||||
abstractions; otherwise guard with `#ifdef OS_WIN` (POSIX `<unistd.h>` ->
|
||||
Windows `<process.h>`). Because libc++ is also tested, include what you use
|
||||
rather than relying on libstdc++ transitive includes.
|
||||
|
||||
Do not use `static_assert` to reject a supported architecture for an optional
|
||||
feature. Check an existing `port::` capability such as `port::kLittleEndian`
|
||||
and disable only the unsupported feature so the rest of RocksDB still builds.
|
||||
Use a portable representation when the feature itself must work across
|
||||
architectures.
|
||||
|
||||
### Unit Test
|
||||
* After all of the unit tests are added, review them and try to extract common
|
||||
@@ -343,29 +224,9 @@ architectures.
|
||||
* Don't use sleep to wait for certain events to happen. This will cause test to
|
||||
be flaky. Instead, use sync point to synchronize thread progress.
|
||||
* Cap unit test execution with 60 seconds timeout.
|
||||
* To build and run unit tests locally, prefer these helper scripts:
|
||||
* `build_tools/rocksptest.sh <test_binary> [more_binaries...] [args...]`
|
||||
builds the binary(ies) with parallel make and `AUTO_CLEAN=1` and runs
|
||||
them under gtest-parallel, sharding the test cases across CPUs. Prefer
|
||||
this whenever running more than a couple of test cases, e.g.
|
||||
`build_tools/rocksptest.sh table_test` or
|
||||
`build_tools/rocksptest.sh db_test env_test --gtest_filter=*Foo*`.
|
||||
* `build_tools/rockstest.sh <test_binary> [args...]` builds with parallel
|
||||
make and `AUTO_CLEAN=1` and runs the binary directly (serially).
|
||||
Use it only for a very small number of test cases, e.g.
|
||||
`build_tools/rockstest.sh db_test --gtest_filter=*MixedSlowdown*`.
|
||||
* After writing a test, stress-test for flakiness (AUTO_CLEAN handles the
|
||||
rebuild needed by the `COERCE_CONTEXT_SWITCH=1` flag change):
|
||||
```bash
|
||||
COERCE_CONTEXT_SWITCH=1 build_tools/rockstest.sh {test_binary} -r100 \
|
||||
--gtest_filter="*YourTestName*"
|
||||
```
|
||||
* For CI-style flaky tests that do not reproduce with `gtest_parallel.py`,
|
||||
`--gtest_repeat`, or normal coerce-mode runs, inspect
|
||||
`tools/gtest_parallel_repro.py --help`.
|
||||
* Each unit test file has overheads, so avoid creating new unit test files
|
||||
for random minor features. Consider adding to slice_test, db_etc3_test, or
|
||||
others.
|
||||
* When there are multiple unit tests need to be executed, try to use
|
||||
gtest_parallel.py if available. E.g.
|
||||
python3 ${GTEST_PARALLEL}/gtest_parallel.py ./table_test
|
||||
|
||||
### Unit test dedup guidelines
|
||||
* Extract helper functions for repeated patterns such as object
|
||||
@@ -386,15 +247,9 @@ architectures.
|
||||
### Adding new public API
|
||||
Refer to claude_md/add_public_api.md
|
||||
|
||||
### Changing existing public API behavior
|
||||
Follow the Behavioral Compatibility requirements above.
|
||||
|
||||
### Adding new option
|
||||
Refer to claude_md/add_option.md
|
||||
|
||||
### Removing deprecated option
|
||||
Refer to claude_md/remove_option.md
|
||||
|
||||
### Metrics
|
||||
* When adding a new feature, evaluate whether there is opportunity to add
|
||||
metrics. Try to avoid causing performance regression on hot path when adding
|
||||
@@ -403,40 +258,19 @@ architectures.
|
||||
### Stress test
|
||||
* When adding a new feature, make sure stress test covers the new option.
|
||||
|
||||
### Component docs
|
||||
* For component-level design notes and implementation walkthroughs, start with
|
||||
`docs/components/index.md`.
|
||||
* Documentation under `docs/components/` is organized by subsystem in
|
||||
`docs/components/<area>/`.
|
||||
* Each subsystem directory should have an `index.md` entry point plus focused
|
||||
chapter files for deeper topics.
|
||||
|
||||
### DB bench update
|
||||
* When adding a performance related feature, support it in db_bench
|
||||
|
||||
### Adding release note
|
||||
* Release note should be kept short at high level for external user consumption.
|
||||
Release notes identify what users might care about most in a release. They
|
||||
are not exhaustive and are not a guide. PLEASE learn from past agents who
|
||||
tried to build elaborate release notes with implementation details and
|
||||
elsewhere-documented nuance. That wastes time. Fight the bias that
|
||||
"my change" is important so must be worthy of release note mention.
|
||||
* If more than single markdown line, consider how their formatting will be
|
||||
integrated into HISTORY.md.
|
||||
|
||||
### Blog posts (docs/_posts)
|
||||
* Blog post authors must be defined in `docs/_data/authors.yml` to be displayed
|
||||
|
||||
### Final verification of the change
|
||||
* Execute `AUTO_CLEAN=1 make check` to build all of the changes and execute all
|
||||
of the tests. `AUTO_CLEAN=1` ensures a clean rebuild if your previous build
|
||||
used different parameters. Note that executing all of the tests could take
|
||||
multiple minutes.
|
||||
* Run `AUTO_CLEAN=1 ASSERT_STATUS_CHECKED=1 make check` to verify all Status
|
||||
objects are properly checked. This catches missing error handling that can
|
||||
lead to silent data corruption. Merely building with ASSERT_STATUS_CHECKED=1
|
||||
accomplishes nothing; it enables a runtime check. New unit tests missing
|
||||
Status checks is a common failure point, even from agents.
|
||||
* Execute make clean to clean all of the changes.
|
||||
* Execute make check to build all of the changes and execute all of the tests.
|
||||
Note that executing all of the tests could take multiple minutes.
|
||||
|
||||
### Monitoring make check progress
|
||||
* Use `make check-progress` to get machine-parseable JSON progress while
|
||||
@@ -444,7 +278,7 @@ architectures.
|
||||
builds without timeout issues.
|
||||
* Run `make check` in background, then poll progress:
|
||||
```bash
|
||||
AUTO_CLEAN=1 make check &
|
||||
make check &
|
||||
# Poll periodically:
|
||||
make check-progress
|
||||
```
|
||||
@@ -469,10 +303,9 @@ architectures.
|
||||
|
||||
### Executing benchmark using db_bench
|
||||
* Since the goal is to measure performance, we need to build a release binary
|
||||
using `AUTO_CLEAN=1 DEBUG_LEVEL=0 make db_bench`. If there is an engine
|
||||
crash due to a bug, switch back to a debug build with
|
||||
`AUTO_CLEAN=1 make dbg`; `AUTO_CLEAN=1` handles the release<->debug rebuild
|
||||
automatically.
|
||||
using `make clean && DEBUG_LEVEL=0 make db_bench`. If there is an engine
|
||||
crash due to bug, we need to switch back to debug build. Make sure to run
|
||||
`make clean` before running `make dbg`.
|
||||
|
||||
### Formatting code
|
||||
* After making change, use `make format-auto` to auto-apply formatting without
|
||||
|
||||
+17
-165
@@ -82,15 +82,10 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||
endif()
|
||||
message(STATUS "CMAKE_BUILD_TYPE is set to ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
# Use ccache for compilation if available. Use CMAKE_C/CXX_COMPILER_LAUNCHER
|
||||
# instead of RULE_LAUNCH_COMPILE to avoid double-wrapping when ccache is also
|
||||
# injected via PATH (e.g., /usr/lib/ccache or brew --prefix ccache/libexec).
|
||||
# Note: we intentionally do NOT set RULE_LAUNCH_LINK because ccache cannot
|
||||
# cache link operations -- it only adds overhead.
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER ccache)
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
endif(CCACHE_FOUND)
|
||||
|
||||
option(WITH_JEMALLOC "build with JeMalloc" OFF)
|
||||
@@ -420,6 +415,13 @@ if(WITH_NUMA)
|
||||
list(APPEND THIRDPARTY_LIBS NUMA::NUMA)
|
||||
endif()
|
||||
|
||||
option(WITH_TBB "build with Threading Building Blocks (TBB)" OFF)
|
||||
if(WITH_TBB)
|
||||
find_package(TBB REQUIRED)
|
||||
add_definitions(-DTBB)
|
||||
list(APPEND THIRDPARTY_LIBS TBB::TBB)
|
||||
endif()
|
||||
|
||||
# Stall notifications eat some performance from inserts
|
||||
option(DISABLE_STALL_NOTIF "Build with stall notifications" OFF)
|
||||
if(DISABLE_STALL_NOTIF)
|
||||
@@ -513,15 +515,6 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "iOS")
|
||||
add_definitions(-DOS_MACOSX -DIOS_CROSS_COMPILE)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
add_definitions(-DOS_LINUX)
|
||||
# Use lld linker if available for faster linking (12x faster than ld.bfd)
|
||||
if(NOT ROCKSDB_NO_FAST_LINKER)
|
||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=lld -Wl,--version
|
||||
OUTPUT_VARIABLE LLD_VERSION_OUTPUT ERROR_QUIET RESULT_VARIABLE LLD_RESULT)
|
||||
if(LLD_RESULT EQUAL 0 AND LLD_VERSION_OUTPUT MATCHES "LLD")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=lld")
|
||||
endif()
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "SunOS")
|
||||
add_definitions(-DOS_SOLARIS)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "kFreeBSD")
|
||||
@@ -647,114 +640,30 @@ if(USE_FOLLY)
|
||||
FMT_INST_PATH)
|
||||
exec_program(ls ARGS -d ${FOLLY_INST_PATH}/../gflags* OUTPUT_VARIABLE
|
||||
GFLAGS_INST_PATH)
|
||||
exec_program(ls ARGS -d ${FOLLY_INST_PATH}/../glog* OUTPUT_VARIABLE
|
||||
GLOG_INST_PATH)
|
||||
set(Boost_DIR ${BOOST_INST_PATH}/lib/cmake/Boost-1.83.0)
|
||||
# Boost's per-library CMake configs find their dependencies (e.g.
|
||||
# boost_assert) only through the package search path.
|
||||
set(CMAKE_PREFIX_PATH ${BOOST_INST_PATH} ${CMAKE_PREFIX_PATH})
|
||||
if(EXISTS ${FMT_INST_PATH}/lib64)
|
||||
set(fmt_DIR ${FMT_INST_PATH}/lib64/cmake/fmt)
|
||||
else()
|
||||
set(fmt_DIR ${FMT_INST_PATH}/lib/cmake/fmt)
|
||||
endif()
|
||||
set(gflags_DIR ${GFLAGS_INST_PATH}/lib/cmake/gflags)
|
||||
if(EXISTS ${GLOG_INST_PATH}/lib64/cmake/glog)
|
||||
set(GLOG_CMAKE_DIR ${GLOG_INST_PATH}/lib64/cmake/glog)
|
||||
elseif(EXISTS ${GLOG_INST_PATH}/lib/cmake/glog)
|
||||
set(GLOG_CMAKE_DIR ${GLOG_INST_PATH}/lib/cmake/glog)
|
||||
endif()
|
||||
if(NOT GLOG_CMAKE_DIR)
|
||||
find_library(GETDEPS_GLOG_LIBRARY NAMES glogd glog
|
||||
PATHS ${GLOG_INST_PATH}/lib64 ${GLOG_INST_PATH}/lib
|
||||
NO_DEFAULT_PATH)
|
||||
if(NOT GETDEPS_GLOG_LIBRARY OR
|
||||
NOT EXISTS ${GLOG_INST_PATH}/include/glog/logging.h)
|
||||
message(FATAL_ERROR "Could not find getdeps glog under "
|
||||
"${GLOG_INST_PATH}")
|
||||
endif()
|
||||
set(GLOG_CMAKE_DIR ${CMAKE_CURRENT_BINARY_DIR}/getdeps-glog-cmake)
|
||||
file(MAKE_DIRECTORY ${GLOG_CMAKE_DIR})
|
||||
file(WRITE ${GLOG_CMAKE_DIR}/glog-config.cmake
|
||||
"if(NOT TARGET glog::glog)\n"
|
||||
" add_library(glog::glog UNKNOWN IMPORTED)\n"
|
||||
" set_target_properties(glog::glog PROPERTIES\n"
|
||||
" IMPORTED_LOCATION \"${GETDEPS_GLOG_LIBRARY}\"\n"
|
||||
" INTERFACE_INCLUDE_DIRECTORIES \"${GLOG_INST_PATH}/include\")\n"
|
||||
"endif()\n"
|
||||
"set(glog_FOUND TRUE)\n"
|
||||
"set(Glog_FOUND TRUE)\n"
|
||||
"set(GLOG_FOUND TRUE)\n"
|
||||
"set(GLOG_LIBRARY \"${GETDEPS_GLOG_LIBRARY}\")\n"
|
||||
"set(GLOG_LIBRARIES \"${GETDEPS_GLOG_LIBRARY}\")\n"
|
||||
"set(GLOG_INCLUDE_DIR \"${GLOG_INST_PATH}/include\")\n")
|
||||
endif()
|
||||
set(glog_DIR ${GLOG_CMAKE_DIR})
|
||||
set(Glog_DIR ${GLOG_CMAKE_DIR})
|
||||
# Unlike gflags, glog may also be installed system-wide. Pre-resolve the
|
||||
# getdeps copy so folly-config.cmake cannot fall back to another version.
|
||||
find_package(glog CONFIG REQUIRED PATHS ${GLOG_CMAKE_DIR}
|
||||
NO_DEFAULT_PATH)
|
||||
|
||||
exec_program(sed ARGS -i 's/gflags_shared//g'
|
||||
${FOLLY_INST_PATH}/lib/cmake/folly/folly-targets.cmake)
|
||||
|
||||
# folly-config.cmake only checks for gflags under a target name that this
|
||||
# install doesn't define, then falls back to our Findgflags.cmake, which
|
||||
# mistakes the gflags_static target name for a library path. gflags is
|
||||
# resolved below instead.
|
||||
set(CMAKE_DISABLE_FIND_PACKAGE_gflags TRUE)
|
||||
include(${FOLLY_INST_PATH}/lib/cmake/folly/folly-config.cmake)
|
||||
unset(CMAKE_DISABLE_FIND_PACKAGE_gflags)
|
||||
|
||||
# Fix gflags library name for debug builds. The getdeps gflags shared
|
||||
# library is versioned (e.g. libgflags_debug.so.2.3), so resolve the
|
||||
# actual file by glob rather than hard-coding a version.
|
||||
# Fix gflags library name for debug builds
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
file(GLOB GFLAGS_DEBUG_SHARED_LIBS
|
||||
"${GFLAGS_INST_PATH}/lib/libgflags_debug.so.*")
|
||||
if(NOT GFLAGS_DEBUG_SHARED_LIBS)
|
||||
message(FATAL_ERROR
|
||||
"Could not find getdeps libgflags_debug.so under ${GFLAGS_INST_PATH}/lib")
|
||||
endif()
|
||||
list(GET GFLAGS_DEBUG_SHARED_LIBS 0 GFLAGS_DEBUG_SHARED_LIB)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath=${GFLAGS_INST_PATH}/lib")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GFLAGS_DEBUG_SHARED_LIB}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GFLAGS_INST_PATH}/lib/libgflags_debug.so.2.2")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Folly itself uses gflags transitively, but RocksDB tools and benchmarks
|
||||
# also call gflags APIs directly, so they need an explicit link dependency.
|
||||
if(WITH_GFLAGS)
|
||||
if(NOT TARGET gflags::gflags AND NOT TARGET gflags_shared AND
|
||||
NOT gflags_LIBRARIES)
|
||||
find_package(gflags CONFIG QUIET)
|
||||
if(NOT gflags_FOUND)
|
||||
find_package(gflags REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
if(TARGET gflags::gflags)
|
||||
set(GFLAGS_LIB gflags::gflags)
|
||||
elseif(TARGET gflags_shared)
|
||||
set(GFLAGS_LIB gflags_shared)
|
||||
elseif(DEFINED GFLAGS_TARGET AND TARGET ${GFLAGS_TARGET})
|
||||
set(GFLAGS_LIB ${GFLAGS_TARGET})
|
||||
elseif(gflags_LIBRARIES)
|
||||
set(GFLAGS_LIB ${gflags_LIBRARIES})
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"WITH_GFLAGS is enabled, but no gflags library could be resolved")
|
||||
endif()
|
||||
list(APPEND THIRDPARTY_LIBS ${GFLAGS_LIB})
|
||||
endif()
|
||||
|
||||
add_compile_definitions(USE_FOLLY FOLLY_NO_CONFIG HAVE_CXX11_ATOMIC)
|
||||
list(APPEND THIRDPARTY_LIBS Folly::folly)
|
||||
set(FOLLY_LIBS Folly::folly)
|
||||
# --copy-dt-needed-entries is ld.bfd-specific; lld handles DT_NEEDED transitively
|
||||
if(NOT CMAKE_EXE_LINKER_FLAGS MATCHES "fuse-ld=lld")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--copy-dt-needed-entries")
|
||||
endif()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--copy-dt-needed-entries")
|
||||
endif()
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
@@ -781,17 +690,14 @@ set(SOURCES
|
||||
db/blob/blob_file_addition.cc
|
||||
db/blob/blob_file_builder.cc
|
||||
db/blob/blob_file_cache.cc
|
||||
db/blob/blob_file_partition_manager.cc
|
||||
db/blob/blob_file_garbage.cc
|
||||
db/blob/blob_file_meta.cc
|
||||
db/blob/blob_file_reader.cc
|
||||
db/blob/blob_garbage_meter.cc
|
||||
db/blob/blob_gen2_format.cc
|
||||
db/blob/blob_log_format.cc
|
||||
db/blob/blob_log_sequential_reader.cc
|
||||
db/blob/blob_log_writer.cc
|
||||
db/blob/blob_source.cc
|
||||
db/blob/blob_write_batch_transformer.cc
|
||||
db/blob/prefetch_buffer_collection.cc
|
||||
db/builder.cc
|
||||
db/c.cc
|
||||
@@ -810,7 +716,6 @@ set(SOURCES
|
||||
db/compaction/sst_partitioner.cc
|
||||
db/compaction/subcompaction_state.cc
|
||||
db/convenience.cc
|
||||
db/coro_db.cc
|
||||
db/db_filesnapshot.cc
|
||||
db/db_impl/compacted_db_impl.cc
|
||||
db/db_impl/db_impl.cc
|
||||
@@ -847,7 +752,6 @@ set(SOURCES
|
||||
db/merge_operator.cc
|
||||
db/multi_scan.cc
|
||||
db/output_validator.cc
|
||||
db/periodic_compaction_phaser.cc
|
||||
db/periodic_task_scheduler.cc
|
||||
db/range_del_aggregator.cc
|
||||
db/range_tombstone_fragmenter.cc
|
||||
@@ -856,17 +760,14 @@ set(SOURCES
|
||||
db/snapshot_impl.cc
|
||||
db/table_cache.cc
|
||||
db/table_properties_collector.cc
|
||||
db/transaction_log_impl.cc
|
||||
db/trim_history_scheduler.cc
|
||||
db/version_builder.cc
|
||||
db/version_edit.cc
|
||||
db/version_edit_handler.cc
|
||||
db/version_set.cc
|
||||
db/version_util.cc
|
||||
db/wal_edit.cc
|
||||
db/wal_iterator_impl.cc
|
||||
db/wal_manager.cc
|
||||
db/wide/lazy_wide_columns.cc
|
||||
db/wide/read_path_blob_resolver.cc
|
||||
db/wide/wide_column_serialization.cc
|
||||
db/wide/wide_columns.cc
|
||||
db/wide/wide_columns_helper.cc
|
||||
@@ -941,13 +842,11 @@ set(SOURCES
|
||||
table/block_based/block_based_table_builder.cc
|
||||
table/block_based/block_based_table_factory.cc
|
||||
table/block_based/block_based_table_iterator.cc
|
||||
table/block_based/multi_scan_index_iterator.cc
|
||||
table/block_based/block_based_table_reader.cc
|
||||
table/block_based/block_builder.cc
|
||||
table/block_based/block_cache.cc
|
||||
table/block_based/block_prefetcher.cc
|
||||
table/block_based/block_prefix_index.cc
|
||||
table/block_based/builtin_index_factory.cc
|
||||
table/block_based/data_block_hash_index.cc
|
||||
table/block_based/data_block_footer.cc
|
||||
table/block_based/filter_block_reader_common.cc
|
||||
@@ -981,7 +880,6 @@ set(SOURCES
|
||||
table/plain/plain_table_index.cc
|
||||
table/plain/plain_table_key_coding.cc
|
||||
table/plain/plain_table_reader.cc
|
||||
table/range_del_block.cc
|
||||
table/sst_file_dumper.cc
|
||||
table/sst_file_reader.cc
|
||||
table/sst_file_writer.cc
|
||||
@@ -1016,7 +914,6 @@ set(SOURCES
|
||||
util/simple_mixed_compressor.cc
|
||||
util/compression_context_cache.cc
|
||||
util/concurrent_task_limiter_impl.cc
|
||||
util/coro_stats_util.cc
|
||||
util/crc32c.cc
|
||||
util/data_structure.cc
|
||||
util/dynamic_bloom.cc
|
||||
@@ -1038,7 +935,6 @@ set(SOURCES
|
||||
util/xxhash.cc
|
||||
utilities/agg_merge/agg_merge.cc
|
||||
utilities/backup/backup_engine.cc
|
||||
utilities/copy_engine/copy_engine.cc
|
||||
utilities/blob_db/blob_compaction_filter.cc
|
||||
utilities/blob_db/blob_db.cc
|
||||
utilities/blob_db/blob_db_impl.cc
|
||||
@@ -1052,7 +948,6 @@ set(SOURCES
|
||||
utilities/cassandra/merge_operator.cc
|
||||
utilities/checkpoint/checkpoint_impl.cc
|
||||
utilities/compaction_filters.cc
|
||||
utilities/sorted_run_builder/sorted_run_builder.cc
|
||||
utilities/compaction_filters/remove_emptyvalue_compactionfilter.cc
|
||||
utilities/counted_fs.cc
|
||||
utilities/debug.cc
|
||||
@@ -1104,9 +999,6 @@ set(SOURCES
|
||||
utilities/transactions/write_prepared_txn_db.cc
|
||||
utilities/transactions/write_unprepared_txn.cc
|
||||
utilities/transactions/write_unprepared_txn_db.cc
|
||||
utilities/trie_index/bitvector.cc
|
||||
utilities/trie_index/louds_trie.cc
|
||||
utilities/trie_index/trie_index_factory.cc
|
||||
utilities/types_util.cc
|
||||
utilities/ttl/db_ttl_impl.cc
|
||||
utilities/wal_filter.cc
|
||||
@@ -1222,23 +1114,8 @@ if(USE_FOLLY_LITE)
|
||||
FMT_INCLUDE_DIR)
|
||||
include_directories(${FMT_INCLUDE_DIR})
|
||||
|
||||
exec_program(python3 ${PROJECT_SOURCE_DIR}/third-party/folly ARGS
|
||||
build/fbcode_builder/getdeps.py show-inst-dir glog OUTPUT_VARIABLE
|
||||
GLOG_INST_PATH)
|
||||
if(EXISTS ${GLOG_INST_PATH}/lib64)
|
||||
set(GLOG_LIB_DIR ${GLOG_INST_PATH}/lib64)
|
||||
else()
|
||||
set(GLOG_LIB_DIR ${GLOG_INST_PATH}/lib)
|
||||
endif()
|
||||
|
||||
add_definitions(-DUSE_FOLLY -DFOLLY_NO_CONFIG)
|
||||
find_library(GLOG_LIBRARY NAMES glog PATHS ${GLOG_LIB_DIR} NO_DEFAULT_PATH)
|
||||
if(NOT GLOG_LIBRARY)
|
||||
find_library(GLOG_LIBRARY NAMES glog)
|
||||
endif()
|
||||
if(GLOG_LIBRARY)
|
||||
list(APPEND THIRDPARTY_LIBS ${GLOG_LIBRARY})
|
||||
endif()
|
||||
list(APPEND THIRDPARTY_LIBS glog)
|
||||
endif()
|
||||
|
||||
set(ROCKSDB_STATIC_LIB rocksdb${ARTIFACT_SUFFIX})
|
||||
@@ -1484,7 +1361,6 @@ if(WITH_TESTS)
|
||||
db/blob/blob_garbage_meter_test.cc
|
||||
db/blob/blob_source_test.cc
|
||||
db/blob/db_blob_basic_test.cc
|
||||
db/blob/db_blob_direct_write_test.cc
|
||||
db/blob/db_blob_compaction_test.cc
|
||||
db/blob/db_blob_corruption_test.cc
|
||||
db/blob/db_blob_index_test.cc
|
||||
@@ -1510,7 +1386,6 @@ if(WITH_TESTS)
|
||||
db/db_clip_test.cc
|
||||
db/db_dynamic_level_test.cc
|
||||
db/db_encryption_test.cc
|
||||
db/db_etc2_test.cc
|
||||
db/db_etc3_test.cc
|
||||
db/db_flush_test.cc
|
||||
db/db_inplace_update_test.cc
|
||||
@@ -1523,7 +1398,6 @@ if(WITH_TESTS)
|
||||
db/db_memtable_test.cc
|
||||
db/db_merge_operator_test.cc
|
||||
db/db_merge_operand_test.cc
|
||||
db/db_open_with_config_test.cc
|
||||
db/db_options_test.cc
|
||||
db/db_properties_test.cc
|
||||
db/db_range_del_test.cc
|
||||
@@ -1534,6 +1408,7 @@ if(WITH_TESTS)
|
||||
db/db_table_properties_test.cc
|
||||
db/db_tailing_iter_test.cc
|
||||
db/db_test.cc
|
||||
db/db_test2.cc
|
||||
db/db_logical_block_size_cache_test.cc
|
||||
db/db_universal_compaction_test.cc
|
||||
db/db_wal_test.cc
|
||||
@@ -1574,9 +1449,7 @@ if(WITH_TESTS)
|
||||
db/version_set_test.cc
|
||||
db/wal_manager_test.cc
|
||||
db/wal_edit_test.cc
|
||||
db/wide/db_lazy_entity_test.cc
|
||||
db/wide/db_wide_basic_test.cc
|
||||
db/wide/db_wide_blob_direct_write_test.cc
|
||||
db/wide/wide_column_serialization_test.cc
|
||||
db/wide/wide_columns_helper_test.cc
|
||||
db/write_batch_test.cc
|
||||
@@ -1606,7 +1479,6 @@ if(WITH_TESTS)
|
||||
options/options_test.cc
|
||||
table/block_based/block_based_table_reader_test.cc
|
||||
table/block_based/block_test.cc
|
||||
table/block_based/builtin_index_factory_test.cc
|
||||
table/block_based/data_block_hash_index_test.cc
|
||||
table/block_based/full_filter_block_test.cc
|
||||
table/block_based/partitioned_filter_block_test.cc
|
||||
@@ -1658,10 +1530,7 @@ if(WITH_TESTS)
|
||||
utilities/cassandra/cassandra_row_merge_test.cc
|
||||
utilities/cassandra/cassandra_serialize_test.cc
|
||||
utilities/checkpoint/checkpoint_test.cc
|
||||
utilities/copy_engine/copy_engine_test.cc
|
||||
utilities/sorted_run_builder/sorted_run_builder_test.cc
|
||||
utilities/env_timed_test.cc
|
||||
utilities/fault_injection_fs_test.cc
|
||||
utilities/memory/memory_test.cc
|
||||
utilities/merge_operators/string_append/stringappend_test.cc
|
||||
utilities/object_registry_test.cc
|
||||
@@ -1679,12 +1548,10 @@ if(WITH_TESTS)
|
||||
utilities/transactions/lock/point/point_lock_manager_stress_test.cc
|
||||
utilities/transactions/write_committed_transaction_ts_test.cc
|
||||
utilities/transactions/write_prepared_transaction_test.cc
|
||||
utilities/transactions/write_prepared_transaction_seqno_test.cc
|
||||
utilities/transactions/write_prepared_transaction_test_seqno.cc
|
||||
utilities/transactions/write_unprepared_transaction_test.cc
|
||||
utilities/transactions/lock/range/range_locking_test.cc
|
||||
utilities/transactions/timestamped_snapshot_test.cc
|
||||
utilities/trie_index/trie_index_db_test.cc
|
||||
utilities/trie_index/trie_index_test.cc
|
||||
utilities/ttl/ttl_test.cc
|
||||
utilities/types_util_test.cc
|
||||
utilities/util_merge_operators_test.cc
|
||||
@@ -1698,7 +1565,6 @@ if(WITH_TESTS)
|
||||
db/db_with_timestamp_test_util.cc
|
||||
monitoring/thread_status_updater_debug.cc
|
||||
table/mock_table.cc
|
||||
test_util/simple_external_table_factory.cc
|
||||
utilities/agg_merge/test_agg_merge.cc
|
||||
utilities/cassandra/test_utils.cc
|
||||
)
|
||||
@@ -1727,21 +1593,7 @@ if(WITH_TESTS)
|
||||
)
|
||||
target_link_libraries(${exename}${ARTIFACT_SUFFIX} testutillib${ARTIFACT_SUFFIX} testharness gtest ${THIRDPARTY_LIBS} ${ROCKSDB_LIB})
|
||||
if(NOT "${exename}" MATCHES "db_sanity_test")
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
|
||||
# Discover tests at ctest time instead of during the parallel build.
|
||||
# POST_BUILD discovery (the default) runs each freshly-built test
|
||||
# binary while the -j build is still compiling; on resource-constrained
|
||||
# CI (notably the arm64 macOS runners) that discovery run can yield
|
||||
# empty output, and CMake's JSON parser then aborts the whole build
|
||||
# with "Syntax error: value, object or array expected". PRE_TEST moves
|
||||
# discovery out of the build phase so a slow/empty enumeration no
|
||||
# longer fails the build.
|
||||
gtest_discover_tests(${exename}
|
||||
DISCOVERY_TIMEOUT 120
|
||||
DISCOVERY_MODE PRE_TEST)
|
||||
else()
|
||||
gtest_discover_tests(${exename} DISCOVERY_TIMEOUT 120)
|
||||
endif()
|
||||
gtest_discover_tests(${exename} DISCOVERY_TIMEOUT 120)
|
||||
add_dependencies(rocksdb_check ${exename}${ARTIFACT_SUFFIX})
|
||||
endif()
|
||||
endforeach(sourcefile ${TESTS})
|
||||
|
||||
+6
-297
@@ -1,308 +1,17 @@
|
||||
# Rocksdb Change Log
|
||||
> NOTE: Entries for next release do not go here. Follow instructions in `unreleased_history/README.txt`
|
||||
|
||||
## 11.13.2 (10/21/2026)
|
||||
### Bug Fixes
|
||||
* Fixed blob direct write with more than one concurrent flush of a column family: a later flush sealed and published the blob files of the oldest pending memtable instead of its own, so flushes failed with `Corruption: VersionBuilder: Blob file #N already added` and the database stopped.
|
||||
|
||||
## 11.13.1 (10/23/2026)
|
||||
### Bug Fixes
|
||||
* Fixed data loss with `min_tombstones_for_range_conversion` and external file ingestion. An iterator whose view predated the ingestion could convert the deleted keys around the ingested keys into a range tombstone that deleted them. This happened when the file got no new sequence number (sequence number zero, `ingest_behind`, or `allow_db_generated_files`), and when an iterator was created during the ingestion.
|
||||
* Fixed a data loss bug where an iterator with `ReadOptions::read_tier = kMemtableTier` could, with `min_tombstones_for_range_conversion` enabled, insert a range tombstone that deleted live keys stored only in SST files. Read-path range tombstone conversion now runs only for iterators with `read_tier = kReadAllTier`.
|
||||
|
||||
## 11.13.0 (10/21/2026)
|
||||
### New Features
|
||||
* Added `FileSystem::IsPreallocationSupported()`. A `FileSystem` that never preallocates file space can return false so that DB open skips reopening and truncating the last WAL file.
|
||||
|
||||
## 11.0.4 (03/11/2026)
|
||||
### Public API Changes
|
||||
* Added the experimental `DBOptions::track_options_file_number_in_manifest`
|
||||
rollout option (with C and Java bindings). The option is persisted in each
|
||||
OPTIONS file. When enabled, RocksDB durably creates an OPTIONS file and then
|
||||
commits its file number in MANIFEST. Column-family create/drop commits the
|
||||
configuration snapshot and membership in one MANIFEST record. A newer tracked
|
||||
OPTIONS file without a commit is ignored after a crash, while a newer OPTIONS
|
||||
file written with tracking disabled retains the legacy highest-numbered-file
|
||||
behavior. Batched column-family changes publish one snapshot; after partial
|
||||
success it can be a safe superset that persisted-options APIs filter against
|
||||
live MANIFEST membership. Ordinary `DB::Open` continues to use caller-supplied
|
||||
options and does not depend on the operational snapshot.
|
||||
* Added `EncodeEntry()`, `PackSequenceAndType()`, and `UnPackSequenceAndType()` in `rocksdb/utilities/types_util.h` to construct internal keys and pack or unpack their sequence numbers and entry types. `kInternalKeyFooterSize` exposes the footer size in bytes.
|
||||
* Added `ldb update_manifest --rebind_options_file --options_file=OPTIONS-<number>` for offline repair of a committed MANIFEST OPTIONS file number. Operators must select a trusted snapshot that has MANIFEST tracking enabled and provide any external DB/CF allocation roots that are not serialized in OPTIONS.
|
||||
|
||||
### Behavior Changes
|
||||
* With `max_bgerror_resume_count <= 0` (auto resume disabled), a retryable or file-scoped IO error during compaction or flush is now a hard background error that stops writes until `DB::Resume()` is called. Previously, compaction errors were silently retried, and flush errors with a healthy WAL were soft errors that let writes continue while flushes were stopped.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixed two more `SstFileManager` trash accounting leaks: retrying a failed trash deletion immediately (for example with rate limiting disabled) after the file had disappeared, and a trash file that was deleted but whose directory sync then failed. In both cases the file's size stayed in the total trash size and tracked size until restart.
|
||||
* Fixed `SstFileManager` trash accounting leaking the size of a queued trash file that disappeared before deletion (for example because its directory was renamed). The leaked bytes stayed in the total trash size until restart, which could push every later deletion past `max_trash_db_ratio` and make it immediate instead of rate limited.
|
||||
* Fixed `MultiGet` with `ReadOptions::async_io` returning `NotSupported` when io_uring initialization or an asynchronous read submission fails. It now checks async I/O support on the reading thread and falls back to synchronous reads when needed.
|
||||
* Fixed subset checkpoints so their newest OPTIONS file lists only the column
|
||||
families retained by the checkpoint. This applies with both legacy
|
||||
highest-numbered OPTIONS selection and MANIFEST-tracked OPTIONS selection, and
|
||||
prevents `LoadLatestOptions` from recreating column families that the subset
|
||||
checkpoint intentionally dropped from its copied MANIFEST.
|
||||
|
||||
### Performance Improvements
|
||||
* Perf context counters and timers no longer call the thread-local init function of `perf_context` on every update. With `kEnableCount`, a counter update costs about 60% less.
|
||||
|
||||
## 11.12.0 (10/07/2026)
|
||||
### New Features
|
||||
* Added `FullExternalTableFactory` and related full-mode external table APIs that preserve RocksDB internal keys, enabling external tables to support nonzero sequence numbers, point and single deletions, merge operands, blob indexes, wide-column entities, snapshots, live DB writes, and multi-level compactions.
|
||||
* Re-remove deprecated DB::Open raw pointer variants in db.h
|
||||
|
||||
## 11.0.3 (03/03/2026)
|
||||
### Public API Changes
|
||||
* Added experimental coroutine capability interfaces for basic and full `ExternalTableReader` implementations. Coroutine-capable external readers can initiate file reads through `FSRandomAccessFile::SubmitReadAsync()`.
|
||||
* `ExternalTableFactory::NewTableReader()` now receives an already-opened `FSRandomAccessFile` and its file size instead of requiring implementations to reopen `file_path`. The supplied file preserves RocksDB's direct-I/O alignment handling, rate limiting, read statistics and listener notifications, prefetching, and synchronous, asynchronous, and batched reads.
|
||||
* Added `PutRangeDeletionBlock()`, `GetRangeDeletionBlock()`, and `IsDeleteRangeSupported()` to the external table interfaces so formats can opt in to range deletions using RocksDB's raw range-deletion metadata block.
|
||||
* Opaque `PreparedFileInfo` metadata can now be serialized to a checksummed representation with `SerializePreparedFileInfo()` and restored with `DeserializePreparedFileInfo()` for reuse across processes.
|
||||
* Removed the deprecated `IngestExternalFileOptions::write_global_seqno` option and its C, Java, and `ldb` APIs, `TableProperties::external_sst_file_global_seqno_offset`, and the `file_offset` output from `ExternalTableReader::GetPropertiesBlock()`. Existing external SST files whose global sequence number was rewritten without updating the properties-block checksum remain readable.
|
||||
* `TablePropertiesNames` has no apparent use in the public API so has been deprecated there.
|
||||
* `TableProperties::creation_time` is renamed to `oldest_ancestor_time`, which better describes its meaning, along with `TablePropertiesNames::kCreationTime` to `kOldestAncestorTime`. The misspelled `SstFileMetaData::oldest_ancester_time` is renamed to `oldest_ancestor_time`. The old names remain available as deprecated aliases and will be removed in a future release.
|
||||
* Added `WriteBufferFlushPolicy` and `WriteBufferManager` policy selection for flushing the oldest or largest column family, including configurable batched flushing of the largest column families across DBs sharing a manager, with C and Java bindings.
|
||||
|
||||
### Behavior Changes
|
||||
* When `ExternalTableBuilderBase::PutPropertiesBlock()` returns `NotSupported`, RocksDB now overrides `num_entries`, `raw_key_size`, and `raw_value_size` from `ExternalTableBuilderBase::GetTableProperties()` with the logical totals tracked by the external-table adapter. Format-specific properties such as `data_size` remain unchanged.
|
||||
* The `FSWritableFile` passed to `ExternalTableFactory::NewTableBuilder()` now reports logical file size including RocksDB-buffered data and exposes the underlying file's direct-I/O mode and required buffer alignment.
|
||||
* `Iterator::Refresh()` now returns `NotSupported` on iterators from a secondary DB's `DB::NewIterators()` only, because those iterators are pinned to one cross-column-family read view. Iterators from `DB::NewIterator()` are unaffected; to advance a batch, call `DB::NewIterators()` again after `TryCatchUpWithPrimary()`.
|
||||
* `SstFileReader` now reports standard SST read statistics and file I/O listener notifications, and honors the configured read rate limiter.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixed full recovery from retryable background errors to atomically advance WAL replay boundaries for all column families, preventing partial recovery of multi-column-family write batches after a failed recovery flush.
|
||||
* Fixed RocksDB builds on big-endian architectures such as s390x by disabling the optional persistent fault-injection log, whose binary format is little-endian-only.
|
||||
* Fixed `DB::ClipColumnFamily()` deleting a non-L0 SST file whose largest key equals `begin_key`, which lost keys at the start of the kept range.
|
||||
* Fixed swapped `oldest_key_time` and `newest_key_time` values in the `table_file_creation` event log entry.
|
||||
* Fixed `ExternalTableReader::VerifyChecksum()` results not being honored by the external table adapter.
|
||||
* Fixed a bug in manifest handling that could lead to a hang or memory corruption in the case of LSM sanity checks being fatally violated (exceptional; see `force_consistency_checks`).
|
||||
* Fixed `MultiGet()` with `ReadOptions::read_tier == kBlockCacheTier` reading data blocks from disk when `allow_mmap_reads` is false. Keys whose data block is not in the block cache now return `Status::Incomplete()`, the same as `Get()`.
|
||||
* Fixed trace replay (`DB::NewDefaultReplayer()`, db_bench `replay`) failing every read record (Get, MultiGet, iterator seek) on the default column family with `Corruption: Invalid Column Family ID` when the default column family handle was not passed, which is always the case in db_bench with `--num_column_families=1`.
|
||||
* Fixed multi-threaded `Replayer::Replay()` ignoring errors from executing trace records and returning OK. It now stops and returns the error, including `Status::NotSupported()` from executing a record, as single-threaded replay does.
|
||||
* Fixed secondary DB `NewIterators()` returning iterators from different database states or blocking for `TryCatchUpWithPrimary()` by serving the last completed catch-up view.
|
||||
|
||||
### Performance Improvements
|
||||
* Single Get coroutine reads using non-mmap, non-direct I/O on a `kFSBuffer`-capable `FileSystem` now use `FSRandomAccessFile::SubmitReadAsync()` instead of falling back to synchronous `Read()`. When rate-limited, these reads acquire their full token budget before submission to preserve a single filesystem-owned buffer, which can make physical I/O burstier than reads using caller-provided buffers.
|
||||
|
||||
|
||||
## 11.11.0 (09/21/2026)
|
||||
### New Features
|
||||
* External tables now support DB-assigned global sequence numbers when `IngestExternalFileOptions::allow_global_seqno` is enabled, allowing overlapping external tables to be ingested across multiple levels when compactions are disabled. This includes the deprecated `write_global_seqno` path when the reader supplies the properties block's file offset.
|
||||
* Added checksum handoff support for SST file writes when `BlockBasedTableOptions::checksum` is `kCRC32c`, allowing block and trailer CRC32C checksums to be passed from the table builder to the file writer for buffered-data validation and filesystem in-flight write protection.
|
||||
* Enhanced `sst_dump --command=recompress` to be more powerful for benchmarking, including through automation with a new `--json` option for machine-readable output.
|
||||
* Relax option sanitization for kv ratio compaction
|
||||
|
||||
## 11.0.2 (02/26/2026)
|
||||
### Public API Changes
|
||||
* Changed the experimental async read statistics API by removing `DB::AsyncCallback::EnableStats()` and changing `OnComplete(const PerfContext*, const IOStatsContext*)` to `OnComplete()`. Callers must configure TLS statistics before each async or coroutine read. `DB::GetAsync()` and `DB::MultiGetAsync()` callbacks must copy per-operation statistics from TLS during `OnComplete()`; coroutine users must copy them from inside a `CoroStackableDB` hook before suspending again. Each operation leaves TLS statistics collection disabled.
|
||||
* Added `Compressor::MaybeOverrideCompressionOptions()` (EXPERIMENTAL), an omnibus hook letting a custom compressor adjust the subset of `CompressionOptions` that the SST builder applies rather than the compressor itself: `parallel_threads`, `max_compressed_bytes_per_kb`, `auto_skip`, and `auto_skip_min_sample_every` (and potentially more in the future). This deprecates `Compressor::GetRecommendedParallelThreads()`, which it subsumes; the default implementation still honors an overridden `GetRecommendedParallelThreads()` for compatibility.
|
||||
* Added experimental `CoroDB::CoGet()` and `CoroDB::CoMultiGet()` overloads for point reads from an `SstFileReader`.
|
||||
* Added experimental `DB::GetWithMetadata()` and `DB::MultiGetWithMetadata()` APIs with opt-in output metadata for key timestamps and explicit-snapshot newer-version detection.
|
||||
* Added a `DB::NewIterators()` overload that accepts parallel vectors of `ReadOptions` and column family handles, allowing each returned iterator to use independent read settings while sharing a consistent database state. The vectors must have the same size, all snapshots must be null or identical, and all `tailing` settings must match.
|
||||
* Added `ReadOptions::custom_context`, an opaque, non-owning pointer passed through table reads so external table implementations can consume application-defined read options.
|
||||
|
||||
### Behavior Changes
|
||||
* `ExternalTableReader::MultiGet()` is now used by RocksDB's `DB::MultiGet()` path. Previously, the external table adapter used `TableReader`'s fallback, which called `ExternalTableReader::Get()` separately for each key.
|
||||
* `DB::OpenAndCompact()` now requires `output_directory` to be a simple name for a new subdirectory when the new `use_session_tmp_dir_for_remote_compaction` DB option is enabled. The option places that subdirectory under the canonical `<dbname>/session_tmp/` root, and `DB::Open()` deletes stale contents under the root after recovery. The disabled default preserves the existing `<dbname>/<output_directory>` layout without automatic cleanup. Previously, remote-compaction output directories were created directly under `<dbname>`, which made it challenging to safely identify and delete obsolete files.
|
||||
* Several block-based SST table properties now better support compression benchmarking and optimization: `uncompressed_data_size` is now persisted in the file (previously it was computed only at write time and read back as 0); a new `lsm_info_at_creation` property records the LSM level and "bottommost" status at the file's creation, distinguishing "not applicable" (e.g. SstFileWriter files) from "unknown" (older files); and the `compression_options` property now records the full compression manager configuration instead of only its name.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixed a usually-minor performance bug where `Cache::ApplyToAllEntries()` used single-entry batches instead of the intended 256-entry default for `ApplyToAllEntriesOptions::average_entries_per_lock`. All of the Cache implementations (LRU and HCC) benefit from the fix, but the disfavored LRU cache was especially impacted by repeated mutex acquisition and release.
|
||||
* Fixed stats-disabled coroutine and asynchronous reads inheriting enabled TLS statistics state when interleaved with stats-enabled reads on the same executor. Each read now uses its captured per-call configuration, while enabled request counters remain isolated across suspensions.
|
||||
* Fixed a bug where a remote compaction (`CompactionService` / `DB::OpenAndCompact`) requested with `OpenAndCompactOptions::allow_resumption=true` but for which resumption was internally disabled (incompatible with `paranoid_file_checks` or output-iteration verification) could fail a retried attempt, because the output directory was not cleaned before starting fresh and output files left by a previously interrupted attempt collided with the reused file numbers.
|
||||
* Fixed a bug where a remote compaction (`CompactionService` / `DB::OpenAndCompact`) could fail when the primary rotated its MANIFEST while the worker was opening the primary's directory read-only. The open reads `CURRENT`, and the primary publishes a new MANIFEST by renaming a freshly written `CURRENT` over the old one; on file systems without POSIX read-after-unlink semantics (remote/object stores) the replaced object is then reported as gone (`PathNotFound`/`NotFound`, or `TryAgain` for the MANIFEST equivalent) instead of remaining readable. `DB::OpenAndCompact()` now retries the secondary open a bounded, configurable number of times for those transient statuses, so a concurrent rotation no longer fails the compaction (which, for a `CompactionService` that does not fall back to a local compaction, became a background error on the primary).
|
||||
* Fixed secondary DB `NewIterators()` returning iterators from different database states when `TryCatchUpWithPrimary()` runs concurrently.
|
||||
* Fixed a bug where a `SeekToFirst()` on an iterator previously used for a `Seek()` could end the scan early and silently omit keys with `ReadOptions::async_io`, or otherwise run with readahead effectively disabled. Affects scans using `ReadOptions::prefix_same_as_start` together with `ReadOptions::auto_readahead_size` (enabled by default); memory-mapped reads are unaffected.
|
||||
|
||||
### Performance Improvements
|
||||
* `DB::MultiGetEntityLazy()` now reads all keys of a batch under a single shared per-column-family SuperVersion pin, and a single `LazyWideColumnsBatch::MultiResolve()` coalesces the resulting blob reads across keys: one read per blob file (and one per SST for embedded blobs), for whole-column and byte-range reads alike, instead of reading each key's blobs separately.
|
||||
|
||||
|
||||
## 11.10.0 (08/28/2026)
|
||||
### New Features
|
||||
* Added `BlockBasedTableOptions::optimize_key_common_prefix` as part of new `format_version=8`. When enabled, each data block and index block stores the common user-key prefix of its keys once instead of at every restart point, reducing block size and block-cache footprint for prefix-heavy data and speeding up Seek for bytewise-ordered keys.
|
||||
* A new experimental feature spreads out periodic (time-based) compaction trigger times across a fleet of similarly-configured DBs to avoid recurring "thundering herd" triggers, especially with remote compaction. See the new experimental DB option `periodic_compaction_phase_recovery_percent`.
|
||||
|
||||
### Public API Changes
|
||||
* `IngestExternalFileArg::atomic_replace_range` now supports a range that only partially overlaps existing files, instead of failing. Requires universal compaction and a table factory that supports range deletion; other configurations still fail on partial overlap. The range is also now specified as half-open (`start` inclusive, `limit` exclusive), resolving a previously documented ambiguity in the upper bound.
|
||||
* Added an immutable `external_table_config` option that is persisted in OPTIONS files and passed to external table factories during bootstrap.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixed a liveness bug where RocksDB could remain indefinitely in recovery from a soft background error when concurrent writes continuously generated normal flush requests.
|
||||
* Fixed a race in online error recovery where a concurrent higher-severity I/O error could leave a stale retry-flush plan active, prevent the required WAL switch, and create duplicate internal WAL history detected on DB reopen.
|
||||
* Fix "bottommost files" infinite compaction loops (`kBottommostFiles`). This happens with the unsupported combination of leveled compaction and `preserve_internal_time_seconds` / `preclude_last_level_data_seconds`, and in an edge case with user-defined timestamps when `full_history_ts_low` is unset. The underlying logic is now more unified to reduce risk of a similar divergence in logic in the future.
|
||||
* Fixed `reuse_manifest_on_open` to create a fresh MANIFEST instead of appending after recovery sees an incomplete atomic group at the MANIFEST tail.
|
||||
* Starting remote compaction (`CompactionService` / `DB::OpenAndCompact`) is now more efficient and more reliable, by avoiding unnecessary file operations (latency) while using more accurate consistency / precondition checks, both avoiding some spurious failures and rejecting more legitimate inconsistencies. New DBOption `remote_compaction_manifest_floor` can be disabled in case of unexpected problems with the change.
|
||||
* Fixed unbounded retention of recovered transaction state by a long-lived secondary opened with `allow_2pc`.
|
||||
* Fixed stale reads on secondary instances, where entries replayed from a WAL that the primary had already flushed could shadow the newer values in the flushed files indefinitely. Also fixed a case where a secondary could stop returning such a key altogether while the primary's flushed file holding it was unreadable.
|
||||
* Fixed subset checkpoints to discard tolerated MANIFEST tail corruption before appending column-family drop records.
|
||||
|
||||
### Performance Improvements
|
||||
* Improved compaction CPU efficiency for column families using an `SstPartitioner` (such as the built-in `SstPartitionerFixedPrefix`): when the partitioner can express its next boundary as a key prefix via the new `SstPartitioner::ShouldPartitionByPrefix()` API, compaction now checks that cached prefix inline instead of copying every user key and making a virtual `ShouldPartition()` call for each key-value written to an SST.
|
||||
|
||||
## 11.9.0 (08/14/2026)
|
||||
### New Features
|
||||
* Added an integrated and improved compression auto-skip feature (new CompressionOptions, still experimental) that saves CPU by skipping compression when and where the overall ratio is inadequate. This improves on the previous auto-skip compression manager by (a) taking achieved compression ratios into account, (b) using a continuously evolving payoff estimate, and (c) combining natively with parallel compression.
|
||||
* Added the `blob_file_writable_file_max_buffer_size` mutable column family option. When set to a non-zero value, blob-file writers use it as their `WritableFileWriter` max buffer size instead of inheriting `DBOptions::writable_file_max_buffer_size`.
|
||||
* Added an experimental lazy wide-column read API, `DB::GetEntityLazy()` / `DB::MultiGetEntityLazy()` (see `include/rocksdb/lazy_wide_columns.h`). The returned `LazyWideColumns` leaves blob-backed columns as unresolved references and, like an iterator, stays valid after the call returns, so the caller resolves only the columns -- and only the byte ranges -- it needs; a byte-range read of an uncompressed blob (separate-file or embedded) reads just those bytes from storage. Adds `Env::IOActivity::kLazyResolve` and `rocksdb.blobdb.lazy.*` statistics. Requires `max_open_files == -1`.
|
||||
* Added DB property `rocksdb.num-running-remote-compactions`, reporting the number of compaction service jobs currently waiting in `CompactionService::Wait()`.
|
||||
* Added DB property `rocksdb.num-unscheduled-compactions`, reporting compactions waiting in the DB's internal compaction queue but not yet assigned to a background job.
|
||||
* Added `DB::AbortCompactions()` and `DB::ResumeCompactions()` for per-column-family compaction abort and resume, with the same active-abort semantics as the DB-wide `AbortAllCompactions()`/`ResumeAllCompactions()` but scoped to a single column family. Calls are reference-counted independently per column family and compose with the DB-wide abort.
|
||||
|
||||
### Public API Changes
|
||||
* Add IndexFactory compatibility names for the existing user-defined index API.
|
||||
* Added the experimental `CoroDB` capability, exposed by `DB::GetCoroDB()`, with lazy native coroutine variants of `Get` and `MultiGet`. The existing `DB::GetAsync()` and `DB::MultiGetAsync()` APIs dispatch through it.
|
||||
* Added `rocksdb_batched_multi_get_pinned_cf()` to return batch-owned pinned MultiGet values and per-key errors without allocating one wrapper per found value.
|
||||
* Add `DBOptions::read_io_executor_threads` to increase the maximum thread count of the shared filesystem read I/O executor used for asynchronous reads when opening a DB. Opening a DB never reduces the shared executor thread count. Change the experimental `FSRandomAccessFile::SubmitReadAsync()` API to return whether the asynchronous path was used, and add the `FILE_SUBMIT_ASYNC_READ_FALLBACK` ticker to count calls that fall back to synchronous reads.
|
||||
* `ReadOptions::table_filter` is now a *pointer* to a caller-owned `std::function` instead of a `std::function` value, to improve efficiency in copying and destroying `ReadOptions` objects (which RocksDB does internally). This is a breaking change for users of this relatively obscure option, who will now need to declare a `std::function` that outlives the read. As a side effect of `ReadOptions` being trivially copyable, new but legitimate compiler warnings may surface.
|
||||
* Removed the experimental `CreateAutoSkipCompressionManager()`. Auto-skip compression is now a first-class feature of the block-based table builder, controlled by the new experimental `CompressionOptions::auto_skip`.
|
||||
* Added `CoroStackableDB` for implementing wrappers over native coroutine reads and used it to add coroutine `Get` and `MultiGet` support to `DBWithTTL` and WritePrepared `TransactionDB`. A stackable wrapper advertises coroutine support only when its wrapped DB supports it; TTL value decoding and transaction visibility semantics are preserved.
|
||||
* Added a `kSstFileWriter` value to `TableFileCreationReason`, which `SstFileWriter` now reports instead of the catch-all `kMisc`. This, along with new `db_name` and `is_remote_compaction` fields in `FilterBuildingContext`, improves the contextual information available to custom filter and compression strategies.
|
||||
* Renamed `TransactionLogIterator` to `WalIterator` (and `include/rocksdb/transaction_log.h` to `include/rocksdb/wal_iterator.h`), because it iterates the write-ahead log and is unrelated to `TransactionDB`. The old names still work. `DB::GetUpdatesSince()` is unchanged. In Java, `WalIterator` is the new name and `TransactionLogIterator` remains as a subclass. Also documented existing behavior that was previously unstated: only writes that reached the WAL are visible (so `WriteOptions::disableWAL` and `IngestExternalFile()` leave holes that end iteration), what each iterator state means, and that `GetUpdatesSince()` silently starts later when the requested sequence number is unavailable.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixed a bug where `BlobFileBuilder` passed an SST path to `OnBlobFileCompleted()` instead of the completed blob path during BlobDB garbage-collection compactions, causing incorrect `SstFileManager` accounting and compaction failures on filesystems where the SST was not yet pathname-visible.
|
||||
|
||||
### Performance Improvements
|
||||
* When `DBOptions::avoid_unnecessary_blocking_io` is true, obsolete `OPTIONS-*` files found during DB open are deleted by background purge instead of synchronously on the opening thread.
|
||||
|
||||
## 11.8.0 (07/28/2026)
|
||||
### Public API Changes
|
||||
* Add callback-based asynchronous read APIs, `DB::GetAsync()` and `DB::MultiGetAsync()`. The idea is that when IO is required, RocksDB can suspend its internal coroutine read path, allowing the read executor thread to do other work. When the IO is complete, RocksDB invokes the user callback. This requires filesystem support for full performance benefits. A new filesystem API `FSRandomAccessFile::SubmitReadAsync()` is introduced for this. Unlike `ReadAsync`, the filesystem is responsible for eventually calling the callback. `FileSystem::GetReadExecutor()` returns the IO executor whose EventBases run coroutine read processing. In the Posix filesystem, an IO-uring based event loop is used to complete the IO.
|
||||
* Added `FlushOptions::listener_wait` (default `false`). When set together with `FlushOptions::wait == true`, `DB::Flush()` will not return until the registered `EventListener::OnFlushCompleted` callbacks for the flushed memtables have finished running. By default (`false`), `Flush(wait=true)` may return as soon as the flush result is committed, which can be before (or while) the `OnFlushCompleted` callbacks execute on the background flush thread. Also added the corresponding C API `rocksdb_flushoptions_set_listener_wait()` / `rocksdb_flushoptions_get_listener_wait()`.
|
||||
* Deprecated `PinnableWideColumns::serialized_size()` in favor of the new `PinnableWideColumns::payload_size()`, which returns the total size of the columns' names and values (for a plain value this equals the value size). Relatedly, wide-column read accounting changed subtly: read statistics for entities (`BYTES_READ`, `BYTES_PER_READ`, and the per-key byte counts for `GetEntity`/`MultiGetEntity`) and the `ReadOptions::value_size_soft_limit` threshold now measure entities by this payload size instead of the serialized entity size. This drops serialization framing bytes from those measurements (so reported/limited sizes for entity reads are slightly smaller than before) and makes plain-value and wide-column accounting consistent.
|
||||
|
||||
### Behavior Changes
|
||||
* `ReadOptions::value_size_soft_limit` now also bounds the blob values resolved from pre-flush blob direct write references during `MultiGet`/`MultiGetEntity` (previously these were resolved after the limit check and read without bound). Enforcement is "always make progress": at least one key is read even if its value alone exceeds the limit, and only once the returned size exceeds the limit do subsequent keys get `Status::Aborted` -- so a caller retrying the aborted keys cannot loop forever on a single value that by itself exceeds the limit.
|
||||
|
||||
### Performance Improvements
|
||||
* Reduced copying when reading wide-column entities that have blob-referenced columns, whether stored in separate blob files or embedded (same-file) as blob records in the same SST. On the point-lookup (`GetEntity`/`MultiGetEntity`) and blob-backed memtable/direct-write read paths, resolving these columns no longer re-serializes the whole entity into a fresh buffer: inline columns are referenced in place in the pinned entity and each resolved blob value is referenced in place from its fetched buffer. This is enabled by an internal change to `PinnableWideColumns` that lets its columns reference multiple backing buffers.
|
||||
|
||||
## 11.7.0 (07/16/2026)
|
||||
### Public API Changes
|
||||
* Added `RangeLockManagerHandle::SetIsKilledCallback()`, a `std::function<bool()>` predicate polled during range-lock waits. When it returns true, a blocked `GetRangeLock()` wait returns promptly with `Status::Aborted()` instead of waiting for the lock timeout. Range-lock users that install no callback keep the original wait-until-grant-or-timeout behavior.
|
||||
* Added `MultiScanArgs::reverse` to support reverse MultiScan reads over bounded scan ranges.
|
||||
|
||||
### Behavior Changes
|
||||
* When using `LockWAL()`, live-file capture APIs such as checkpoint and backup now flush WAL-disabled unpersisted data; they can block until `UnlockWAL()` or return `Aborted` when called from the same thread that holds `LockWAL()` to avoid deadlock. `UnlockWAL()` must now also be called from the same thread that called `LockWAL()`.
|
||||
|
||||
### Performance Improvements
|
||||
* Fixed slow DB open with `best_efforts_recovery`, and slow catch-up of secondary and follower (read-only) instances, in which time and memory grew quadratically with the number of files in the DB (so the slowdown was worst for large DBs with long history).
|
||||
|
||||
## 11.6.0 (07/02/2026)
|
||||
### New Features
|
||||
* Added EXPERIMENTAL embedded blob SST support through `SstFileWriter::OpenWithEmbeddedBlobs()`, storing eligible large values as same-file blob records in block-based SST files and resolving them transparently for reads. This niche feature currently supports uncompressed embedded blobs only; compression options are placeholders and compression support is deferred to follow-up work.
|
||||
|
||||
### Public API Changes
|
||||
* Expanded the C API (`include/rocksdb/c.h`) with a large set of new `rocksdb_*` functions, mostly option getters/setters plus table-properties, job/event-listener, and metadata accessors, a WAL filter, a ReadOptions table filter, and a backup exclude-files callback. Many are now produced by a new semi-automated generator (`tools/c_api_gen/`) from the C++ headers; `include/rocksdb/c.h` remains a single self-contained header and the signatures of pre-existing functions are unchanged.
|
||||
|
||||
### Bug Fixes
|
||||
* Reverted PR14831 that made range_lock_manager aware of reverse-order CF
|
||||
* Fixed a bug in `RandomAccessFileReader::ReadAsync` where an already-aligned direct-IO read request with a null `scratch` and a caller-provided `aligned_buf` would take the "already aligned" fast path and submit the null buffer to the underlying async read (e.g. a null iovec base to io_uring, failing with EFAULT). This could surface as spurious iterator failures during async prefetch (MultiScan with async IO) on direct-IO databases. The async path now allocates a backing buffer in this case, matching the synchronous `Read` path.
|
||||
* Fixed a bug where closing a read-only DB instance could delete live SST files created by a concurrent read-write DB sharing the same directory.
|
||||
|
||||
## 11.5.0 (06/16/2026)
|
||||
### New Features
|
||||
* External table readers that open files through `ExternalTableOptions::fs` now update RocksDB SST/file-read statistics and file IO listener callbacks, making external file IO activity visible in existing read metrics.
|
||||
* Added `DB::PrepareFileIngestion()`, a two-phase form of `IngestExternalFile`/`IngestExternalFiles`. `PrepareFileIngestion()` performs all of the work that does not require the DB mutex (validating the arguments, reading each external file's metadata, and linking/copying the files into the DB) and returns an opaque `FileIngestionHandle`. `DB::CommitFileIngestionHandle()` (or `DB::CommitFileIngestionHandles()` for several handles at once) then makes the prepared files visible; multiple handles are committed atomically in a single MANIFEST write, or none are. `FileIngestionHandle::Abort()` (or simply destroying the handle) cancels a prepared ingestion and rolls it back. This gives flexibility to the application to Prepare a file separately from when its committed, and may shorten an applications critical path on `IngestExternalFile`.
|
||||
* Added two stats histograms reporting the per-call latency (in microseconds) of each successful `IngestExternalFile`/`IngestExternalFiles` call, split by phase: `rocksdb.ingest.external.file.prepare.micros` (argument validation and reading/validating/linking the external files, which does not block live writes) and `rocksdb.ingest.external.file.run.micros` (the ingestion performed under the DB mutex while live writes are blocked). Failed ingestions are not recorded.
|
||||
* Added `DBOptions::use_direct_io_for_compaction_reads` (default false). When enabled, compaction-input SST reads use `O_DIRECT` while user reads remain buffered, avoiding page-cache eviction of hot user-read data by sequential compaction scans. Pair with `use_direct_io_for_flush_and_compaction = true` on write-heavy workloads for direct I/O on both compaction inputs and outputs. Rejected at Open when combined with `allow_mmap_reads = true`. No-op when `use_direct_reads = true` is already set (since all reads are already direct).
|
||||
|
||||
### Public API Changes
|
||||
* `DB::GetPreparedFileInfoForExternalSstIngestion()` can now prepare metadata for a live DB-generated SST file so it can be passed to `IngestExternalFileArg::file_infos`. The input path must exactly match a live table file owned by the source DB, and the returned metadata handle must outlive the ingestion.
|
||||
* `ExternalSstFileInfo` gained a `prepared_file_info` member produced by `SstFileWriter::Finish`, and `IngestExternalFileArg` gained a `file_infos` field: a vector of borrowed `const PreparedFileInfo*` pointers, parallel to `external_files`. The owning `ExternalSstFileInfo::prepared_file_info` handle must outlive the ingestion. When set, `IngestExternalFiles()` reuses the supplied per-file metadata instead of re-opening and scanning each file to recompute it, avoiding that extra I/O.
|
||||
* Corrected the public C++ option spelling from `memtable_veirfy_per_key_checksum_on_seek` to `memtable_verify_per_key_checksum_on_seek`. RocksDB continues to accept the old misspelled OPTIONS-file key for compatibility, while newly serialized OPTIONS files use the corrected key.
|
||||
* Added experimental read-scoped block buffer provider API, configured through `ReadOptions::read_scoped_block_buffer_provider`, for supported block-based table iterator scans and MultiScan reads to use caller-provided read-scoped storage for final data-block contents. When configured, supported provider-backed scan data-block reads bypass the data-block cache. The provider is ignored when mmap reads are enabled. RocksDB may still use ordinary temporary scratch for serialized block bytes, such as when a block may be compressed. Get and MultiGet do not currently provide API guarantees for this provider.
|
||||
* Added `FileSystem::SyncFile()` and `Env::SyncFile()` public APIs for syncing or fsyncing a file by name without requiring callers to reopen it as writable.
|
||||
|
||||
### Behavior Changes
|
||||
* The default `compression` for column families is now `kLZ4Compression` rather than `kSnappyCompression`. This affects only column families that do not explicitly set `compression`, and only newly-written SST files. The change is fully compatible: existing data remains readable with no migration needed, as RocksDB selects the decompressor per block. LZ4 offers slightly better compression ratios and decompression CPU efficiency vs. Snappy and similar compression CPU, tested across various server CPUs. When support is not compiled in, the fallback path for default compression is LZ4 -> Snappy -> NoCompression.
|
||||
* Disable parallel compression (ignore `CompressionOptions::parallel_threads`) for fast built-in compressors: Snappy, LZ4 (accelerated, not LZ4HC), and accelerated levels of ZSTD (level < 0). These do not generally benefit from parallel compression. This behavior can be overridden with a custom Compressor from a custom CompressionManager.
|
||||
* `PosixFileSystem::OptimizeForCompactionTableRead` now delegates to the base `FileSystem::OptimizeForCompactionTableRead` implementation before applying its Linux-only compaction-readahead clamp (added for #12038). The returned `FileOptions::use_direct_reads` therefore reflects `DBOptions::use_direct_reads`, consistent with the base class and with other `FileSystem` implementations. Previously the override ignored the base implementation and keyed both the returned options and the Linux readahead clamp off the incoming `FileOptions` rather than `DBOptions`. At the in-tree call site the incoming `FileOptions::use_direct_reads` already matches `DBOptions::use_direct_reads`, so this is effectively a no-op for existing configurations; it removes a latent inconsistency where a caller passing `FileOptions` whose `use_direct_reads` disagreed with `DBOptions` would have had the global flag silently ignored for compaction-input reads on Linux. (Note: the `#12038` readahead clamp still keys off the global `use_direct_reads`; it is not skipped for the compaction-only `use_direct_io_for_compaction_reads` path, since that flag enables O_DIRECT after this hook runs.)
|
||||
* Brought more unity to `kLZ4Compression` and `kLZ4HCCompression` by giving each access to the other's compression levels. Negative (fast) values previously only available to LZ4 and positive (slow) values previously only available to LZ4HC are now available to both, so configuring a non-default `compression_opts.level` now selects the LZ4 compressor variant. This is a behavior change for previously tolerated but dubious configurations such as positive compression level with `kLZ4Compression`. `kLZ4Compression` and `kLZ4HCCompression` keep their effective default levels, equivalent to -1 and 9 respectively.
|
||||
* Removed a discontinuity in `kZSTD` compression levels at `compression_opts.level == 0` by mapping that setting to `level = -1` rather than to `level = 3` as the ZSTD library does internally. This improves the compression auto-tuning landscape.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixed a bug where the range lock manager would crash with an assertion failure when using a reverse comparator column family.
|
||||
|
||||
### Performance Improvements
|
||||
* Reduced commit latency when ingesting many external files by allowing `IngestExternalFileOptions::file_opening_threads` to open table readers for committed ingested files using multiple threads.
|
||||
* Reduced commit latency for large external file ingestions into the last level by adding `IngestExternalFileOptions::prefetch_lmax_index_and_filter_blocks`, which can skip commit-time index and filter block prefetching for cache-backed table metadata.
|
||||
|
||||
## 11.4.0 (06/02/2026)
|
||||
### Public API Changes
|
||||
* Added `rocksdb_options_set_memtable_batch_lookup_optimization()` and `rocksdb_options_get_memtable_batch_lookup_optimization()` to the C API, exposing the existing `AdvancedColumnFamilyOptions::memtable_batch_lookup_optimization` field. This allows C API users (and downstream language bindings) to enable the skip-list memtable's batch-lookup optimization for `MultiGet`, which caches the search path between consecutive keys and reduces per-key cost from O(log N) to O(log d) where d is the distance between consecutive keys.
|
||||
* Added `rocksdb_readoptions_set_optimize_multiget_for_io()` and `rocksdb_readoptions_get_optimize_multiget_for_io()` to the C API, exposing the existing `ReadOptions::optimize_multiget_for_io` field. This allows C API users (and downstream language bindings) to opt out of the multi-level parallel MultiGet path, which only takes effect when the library is built with `USE_COROUTINES`.
|
||||
* Added `rocksdb_block_based_table_index_block_search_type_auto` enum constant and the `rocksdb_block_based_options_set_uniform_cv_threshold()` setter to the C API. The constant exposes `BlockSearchType::kAuto`, and the setter exposes `BlockBasedTableOptions::uniform_cv_threshold`. Both are required for `kAuto` index-block search to take effect from the C API: without setting `uniform_cv_threshold >= 0`, the per-block `is_uniform` footer bit is never written, and `kAuto` falls back to binary search at read time.
|
||||
* Added `EventListener::OnDBShutdownBegin`, a callback that fires once when a DB begins shutdown, including when RocksDB cleans up a failed `DB::Open()` attempt.
|
||||
* Added a new PerfContext counter `blob_cache_read_byte` for blob cache bytes read.
|
||||
|
||||
### Behavior Changes
|
||||
* Remote compaction now falls back to local compaction when the primary cannot deserialize a successful `CompactionServiceResult` before installing any remote output files.
|
||||
* StringToMap (rocksdb/convenience.h) now preserves the outer braces of nested values so each map entry is in self-contained form and can be embedded directly into another `key=value;` string (e.g. SetOptions) without losing inner ';' delimiters. A new symmetric MapToString utility is provided.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixed a bug where `AbortAllCompactions()` could leave automatic compaction work unscheduled when aborting before the background worker picked it, causing compaction and write stalls until DB restart.
|
||||
* Fix a bug where db had a false positive compaction corruption error due to remote compaction service result with `has_accurate_num_input_records=false` not being serialized.
|
||||
* Fixed WritePrepared TransactionDB cleanup after retryable commit or rollback write failures so prepared transactions remain rollbackable instead of leaving unresolved prepared state.
|
||||
* Fix a rare corruption bug for tiered compaction that incorrectly moved last level range tombstones into proximal level. This corruption error is surfaced when force_consistency_checks is enabled.
|
||||
|
||||
### Performance Improvements
|
||||
* Reduce the likelihood of user-facing metadata operations blocking on MANIFEST rotation when file creation is slow, such as on remote storage. MANIFEST write batches containing foreground edits from `CreateColumnFamily()`, `DropColumnFamily()`, `CreateColumnFamilyWithImport()`, `IngestExternalFile()`, and `DeleteFilesInRanges()` now get a relaxed file size threshold for triggering MANIFEST rotation; background-only MANIFEST write batches, such as compaction and flush, continue to use the normal threshold. This change should make auto-tuning manifest file size more attractive (see `max_manifest_file_size` and `max_manifest_space_amp_pct` options).
|
||||
|
||||
|
||||
## 11.3.0 (05/15/2026)
|
||||
### New Features
|
||||
* Add experimental DB option `async_wal_precreate` to precreate the next WAL file in a background thread and reduce foreground WAL rotation latency. The option is sanitized to false when WAL recycling is enabled.
|
||||
* Added a new `EventListener::OnCompactionPreCommit` callback that fires after a compaction job finishes but before its input files are released (i.e. while `FileMetaData::being_compacted` is still true). Listeners that maintain bookkeeping of which files are currently being compacted can clean up such state in this new callback to avoid races with concurrent compaction picking, where another thread might pick up the same files for a new compaction immediately after `being_compacted` is flipped back to false but before `OnCompactionCompleted` fires. The default implementation is a no-op so this is not a breaking change.
|
||||
* Add mutable DBOption `optimize_manifest_for_recovery` (default false). When enabled, RocksDB can reduce recovery work after a clean shutdown, which may lower DB::Open latency on warm reopens.
|
||||
* Added public utility APIs `ParseCompressionNameForDisplay()` to convert `TableProperties::compression_name` into a human-readable compression name for both legacy and format_version 7+ SST metadata, including custom `CompressionManager`-provided display names for custom compression types.
|
||||
* Add `reuse_manifest_on_open` DBOption (default false). When enabled, DB::Open reuses the existing MANIFEST file for append instead of creating a fresh one, avoiding the cost of serializing the entire database state into a new MANIFEST on the first post-open write. To prevent this feature from interfering with manifest file size auto-tuning, an extra forward-compatible field is now always added to the MANIFEST (to track the last "compacted" size).
|
||||
|
||||
### Behavior Changes
|
||||
* Read-only open with `error_if_wal_file_exists=true` now tolerates empty WAL files so empty precreated WALs do not prevent inspection.
|
||||
* WriteCommitted TransactionDB now matches WritePrepared and WriteUnprepared compaction filtering in both single- and two-write-queue modes: a compaction filter's FilterMergeOperand will not be invoked on merge operands at or below the latest published sequence number.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixed blob-backed wide-column merge reads to preserve correct status
|
||||
propagation and resolution across memtable, read-only, and secondary DB
|
||||
paths.
|
||||
* Fixed a bug where `DB::GetCreationTimeOfOldestFile()` could return inaccurate results instead of the real creation time when called shortly after opening a legacy DB (one whose manifest lacks `file_creation_time`) with `open_files_async = true`. The API now waits for background SST file loading to complete only when needed; modern DBs are unaffected.
|
||||
* Fixed merge reads against wide-column/blob-backed base values to preserve precise failure statuses, including `GetMergeOperands()` and direct-write memtable reads.
|
||||
* Fix bug in range tombstone synthesis that covers live keys added during an IngestExternalFile
|
||||
* Reject the empty string as a column family name in `DB::CreateColumnFamily` / `DB::CreateColumnFamilies`. Previously such calls returned OK and a usable handle, but the column family was not persisted in the manifest, so any data written to it was silently lost on DB reopen.
|
||||
* Fixed a bug where a WriteCommitted TransactionDB using commit-bypass WBWI ingestion could drop an entry that is still visible at the published sequence boundary.
|
||||
|
||||
## 11.2.0 (04/18/2026)
|
||||
### New Features
|
||||
* Added experimental `DBOptions::fast_sst_open` option. When enabled, RocksDB retrieves opaque file system metadata for SST files after flush, compaction, and external file ingestion, persists it in the MANIFEST, and passes it back to the file system on subsequent file opens to accelerate DB open time.
|
||||
* Added new option `min_tombstones_for_range_conversion` in `AdvancedColumnFamilyOptions`. When set to a non-zero value N, forward or reverse iteration will convert N or more contiguous point tombstones into a range tombstone in the mutable memtable. Future read operations will then be able to benefit from range tombstone optimizations. There are some limitations when it comes to table_filters, prefix_filters, and UDTs. See header comments for more details.
|
||||
* Added read-triggered compaction: a new column family option `read_triggered_compaction_threshold` (default 0, disabled) that marks SST files for compaction when their read frequency (`num_collapsible_entry_reads_sampled / file_size`) exceeds the threshold. This helps reduce read amplification for frequently-read ("hot") keys. A new DB option `max_compaction_trigger_wakeup_seconds` (default 43200s / 12 hours) controls the maximum interval for periodic compaction score re-evaluation, which is necessary for this feature to work on quiet (no-write) databases.
|
||||
|
||||
### Public API Changes
|
||||
* Added new `WideColumnBlobResolver` interface and `CompactionFilter::FilterV4()` method, including `ResolveColumn()` / `ResolveColumns()` helpers for lazy loading blob column values in wide-column entities during compaction. This allows compaction filters to resolve blob values on-demand, avoiding unnecessary I/O for blob columns they don't need to access.
|
||||
* Changed experimental feature `ExternalTableReader::Get` and `ExternalTableReader::MultiGet` to use `PinnableSlice` instead of `std::string` for output values, enabling zero-copy pinning. This will break existing implementations.
|
||||
* Added `SstFileReader::Get` and `SstFileReader::MultiGet` overloads that accept `PinnableSlice`/`std::vector<PinnableSlice>*`, enabling zero-copy reads when the underlying `TableReader` supports pinning.
|
||||
|
||||
### Behavior Changes
|
||||
* Prefix filter changes - when seeking to a key that is out of domain, and total_order_seek is false, total_order_seek is treated as if it were true. When prefix_same_as_start = true, now iterating past a key that is out of domain invalidates the iterator. The existing behavior does not check for InDomain in the DBIter, so Transform() can produce undefined behavior (e.g. key of size 3 on FixedPrefixTransform(4)).
|
||||
* Wide-column entities with blob-backed columns now use a new V2 on-disk encoding; older RocksDB versions that do not support wide-column blob separation will reject DBs or SSTs containing those entities.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix blob garbage accounting for blob direct-write flushes so flush-time filtering and overwrite elision correctly register obsolete blob bytes in blob metadata.
|
||||
* Fix a memory accounting leak in IODispatcher where ReadIndex() moved block values out of ReadSet without releasing the associated prefetch memory, causing subsequent prefetches to be blocked when max_prefetch_memory_bytes was set.
|
||||
* Fix MultiScan to fall back to synchronous coalesced reads when async I/O is unsupported at runtime.
|
||||
|
||||
|
||||
## 11.1.0 (03/23/2026)
|
||||
### New Features
|
||||
* Add a new option `open_files_async`. The existing behavior is on DB open, we open all sst files and do basic validations. For very large DBs on remote filesystems with many ssts, this may take very long. This option performs these validations instead in the background. Open errors found by this async background task are surfaced as a new background error kAsyncFileOpen.
|
||||
* Added `BlockBasedTableOptions::kAuto` index block search type that automatically selects between binary and interpolation search on a per-index-block basis. During SST construction, each index block's key distribution uniformity is analyzed using the coefficient of variation of key gaps, and index blocks with uniform keys use interpolation search while others fall back to binary search. The uniformity threshold is configurable via `BlockBasedTableOptions::uniform_cv_threshold` (default: 0.2).
|
||||
* Introduced enforce_write_buffer_manager_during_recovery option to allow WriteBufferManager to be enforced during WAL recovery. (Default: true)
|
||||
* Add `memtable_batch_lookup_optimization` option to use batch lookup optimization for memtable MultiGet. For skip list memtables, after each key lookup, the search path is cached and reused for the next key, reducing per-key cost from O(log N) to O(log d) where d is the distance between consecutive keys. Benchmarks show ~7% improvement in memtable-resident MultiGet throughput.
|
||||
* Added `BlockBasedTableOptions::PrepopulateBlockCache::kFlushAndCompaction` to prepopulate the block cache during both flush and compaction. Compaction-warmed blocks are inserted at `BOTTOM` priority (vs `LOW` for flush) so they are evicted first under cache pressure. Recommended only for use cases where most or all of the database is expected to reside in cache (e.g., tiered or remote storage where the working set fits in cache).
|
||||
* Added new mutable DB option `verify_manifest_content_on_close` (default: false). When enabled, on DB close the MANIFEST file is read back and all records are validated (CRC checksums and logical content). If corruption is detected, a fresh MANIFEST is written from in-memory state.
|
||||
|
||||
### Behavior Changes
|
||||
* num_reads_sampled now factors in re-seeks and next/prev() on file iterators for files in L1+. next/prev() is discounted by 64x compared to seek due to being a much cheaper call.
|
||||
* Remote compaction workers now skip WAL recovery when opening the secondary DB instance, since only the LSM state from MANIFEST is needed for compaction. This reduces I/O and speeds up remote compaction startup.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix a bug in round-robin compaction that missed selecting input files that are needed to guarantee data correctness and cause crashing in debug builds or silent data corruption in release builds for Get().
|
||||
* Revert removing deprecated DB::Open raw pointer variants in db.h
|
||||
|
||||
## 11.0.0 (02/23/2026)
|
||||
### New Features
|
||||
|
||||
@@ -86,20 +86,11 @@ else
|
||||
LIB_MODE?=shared
|
||||
endif
|
||||
|
||||
# Set by the gen_check_scripts wrappers to mark a recursive make reusing the
|
||||
# parent's make_config.mk: silence the parse-time banners and skip
|
||||
# build_detect_platform (below).
|
||||
$(if $(ROCKSDB_RECURSIVE_MAKE_SAME_CONFIG),,$(info $$DEBUG_LEVEL is $(DEBUG_LEVEL), $$LIB_MODE is $(LIB_MODE)))
|
||||
$(info $$DEBUG_LEVEL is $(DEBUG_LEVEL), $$LIB_MODE is $(LIB_MODE))
|
||||
|
||||
# Detect what platform we're building on.
|
||||
# Export some common variables that might have been passed as Make variables
|
||||
# instead of environment variables.
|
||||
#
|
||||
# Skipped by the gen_check_scripts wrappers (which run concurrently under
|
||||
# gnu_parallel): each would otherwise rewrite the shared make_config.mk
|
||||
# non-atomically and a concurrent reader could catch it mid-write ("missing
|
||||
# separator"). Requires an existing make_config.mk, so a normal build still detects.
|
||||
ifeq ($(and $(ROCKSDB_RECURSIVE_MAKE_SAME_CONFIG),$(wildcard make_config.mk)),)
|
||||
dummy := $(shell (export ROCKSDB_ROOT="$(CURDIR)"; \
|
||||
export CXXFLAGS="$(EXTRA_CXXFLAGS)"; \
|
||||
export LDFLAGS="$(EXTRA_LDFLAGS)"; \
|
||||
@@ -113,9 +104,8 @@ dummy := $(shell (export ROCKSDB_ROOT="$(CURDIR)"; \
|
||||
export ROCKSDB_CXX_STANDARD="$(ROCKSDB_CXX_STANDARD)"; \
|
||||
export USE_FOLLY="$(USE_FOLLY)"; \
|
||||
export USE_FOLLY_LITE="$(USE_FOLLY_LITE)"; \
|
||||
"$(CURDIR)/build_tools/build_detect_platform" "$(CURDIR)/make_config.mk" $(if $(ROCKSDB_RECURSIVE_MAKE_SAME_CONFIG),2>/dev/null)))
|
||||
endif
|
||||
# this file (generated above, or reused when skipped) sets build flags and sources
|
||||
"$(CURDIR)/build_tools/build_detect_platform" "$(CURDIR)/make_config.mk"))
|
||||
# this file is generated by the previous line to set build flags and sources
|
||||
include make_config.mk
|
||||
|
||||
# Figure out optimize level.
|
||||
@@ -191,7 +181,7 @@ ifeq ($(filter -DROCKSDB_ASSERT_STATUS_CHECKED,$(OPT)),)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(if $(ROCKSDB_RECURSIVE_MAKE_SAME_CONFIG),,$(warning Warning: Compiling in debug mode. Don't use the resulting binary in production))
|
||||
$(warning Warning: Compiling in debug mode. Don't use the resulting binary in production)
|
||||
endif
|
||||
|
||||
# `USE_LTO=1` enables link-time optimizations. Among other things, this enables
|
||||
@@ -298,7 +288,7 @@ endif
|
||||
endif
|
||||
|
||||
export JAVAC_ARGS
|
||||
CLEAN_FILES += rocksdb.pc
|
||||
CLEAN_FILES += make_config.mk rocksdb.pc
|
||||
|
||||
ifeq ($(V), 1)
|
||||
$(info $(shell uname -a))
|
||||
@@ -337,9 +327,6 @@ missing_make_config_paths := $(shell \
|
||||
$(foreach path, $(missing_make_config_paths), \
|
||||
$(warning Warning: $(path) does not exist))
|
||||
|
||||
# This (the first rule) must depend on "all".
|
||||
default: all
|
||||
|
||||
ifeq ($(PLATFORM), OS_AIX)
|
||||
# no debug info
|
||||
else ifneq ($(PLATFORM), IOS)
|
||||
@@ -397,10 +384,6 @@ endif
|
||||
# TSAN doesn't work well with jemalloc. If we're compiling with TSAN, we should use regular malloc.
|
||||
ifdef COMPILE_WITH_TSAN
|
||||
DISABLE_JEMALLOC=1
|
||||
# Use a suppressions file instead of the process-wide TSAN default
|
||||
# suppressions hook, which belongs to the final application.
|
||||
TSAN_OPTIONS?=suppressions=$(CURDIR)/tools/tsan_suppressions.txt
|
||||
export TSAN_OPTIONS
|
||||
EXEC_LDFLAGS += -fsanitize=thread
|
||||
PLATFORM_CCFLAGS += -fsanitize=thread -fPIC -DFOLLY_SANITIZE_THREAD
|
||||
PLATFORM_CXXFLAGS += -fsanitize=thread -fPIC -DFOLLY_SANITIZE_THREAD
|
||||
@@ -467,7 +450,7 @@ ifndef USE_FOLLY
|
||||
endif
|
||||
|
||||
ifndef GTEST_THROW_ON_FAILURE
|
||||
export GTEST_THROW_ON_FAILURE=0
|
||||
export GTEST_THROW_ON_FAILURE=1
|
||||
endif
|
||||
ifndef GTEST_HAS_EXCEPTIONS
|
||||
export GTEST_HAS_EXCEPTIONS=1
|
||||
@@ -498,6 +481,9 @@ ifdef ROCKSDB_MODIFY_NPHASH
|
||||
PLATFORM_CXXFLAGS += -DROCKSDB_MODIFY_NPHASH=1
|
||||
endif
|
||||
|
||||
# This (the first rule) must depend on "all".
|
||||
default: all
|
||||
|
||||
WARNING_FLAGS = -W -Wextra -Wall -Wsign-compare -Wshadow \
|
||||
-Wunused-parameter
|
||||
|
||||
@@ -589,13 +575,9 @@ TESTS += $(PLUGIN_TESTS)
|
||||
ifneq ($(filter check-headers, $(MAKECMDGOALS)),)
|
||||
# TODO: add/support JNI headers
|
||||
DEV_HEADER_DIRS := $(sort include/ $(dir $(ALL_SOURCES)))
|
||||
FOLLY_DEPENDENT_HEADERS := \
|
||||
include/rocksdb/coro_db.h \
|
||||
include/rocksdb/coro_external_table.h \
|
||||
include/rocksdb/utilities/coro_stackable_db.h
|
||||
# Some headers like in port/ are platform-specific
|
||||
DEV_HEADERS_TO_CHECK := $(filter-out $(FOLLY_DEPENDENT_HEADERS), $(shell $(FIND) $(DEV_HEADER_DIRS) -type f -name '*.h' | grep -E -v 'port/|plugin/|range_tree/|secondary_index/'))
|
||||
PUBLIC_HEADERS_TO_CHECK := $(filter-out $(FOLLY_DEPENDENT_HEADERS), $(shell $(FIND) include/ -type f -name '*.h'))
|
||||
DEV_HEADERS_TO_CHECK := $(shell $(FIND) $(DEV_HEADER_DIRS) -type f -name '*.h' | grep -E -v 'port/|plugin/|range_tree/|secondary_index/')
|
||||
PUBLIC_HEADERS_TO_CHECK := $(shell $(FIND) include/ -type f -name '*.h')
|
||||
else
|
||||
DEV_HEADERS_TO_CHECK :=
|
||||
PUBLIC_HEADERS_TO_CHECK :=
|
||||
@@ -639,24 +621,25 @@ endif
|
||||
|
||||
ROCKSDBTESTS_SUBSET ?= $(TESTS)
|
||||
|
||||
# c_test - doesn't use gtest, can't be sharded
|
||||
# Other tests previously listed here (backup_engine_test, db_bloom_filter_test,
|
||||
# perf_context_test, etc.) were NON_PARALLEL due to /dev/shm memory concerns
|
||||
# when the old per-test-case sharding spawned thousands of processes. With the
|
||||
# new gtest-based sharding (GTEST_SHARD_SIZE=10, max NCORES*8 shards), at most
|
||||
# ~4 shards run concurrently on CI (4 cores), so peak memory is manageable
|
||||
# (4 * 1GB = 4GB << 16GB shm).
|
||||
# c_test - doesn't use gtest
|
||||
# env_test - suspicious use of test::TmpDir
|
||||
# deletefile_test - serial because it generates giant temporary files in
|
||||
# its various tests. Parallel can fill up your /dev/shm
|
||||
# db_bloom_filter_test - serial because excessive space usage by instances
|
||||
# of DBFilterConstructionReserveMemoryTestWithParam can fill up /dev/shm
|
||||
NON_PARALLEL_TEST = \
|
||||
c_test \
|
||||
env_test \
|
||||
deletefile_test \
|
||||
db_bloom_filter_test \
|
||||
$(PLUGIN_TESTS) \
|
||||
|
||||
PARALLEL_TEST = $(filter-out $(NON_PARALLEL_TEST), $(ROCKSDBTESTS_SUBSET))
|
||||
PARALLEL_TEST = $(filter-out $(NON_PARALLEL_TEST), $(TESTS))
|
||||
|
||||
# Not necessarily well thought out or up-to-date, but matches old list
|
||||
TESTS_PLATFORM_DEPENDENT := \
|
||||
db_basic_test \
|
||||
db_blob_basic_test \
|
||||
db_blob_direct_write_test \
|
||||
db_encryption_test \
|
||||
external_sst_file_basic_test \
|
||||
auto_roll_logger_test \
|
||||
@@ -664,7 +647,6 @@ TESTS_PLATFORM_DEPENDENT := \
|
||||
dynamic_bloom_test \
|
||||
c_test \
|
||||
checkpoint_test \
|
||||
sorted_run_builder_test \
|
||||
crc32c_test \
|
||||
coding_test \
|
||||
inlineskiplist_test \
|
||||
@@ -778,6 +760,7 @@ util/build_version.cc: $(filter-out $(OBJ_DIR)/util/build_version.o, $(LIB_OBJEC
|
||||
$(AM_V_at)$(gen_build_version) > $@
|
||||
endif
|
||||
CLEAN_FILES += util/build_version.cc
|
||||
|
||||
default: all
|
||||
|
||||
#-----------------------------------------------
|
||||
@@ -822,21 +805,9 @@ endif # PLATFORM_SHARED_EXT
|
||||
.PHONY: check clean coverage ldb_tests package dbg gen-pc build_size \
|
||||
release tags tags0 valgrind_check format static_lib shared_lib all \
|
||||
rocksdbjavastatic rocksdbjava install install-static install-shared \
|
||||
uninstall analyze tools tools_lib check-headers checkout_folly clang-tidy \
|
||||
check-c-api-c_test
|
||||
uninstall analyze tools tools_lib check-headers checkout_folly clang-tidy
|
||||
|
||||
# Auto-configure git hooks on first build so developers do not need to run
|
||||
# "make install-hooks" manually. This is a no-op if already set.
|
||||
setup-hooks:
|
||||
@if [ -d .git ] && [ -d githooks ]; then \
|
||||
cur=$$(git config core.hooksPath 2>/dev/null); \
|
||||
if [ "$$cur" != "githooks" ]; then \
|
||||
git config core.hooksPath githooks; \
|
||||
echo "git hooks: configured core.hooksPath = githooks"; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
all: setup-hooks $(LIBRARY) $(BENCHMARKS) tools tools_lib test_libs $(TESTS)
|
||||
all: $(LIBRARY) $(BENCHMARKS) tools tools_lib test_libs $(TESTS)
|
||||
|
||||
all_but_some_tests: $(LIBRARY) $(BENCHMARKS) tools tools_lib test_libs $(ROCKSDBTESTS_SUBSET)
|
||||
|
||||
@@ -900,62 +871,21 @@ coverage: clean
|
||||
|
||||
parallel_tests = $(patsubst %,parallel_%,$(PARALLEL_TEST))
|
||||
.PHONY: gen_parallel_tests $(parallel_tests)
|
||||
# Shard size controls how many test cases run per process. The actual number
|
||||
# of shards per binary is: min(ceil(test_count / shard_size), NCORES * 8)
|
||||
# This adapts to machine size: many small shards on beefy machines, fewer
|
||||
# larger shards on CI (typically 2-4 cores).
|
||||
GTEST_SHARD_SIZE ?= 10
|
||||
NCORES ?= $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
|
||||
|
||||
# Per-binary overrides for GTEST_SHARD_SIZE, used to chop up binaries whose
|
||||
# individual test cases are slow enough that the default of 10 leaves one
|
||||
# shard on the critical path of "make check". Format: whitespace-separated
|
||||
# tokens "BINARY:SIZE". Sizes were tuned from `make suggest-slow-tests`
|
||||
# output to keep max shard time under ~20s on a beefy box. Reducing too far
|
||||
# adds per-shard fixed overhead, so don't use 1 unless individual tests are
|
||||
# >5s.
|
||||
SHARD_SIZE_OVERRIDES ?= \
|
||||
point_lock_manager_stress_test:1 \
|
||||
external_sst_file_test:1 \
|
||||
external_sst_file_basic_test:2 \
|
||||
db_test:3 \
|
||||
compaction_service_test:1
|
||||
|
||||
$(parallel_tests):
|
||||
$(AM_V_at)TEST_BINARY=$(patsubst parallel_%,%,$@); \
|
||||
TEST_COUNT=` \
|
||||
(./$$TEST_BINARY --gtest_list_tests 2>/dev/null || echo " list_failure") \
|
||||
| grep -c '^ '`; \
|
||||
if [ "$$TEST_COUNT" -le 0 ]; then TEST_COUNT=1; fi; \
|
||||
SHARD_SIZE=$(GTEST_SHARD_SIZE); \
|
||||
for o in $(SHARD_SIZE_OVERRIDES); do \
|
||||
case "$$o" in \
|
||||
"$$TEST_BINARY":*) SHARD_SIZE=$${o#*:} ;; \
|
||||
esac; \
|
||||
done; \
|
||||
MAX_SHARDS=$$(( $(NCORES) * 8 )); \
|
||||
NUM_SHARDS=$$(( (TEST_COUNT + SHARD_SIZE - 1) / SHARD_SIZE )); \
|
||||
if [ "$$NUM_SHARDS" -gt "$$MAX_SHARDS" ]; then NUM_SHARDS=$$MAX_SHARDS; fi; \
|
||||
if [ "$$NUM_SHARDS" -le 0 ]; then NUM_SHARDS=1; fi; \
|
||||
echo " Generating $$NUM_SHARDS shards for $$TEST_BINARY ($$TEST_COUNT tests, shard_size=$$SHARD_SIZE)"; \
|
||||
SHARD_IDX=0; \
|
||||
while [ "$$SHARD_IDX" -lt "$$NUM_SHARDS" ]; do \
|
||||
if [ -n "$(CI_TOTAL_SHARDS)" ] && [ $$(( $$SHARD_IDX % $(CI_TOTAL_SHARDS) )) -ne $(CI_SHARD_INDEX) ]; then \
|
||||
SHARD_IDX=$$((SHARD_IDX + 1)); \
|
||||
continue; \
|
||||
fi; \
|
||||
TEST_SCRIPT=t/run-$$TEST_BINARY-shard-$$SHARD_IDX; \
|
||||
TEST_NAMES=` \
|
||||
(./$$TEST_BINARY --gtest_list_tests || echo " $${TEST_BINARY}__list_tests_failure") \
|
||||
| awk '/^[^ ]/ { prefix = $$1 } /^[ ]/ { print prefix $$1 }'`; \
|
||||
echo " Generating parallel test scripts for $$TEST_BINARY"; \
|
||||
for TEST_NAME in $$TEST_NAMES; do \
|
||||
TEST_SCRIPT=t/run-$$TEST_BINARY-$${TEST_NAME//\//-}; \
|
||||
printf '%s\n' \
|
||||
'#!/bin/sh' \
|
||||
"d=\$(TEST_TMPDIR)$$TEST_SCRIPT" \
|
||||
'mkdir -p $$d' \
|
||||
"TEST_TMPDIR=\$$d GTEST_TOTAL_SHARDS=$$NUM_SHARDS GTEST_SHARD_INDEX=$$SHARD_IDX $(DRIVER) ./$$TEST_BINARY" \
|
||||
'test_retcode=$$?' \
|
||||
'[ $$test_retcode -eq 0 ] && rm -rf $$d' \
|
||||
'exit $$test_retcode' \
|
||||
"TEST_TMPDIR=\$$d $(DRIVER) ./$$TEST_BINARY --gtest_filter=$$TEST_NAME" \
|
||||
> $$TEST_SCRIPT; \
|
||||
chmod a=rx $$TEST_SCRIPT; \
|
||||
SHARD_IDX=$$((SHARD_IDX + 1)); \
|
||||
done
|
||||
|
||||
gen_parallel_tests:
|
||||
@@ -963,116 +893,29 @@ gen_parallel_tests:
|
||||
$(AM_V_at)$(FIND) t -type f -name 'run-*' -exec rm -f {} \;
|
||||
$(MAKE) $(parallel_tests)
|
||||
|
||||
# Auxiliary (non-unit-test) checks that are part of `make check`. Kept as a
|
||||
# single list so the same set can run as parallel jobs alongside the C++ unit
|
||||
# tests (see gen_check_scripts + check_0) and serially in the J=1 fallback.
|
||||
CHECK_EXTRA_TARGETS =
|
||||
ifneq ($(PLATFORM), OS_AIX)
|
||||
CHECK_EXTRA_TARGETS += check-all-python
|
||||
ifndef ASSERT_STATUS_CHECKED # not yet working with these tests
|
||||
CHECK_EXTRA_TARGETS += ldb_tests db_crashtest_tests rocksdb_dump_test
|
||||
endif
|
||||
endif
|
||||
ifndef SKIP_FORMAT_BUCK_CHECKS
|
||||
CHECK_EXTRA_TARGETS += check-format check-buck-targets check-sources check-workflow-yaml check-c-api-gen
|
||||
endif
|
||||
|
||||
# Generate a t/run-<target> wrapper per enabled auxiliary check; check_0's
|
||||
# `$(FIND) t -name 'run-*'` then runs them as gnu_parallel jobs alongside the
|
||||
# unit tests, each framed with a gtest-style pass/fail line. Under CI sharding,
|
||||
# round-robin across shards so each check runs on exactly one shard. Kept
|
||||
# separate from gen_parallel_tests (which cleans t/run-* first) so the valgrind_*
|
||||
# targets, which also glob t/run-*, don't pick these up.
|
||||
.PHONY: gen_check_scripts
|
||||
gen_check_scripts:
|
||||
$(AM_V_at)mkdir -p t; \
|
||||
idx=0; \
|
||||
for tgt in $(CHECK_EXTRA_TARGETS); do \
|
||||
if [ -z "$(CI_TOTAL_SHARDS)" ] || [ $$(( idx % $(CI_TOTAL_SHARDS) )) -eq $(CI_SHARD_INDEX) ]; then \
|
||||
s=t/run-$$tgt; \
|
||||
printf '%s\n' \
|
||||
'#!/bin/sh' \
|
||||
'# Generated by `make gen_check_scripts`.' \
|
||||
"t=$$tgt" \
|
||||
'# Drop the parent jobserver from MAKEFLAGS (its fds are lost through' \
|
||||
'# gnu_parallel, causing a spurious warning); keep overrides after "--".' \
|
||||
'MAKEFLAGS=$$(printf "%s" "$$MAKEFLAGS" | sed -e "s/ --jobserver-auth=[^ ]*//g" -e "s/ --jobserver-fds=[^ ]*//g" -e "s/ -j[0-9]*//g")' \
|
||||
'export MAKEFLAGS' \
|
||||
'echo; echo "[----------]"; echo "[ RUN ] >>> make $$t <<<"' \
|
||||
'$(MAKE) --no-print-directory ROCKSDB_RECURSIVE_MAKE_SAME_CONFIG=1 "$$t"' \
|
||||
'rc=$$?' \
|
||||
'if [ "$$rc" = 0 ]; then' \
|
||||
' echo "[ OK ] >>> make $$t <<<"' \
|
||||
'else' \
|
||||
' echo "[ FAILED ] >>> make $$t <<<"' \
|
||||
'fi' \
|
||||
'echo "[----------]"' \
|
||||
'exit $$rc' \
|
||||
> $$s; \
|
||||
chmod a=rx $$s; \
|
||||
fi; \
|
||||
idx=$$((idx + 1)); \
|
||||
done
|
||||
|
||||
# Reorder input lines (one per test or per shard) so the longest-running
|
||||
# tests/shards start first under "make check" parallel scheduling. The trick
|
||||
# is to prefix matched names with a fake duration (100), sort numerically
|
||||
# descending, then strip the prefix. Slow-matched tests therefore come ahead
|
||||
# of all unmatched tests; ordering within each group is unspecified.
|
||||
# Reorder input lines (which are one per test) so that the
|
||||
# longest-running tests appear first in the output.
|
||||
# Do this by prefixing each selected name with its duration,
|
||||
# sort the resulting names, and remove the leading numbers.
|
||||
# FIXME: the "100" we prepend is a fake time, for now.
|
||||
# FIXME: squirrel away timings from each run and use them
|
||||
# (when present) on subsequent runs to order these tests.
|
||||
#
|
||||
# Why this matters: gnu_parallel hands out jobs in input order. If a slow
|
||||
# test starts only after most others have finished, the run is bottlenecked
|
||||
# on its tail. Front-loading slow tests overlaps them with the bulk of
|
||||
# faster ones for much better wall-clock time.
|
||||
# Without this reordering, these two tests would happen to start only
|
||||
# after almost all other tests had completed, thus adding 100 seconds
|
||||
# to the duration of parallel "make check". That's the difference
|
||||
# between 4 minutes (old) and 2m20s (new).
|
||||
#
|
||||
# Maintenance:
|
||||
# 1) Run `make check` so LOG is up-to-date.
|
||||
# 2) Run `make suggest-slow-tests` to see candidate slow binaries.
|
||||
# 3) Add binaries with high per-shard time (slow critical path) or high
|
||||
# total time across many shards (need early queueing for fan-out).
|
||||
# Each alternative is wrapped in `^.*NAME.*$$` so the *whole input line* is
|
||||
# captured into $$1; then `s,(...),100 $$1,` prepends "100 " to the line.
|
||||
# 152.120 PASS t/DBTest.FileCreationRandomFailure
|
||||
# 107.816 PASS t/DBTest.EncodeDecompressedBlockSizeTest
|
||||
#
|
||||
# Tiers below are based on observed timings (see suggest-slow-tests).
|
||||
# Tier 1: max single-shard time >= 30s (critical-path bottlenecks).
|
||||
# Tier 2: max single-shard time 15-30s.
|
||||
# Tier 3: huge total time across many tiny shards; front-loading them keeps
|
||||
# the tail of the run busy while big shards finish.
|
||||
slow_test_regexp = \
|
||||
^.*point_lock_manager_stress_test.*$$|^.*db_test.*$$|^.*external_sst_file_test.*$$|^.*compaction_service_test.*$$|^.*corruption_test.*$$|^.*comparator_db_test.*$$|^.*external_sst_file_basic_test.*$$|^.*rate_limiter_test.*$$|^.*db_compaction_test.*$$|^.*write_prepared_transaction_test.*$$|^.*db_merge_operator_test.*$$|\
|
||||
^.*db_dynamic_level_test.*$$|^.*db_bloom_filter_test.*$$|^.*error_handler_fs_test.*$$|^.*merge_helper_test.*$$|^.*transaction_test.*$$|^.*db_kv_checksum_test.*$$|^.*inlineskiplist_test.*$$|\
|
||||
^.*db_with_timestamp_basic_test.*$$|^.*table_test.*$$|^.*db_wal_test.*$$|^.*block_based_table_reader_test.*$$|^.*block_test.*$$|\
|
||||
^.*run-check-c-api-gen.*$$|^.*run-check-format.*$$
|
||||
^.*MySQLStyleTransactionTest.*$$|^.*SnapshotConcurrentAccessTest.*$$|^.*SeqAdvanceConcurrentTest.*$$|^t/run-table_test-HarnessTest.Randomized$$|^t/run-db_test-.*(?:FileCreationRandomFailure|EncodeDecompressedBlockSizeTest)$$|^.*RecoverFromCorruptedWALWithoutFlush$$
|
||||
prioritize_long_running_tests = \
|
||||
perl -pe 's,($(slow_test_regexp)),100 $$1,' \
|
||||
| sort -k1,1gr \
|
||||
| sed 's/^[.0-9]* //'
|
||||
|
||||
# Helper: print binaries observed to be slow in the last `make check` run.
|
||||
# Use this to decide whether `slow_test_regexp` above needs updating.
|
||||
# Aggregates per-binary across shards; flags any binary whose max single-shard
|
||||
# time is >= 20s OR whose total time is >= 200s.
|
||||
.PHONY: suggest-slow-tests
|
||||
suggest-slow-tests:
|
||||
@if [ ! -s LOG ]; then \
|
||||
echo "No (or empty) LOG file. Run 'make check' first." >&2; exit 1; \
|
||||
fi
|
||||
@bash -c '$(quoted_perl_command)' < LOG | awk '\
|
||||
{ \
|
||||
t=$$1; name=$$3; \
|
||||
sub(/^t\/run-/, "", name); \
|
||||
sub(/-shard-[0-9]+$$/, "", name); \
|
||||
total[name] += t; \
|
||||
if (t > max[name]) max[name] = t; \
|
||||
count[name]++; \
|
||||
} \
|
||||
END { \
|
||||
printf "%8s %8s %5s %s\n", "TOTAL_s", "MAX_s", "SHRDS", "BINARY"; \
|
||||
for (n in total) \
|
||||
if (max[n] >= 20 || total[n] >= 200) \
|
||||
printf "%8.1f %8.1f %5d %s\n", total[n], max[n], count[n], n; \
|
||||
}' | (read header; echo "$$header"; sort -k2,2gr)
|
||||
|
||||
# "make check" uses
|
||||
# Run with "make J=1 check" to disable parallelism in "make check".
|
||||
# Run with "make J=200% check" to run two parallel jobs per core.
|
||||
@@ -1102,14 +945,8 @@ check_0:
|
||||
'To monitor subtest <duration,pass/fail,name>,' \
|
||||
' run "make watch-log" in a separate window' ''; \
|
||||
{ \
|
||||
NON_PARALLEL_LIST="$(filter-out $(PARALLEL_TEST),$(ROCKSDBTESTS_SUBSET))"; \
|
||||
if [ -n "$$NON_PARALLEL_LIST" ]; then \
|
||||
printf './%s\n' $$NON_PARALLEL_LIST \
|
||||
| if [ -n "$(CI_TOTAL_SHARDS)" ]; then \
|
||||
awk -v s=$(CI_SHARD_INDEX) -v n=$(CI_TOTAL_SHARDS) '(NR-1)%n==s'; \
|
||||
else cat; fi; \
|
||||
fi; \
|
||||
$(FIND) t -name 'run-*' -print; \
|
||||
printf './%s\n' $(filter-out $(PARALLEL_TEST),$(TESTS)); \
|
||||
find t -name 'run-*' -print; \
|
||||
} \
|
||||
| $(prioritize_long_running_tests) \
|
||||
| grep -E '$(tests-regexp)' \
|
||||
@@ -1131,7 +968,7 @@ valgrind_check_0:
|
||||
' run "make watch-log" in a separate window' ''; \
|
||||
{ \
|
||||
printf './%s\n' $(filter-out $(PARALLEL_TEST) %skiplist_test options_settable_test, $(TESTS)); \
|
||||
$(FIND) t -name 'run-*' -print; \
|
||||
find t -name 'run-*' -print; \
|
||||
} \
|
||||
| $(prioritize_long_running_tests) \
|
||||
| grep -E '$(tests-regexp)' \
|
||||
@@ -1164,120 +1001,29 @@ check-progress:
|
||||
# If J != 1 and GNU parallel is installed, run the tests in parallel,
|
||||
# via the check_0 rule above. Otherwise, run them sequentially.
|
||||
check: all
|
||||
$(AM_V_at)echo "Cleaning up stale test directories older than 3 hours..."; \
|
||||
test_tmpdir_parent=$$(dirname $(TEST_TMPDIR)); \
|
||||
find $$test_tmpdir_parent -maxdepth 1 -name 'rocksdb.*' -type d \
|
||||
-mmin +180 -exec rm -rf {} + 2>/dev/null; \
|
||||
true
|
||||
$(MAKE) gen_parallel_tests
|
||||
$(AM_V_GEN)if test "$(J)" != 1 \
|
||||
&& (build_tools/gnu_parallel --gnu --help 2>/dev/null) | \
|
||||
grep -q 'GNU Parallel'; \
|
||||
then \
|
||||
$(MAKE) gen_check_scripts; \
|
||||
$(MAKE) T="$$t" check_0; \
|
||||
else \
|
||||
for t in $(TESTS); do \
|
||||
echo "===== Running $$t (`date`)"; ./$$t || exit 1; done; \
|
||||
for t in $(CHECK_EXTRA_TARGETS); do \
|
||||
echo "===== Running $$t (`date`)"; $(MAKE) $$t || exit 1; done; \
|
||||
fi
|
||||
rm -rf $(TEST_TMPDIR)
|
||||
# NOTE: ^^^^^^^^ don't add new auxiliary checks here, but instead to
|
||||
# CHECK_EXTRA_TARGETS
|
||||
|
||||
# Check that the auto-generated C API files are up to date. It regenerates the
|
||||
# fragments and the inlined c.h/c.cc and compares them against a snapshot of the
|
||||
# checked-in copies (no net change when everything is up to date). It requires
|
||||
# clang++ (libclang, used to parse the C++ headers) and clang-format. When those
|
||||
# are unavailable the staleness/compat sub-checks are SKIPPED with a message so
|
||||
# `make check` still works without the codegen toolchain; the link-completeness
|
||||
# sub-check always runs (it needs no toolchain).
|
||||
#
|
||||
# Pin the formatter to match CI by setting CLANG_FORMAT_BINARY, e.g.:
|
||||
# make check-c-api-gen CLANG_FORMAT_BINARY=clang-format-21
|
||||
# This target is part of `make check` and is skipped by SKIP_FORMAT_BUCK_CHECKS.
|
||||
#
|
||||
# Set CHECK_C_API_GEN_STRICT=1 to turn every "skip" below into a hard error, so a
|
||||
# core CI job that runs this target cannot silently regress to a no-op if a
|
||||
# prerequisite (clang++, or the compat baseline ref) goes missing. The dedicated
|
||||
# build-linux-clang-21-no_test_run CI job runs this target with the flag set.
|
||||
# Any non-empty value other than 0/no/false enables strict mode.
|
||||
CLANG_FORMAT_BINARY ?=
|
||||
# Backward-compatibility baseline for the C API (signature-level) check. CI
|
||||
# overrides this with the PR's merge target or the branch's pre-push tip;
|
||||
# locally it falls back to main or origin/main and is skipped if neither resolves.
|
||||
API_COMPAT_REF ?= main
|
||||
CHECK_C_API_GEN_STRICT ?=
|
||||
check-c-api-gen:
|
||||
# Link-completeness is a property of the checked-in c.h/c.cc and needs no
|
||||
# clang toolchain, so it always runs: every declared public C API function
|
||||
# must have exactly one definition (guards against dropped wrappers that
|
||||
# would break downstream language bindings at link time).
|
||||
$(PYTHON) tools/c_api_gen/check_api_completeness.py
|
||||
# Backward-compatibility: no public C function may be removed or have its
|
||||
# signature changed vs the baseline. Skipped if the baseline ref is not
|
||||
# resolvable locally (CI passes an explicit ref), unless CHECK_C_API_GEN_STRICT.
|
||||
@strict=""; case "$(CHECK_C_API_GEN_STRICT)" in ""|0|no|NO|false|FALSE) ;; *) strict=1 ;; esac; \
|
||||
ref=""; \
|
||||
if git rev-parse --verify --quiet "$(API_COMPAT_REF)^{commit}" >/dev/null; then ref="$(API_COMPAT_REF)"; \
|
||||
elif git rev-parse --verify --quiet "origin/$(API_COMPAT_REF)^{commit}" >/dev/null; then ref="origin/$(API_COMPAT_REF)"; fi; \
|
||||
if [ -n "$$ref" ]; then \
|
||||
$(PYTHON) tools/c_api_gen/check_api_compatibility.py --ref "$$ref"; \
|
||||
elif [ -n "$$strict" ]; then \
|
||||
echo "ERROR: C API compat baseline '$(API_COMPAT_REF)' not resolvable and CHECK_C_API_GEN_STRICT is set" >&2; exit 1; \
|
||||
else \
|
||||
echo "Skipping C API backward-compatibility check ($(API_COMPAT_REF) not found; set API_COMPAT_REF)"; \
|
||||
fi
|
||||
# Staleness: regenerate and confirm the checked-in output is current. Needs a
|
||||
# clang++ (the generator parses C++ ASTs). Use CLANG_CXX, which
|
||||
# build_tools/build_detect_platform resolves once (the fbcode clang++ in
|
||||
# fbcode builds, else a versioned clang++ on PATH) and passes explicitly, so
|
||||
# the check and the generator agree on the same binary without heuristics.
|
||||
@strict=""; case "$(CHECK_C_API_GEN_STRICT)" in ""|0|no|NO|false|FALSE) ;; *) strict=1 ;; esac; \
|
||||
cf_arg=""; \
|
||||
if [ -n "$(CLANG_FORMAT_BINARY)" ]; then cf_arg="--clang-format $(CLANG_FORMAT_BINARY)"; fi; \
|
||||
if [ -n "$(CLANG_CXX)" ] && command -v "$(CLANG_CXX)" >/dev/null 2>&1; then \
|
||||
$(PYTHON) tools/c_api_gen/verify_generated_up_to_date.py --clang "$(CLANG_CXX)" $$cf_arg; \
|
||||
elif [ -n "$$strict" ]; then \
|
||||
echo "ERROR: no clang++ found (CLANG_CXX unset) and CHECK_C_API_GEN_STRICT is set; cannot run the C API staleness check" >&2; exit 1; \
|
||||
else \
|
||||
echo "Skipping C API codegen staleness check (no clang++ found; CLANG_CXX unset, install clang++ to enable)"; \
|
||||
fi
|
||||
|
||||
# Regenerate the checked-in C API generated files (fragments under c_api_gen/,
|
||||
# the inlined include/rocksdb/c.h and db/c.cc, and the round-trip tests). Uses
|
||||
# CLANG_CXX (resolved by build_tools/build_detect_platform) so it works in a gcc
|
||||
# build too. Aborts up front if no usable clang++ is available, so a bad
|
||||
# toolchain never leaves the tree in a partially regenerated state. Pin the
|
||||
# formatter to match CI with CLANG_FORMAT_BINARY, e.g.:
|
||||
# make regen-c-api CLANG_FORMAT_BINARY=clang-format-21
|
||||
.PHONY: regen-c-api
|
||||
regen-c-api:
|
||||
@if [ -z "$(CLANG_CXX)" ] || ! command -v "$(CLANG_CXX)" >/dev/null 2>&1; then \
|
||||
echo "ERROR: no clang++ found (CLANG_CXX unset); build on a host with clang++ or the fbcode toolchain to regenerate the C API" >&2; exit 1; \
|
||||
fi
|
||||
@cf_arg=""; \
|
||||
if [ -n "$(CLANG_FORMAT_BINARY)" ]; then cf_arg="--clang-format $(CLANG_FORMAT_BINARY)"; fi; \
|
||||
$(PYTHON) tools/c_api_gen/regen_all.py --clang "$(CLANG_CXX)" $$cf_arg
|
||||
|
||||
# Quick local validation for C API generation plus the focused C API test.
|
||||
# This verifies the checked-in generated fragments as well as the inlined
|
||||
# include/rocksdb/c.h and db/c.cc outputs, then runs c_test in an isolated
|
||||
# TEST_TMPDIR to avoid stale-state failures.
|
||||
check-c-api-c_test:
|
||||
$(PYTHON) tools/c_api_gen/verify_generated_up_to_date.py --clang "$(CLANG_CXX)"
|
||||
$(MAKE) c_test
|
||||
@tmpdir=$$(mktemp -d); \
|
||||
trap 'rm -rf "$$tmpdir"' EXIT; \
|
||||
echo "===== Running c_test with TEST_TMPDIR=$$tmpdir"; \
|
||||
if command -v timeout >/dev/null 2>&1; then \
|
||||
TEST_TMPDIR="$$tmpdir" timeout 60 ./c_test; \
|
||||
elif command -v gtimeout >/dev/null 2>&1; then \
|
||||
TEST_TMPDIR="$$tmpdir" gtimeout 60 ./c_test; \
|
||||
else \
|
||||
TEST_TMPDIR="$$tmpdir" ./c_test; \
|
||||
fi
|
||||
ifneq ($(PLATFORM), OS_AIX)
|
||||
$(PYTHON) tools/check_all_python.py
|
||||
ifndef ASSERT_STATUS_CHECKED # not yet working with these tests
|
||||
$(PYTHON) tools/ldb_test.py
|
||||
sh tools/rocksdb_dump_test.sh
|
||||
endif
|
||||
endif
|
||||
ifndef SKIP_FORMAT_BUCK_CHECKS
|
||||
$(MAKE) check-format
|
||||
$(MAKE) check-buck-targets
|
||||
$(MAKE) check-sources
|
||||
endif
|
||||
|
||||
# TODO add ldb_tests
|
||||
check_some: $(ROCKSDBTESTS_SUBSET)
|
||||
@@ -1287,18 +1033,6 @@ check_some: $(ROCKSDBTESTS_SUBSET)
|
||||
ldb_tests: ldb
|
||||
$(PYTHON) tools/ldb_test.py
|
||||
|
||||
.PHONY: db_crashtest_tests
|
||||
db_crashtest_tests:
|
||||
$(PYTHON) tools/db_crashtest_test.py
|
||||
|
||||
.PHONY: check-all-python
|
||||
check-all-python:
|
||||
$(PYTHON) tools/check_all_python.py
|
||||
|
||||
.PHONY: rocksdb_dump_test
|
||||
rocksdb_dump_test: rocksdb_dump rocksdb_undump
|
||||
sh tools/rocksdb_dump_test.sh
|
||||
|
||||
include crash_test.mk
|
||||
|
||||
asan_check: clean
|
||||
@@ -1436,32 +1170,16 @@ rocksdb.h rocksdb.cc: build_tools/amalgamate.py Makefile $(LIB_SOURCES) unity.cc
|
||||
build_tools/amalgamate.py -I. -i./include unity.cc -x include/rocksdb/c.h -H rocksdb.h -o rocksdb.cc
|
||||
|
||||
clean: clean-ext-libraries-all clean-rocks clean-rocksjava
|
||||
# Removed here rather than in clean-rocks (via CLEAN_FILES) so the build-parameter
|
||||
# auto-clean, which runs clean-rocks, doesn't delete the make_config.mk already
|
||||
# included by the in-progress make.
|
||||
@rm -f make_config.mk
|
||||
|
||||
clean-not-downloaded: clean-ext-libraries-bin clean-rocks clean-not-downloaded-rocksjava
|
||||
@rm -f make_config.mk
|
||||
|
||||
clean-rocks:
|
||||
# Not practical to exactly match all versions/variants in naming (e.g. debug or not)
|
||||
@echo Removing link targets
|
||||
@rm -f ${LIBNAME}*.so* ${LIBNAME}*.a $(BENCHMARKS) $(TOOLS) $(TESTS) $(PARALLEL_TEST) $(MICROBENCHS)
|
||||
@echo Finding and cleaning other files
|
||||
@rm -rf $(CLEAN_FILES) ios-x86 ios-arm scan_build_report
|
||||
@if $(FIND) Makefile -regextype awk &> /dev/null; then \
|
||||
$(FIND) . -regextype awk \
|
||||
-regex '.*/([.].*|third-party)' -prune -o \
|
||||
-type f -regex '.*[.]([oda]|gcda|gcno)' -exec rm -f {} \; ; \
|
||||
else \
|
||||
$(FIND) . -name "*.[oda]" -exec rm -f {} \; ; \
|
||||
fi
|
||||
# Remove the build signature(s) LAST. Done after the object files are gone so
|
||||
# that a Ctrl+C partway through clean leaves the old signature in place: it
|
||||
# still matches the leftover objects, so a later build with different
|
||||
# parameters is still detected (signature usefulness is preserved).
|
||||
@rm -f $(BUILD_SIG_FILE) jl/.build_signature jls/.build_signature
|
||||
rm -f ${LIBNAME}*.so* ${LIBNAME}*.a
|
||||
rm -f $(BENCHMARKS) $(TOOLS) $(TESTS) $(PARALLEL_TEST) $(MICROBENCHS)
|
||||
rm -rf $(CLEAN_FILES) ios-x86 ios-arm scan_build_report
|
||||
$(FIND) . -name "*.[oda]" -exec rm -f {} \;
|
||||
$(FIND) . -type f \( -name "*.gcda" -o -name "*.gcno" \) -exec rm -f {} \;
|
||||
|
||||
clean-rocksjava: clean-rocks
|
||||
rm -rf jl jls
|
||||
@@ -1474,7 +1192,7 @@ clean-ext-libraries-all:
|
||||
rm -rf bzip2* snappy* zlib* lz4* zstd*
|
||||
|
||||
clean-ext-libraries-bin:
|
||||
$(FIND) . -maxdepth 1 -type d \( -name bzip2\* -or -name snappy\* -or -name zlib\* -or -name lz4\* -or -name zstd\* \) -prune -exec rm -rf {} \;
|
||||
find . -maxdepth 1 -type d \( -name bzip2\* -or -name snappy\* -or -name zlib\* -or -name lz4\* -or -name zstd\* \) -prune -exec rm -rf {} \;
|
||||
|
||||
tags:
|
||||
ctags -R .
|
||||
@@ -1498,43 +1216,12 @@ format-auto:
|
||||
check-format:
|
||||
build_tools/format-diff.sh -c
|
||||
|
||||
|
||||
# Crude alternative to setup-hooks: copies hooks into .git/hooks/ instead of
|
||||
# using core.hooksPath. The copies won't track changes to githooks/.
|
||||
install-hooks:
|
||||
@echo "Installing git hooks from githooks/..."
|
||||
@if [ -d githooks ]; then \
|
||||
for hook in githooks/*; do \
|
||||
hook_name=$$(basename "$$hook"); \
|
||||
cp "$$hook" .git/hooks/"$$hook_name"; \
|
||||
chmod +x .git/hooks/"$$hook_name"; \
|
||||
echo " Installed $$hook_name"; \
|
||||
done; \
|
||||
echo "Done. Hooks installed to .git/hooks/"; \
|
||||
else \
|
||||
echo "Error: githooks/ directory not found"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
# Reverse of install-hooks (not needed if using setup-hooks / core.hooksPath).
|
||||
uninstall-hooks:
|
||||
@echo "Removing installed git hooks..."
|
||||
@for hook in githooks/*; do \
|
||||
hook_name=$$(basename "$$hook"); \
|
||||
rm -f .git/hooks/"$$hook_name"; \
|
||||
echo " Removed $$hook_name"; \
|
||||
done
|
||||
@echo "Done."
|
||||
|
||||
check-buck-targets:
|
||||
buckifier/check_buck_targets.sh
|
||||
|
||||
check-sources:
|
||||
build_tools/check-sources.sh
|
||||
|
||||
check-workflow-yaml:
|
||||
build_tools/check-workflow-yaml.sh
|
||||
|
||||
# Run clang-tidy on locally changed files, filtered to changed lines only.
|
||||
# Requires compile_commands.json (generate with cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON).
|
||||
# Override CLANG_TIDY_BINARY and CLANG_TIDY_JOBS as needed:
|
||||
@@ -1722,9 +1409,6 @@ db_basic_test: $(OBJ_DIR)/db/db_basic_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
db_blob_basic_test: $(OBJ_DIR)/db/blob/db_blob_basic_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
db_blob_direct_write_test: $(OBJ_DIR)/db/blob/db_blob_direct_write_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
db_blob_compaction_test: $(OBJ_DIR)/db/blob/db_blob_compaction_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1734,12 +1418,6 @@ db_readonly_with_timestamp_test: $(OBJ_DIR)/db/db_readonly_with_timestamp_test.o
|
||||
db_wide_basic_test: $(OBJ_DIR)/db/wide/db_wide_basic_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
db_lazy_entity_test: $(OBJ_DIR)/db/wide/db_lazy_entity_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
db_wide_blob_direct_write_test: $(OBJ_DIR)/db/wide/db_wide_blob_direct_write_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
db_with_timestamp_basic_test: $(OBJ_DIR)/db/db_with_timestamp_basic_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1749,13 +1427,10 @@ db_with_timestamp_compaction_test: db/db_with_timestamp_compaction_test.o $(TEST
|
||||
db_encryption_test: $(OBJ_DIR)/db/db_encryption_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
db_open_with_config_test: $(OBJ_DIR)/db/db_open_with_config_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
db_test: $(OBJ_DIR)/db/db_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
db_etc2_test: $(OBJ_DIR)/db/db_etc2_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
db_test2: $(OBJ_DIR)/db/db_test2.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
db_etc3_test: $(OBJ_DIR)/db/db_etc3_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
@@ -1896,12 +1571,6 @@ backup_engine_test: $(OBJ_DIR)/utilities/backup/backup_engine_test.o $(TEST_LIBR
|
||||
checkpoint_test: $(OBJ_DIR)/utilities/checkpoint/checkpoint_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
copy_engine_test: $(OBJ_DIR)/utilities/copy_engine/copy_engine_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
sorted_run_builder_test: $(OBJ_DIR)/utilities/sorted_run_builder/sorted_run_builder_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
cache_simulator_test: $(OBJ_DIR)/utilities/simulator_cache/cache_simulator_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1920,12 +1589,6 @@ object_registry_test: $(OBJ_DIR)/utilities/object_registry_test.o $(TEST_LIBRARY
|
||||
ttl_test: $(OBJ_DIR)/utilities/ttl/ttl_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
trie_index_db_test: $(OBJ_DIR)/utilities/trie_index/trie_index_db_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
trie_index_test: $(OBJ_DIR)/utilities/trie_index/trie_index_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
types_util_test: $(OBJ_DIR)/utilities/types_util_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1977,9 +1640,6 @@ io_posix_test: $(OBJ_DIR)/env/io_posix_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
fault_injection_test: $(OBJ_DIR)/db/fault_injection_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
fault_injection_fs_test: $(OBJ_DIR)/utilities/fault_injection_fs_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
rate_limiter_test: $(OBJ_DIR)/util/rate_limiter_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -2019,9 +1679,6 @@ block_fetcher_test: table/block_fetcher_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
block_test: $(OBJ_DIR)/table/block_based/block_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
builtin_index_factory_test: $(OBJ_DIR)/table/block_based/builtin_index_factory_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
data_block_hash_index_test: $(OBJ_DIR)/table/block_based/data_block_hash_index_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -2181,7 +1838,7 @@ write_committed_transaction_ts_test: $(OBJ_DIR)/utilities/transactions/write_com
|
||||
write_prepared_transaction_test: $(OBJ_DIR)/utilities/transactions/write_prepared_transaction_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
write_prepared_transaction_seqno_test: $(OBJ_DIR)/utilities/transactions/write_prepared_transaction_seqno_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
write_prepared_transaction_test_seqno: $(OBJ_DIR)/utilities/transactions/write_prepared_transaction_test_seqno.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
write_unprepared_transaction_test: $(OBJ_DIR)/utilities/transactions/write_unprepared_transaction_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
@@ -2444,27 +2101,22 @@ ROCKSDB_JAVADOCS_JAR = rocksdbjni-$(ROCKSDB_JAVA_VERSION)-javadoc.jar
|
||||
ROCKSDB_SOURCES_JAR = rocksdbjni-$(ROCKSDB_JAVA_VERSION)-sources.jar
|
||||
SHA256_CMD = sha256sum
|
||||
|
||||
# The *_DOWNLOAD_PREFIX defaults below point at the upstream projects; CI
|
||||
# overrides them to a mirror on the "third-party-deps" GitHub release (see
|
||||
# .github/actions/pre-steps/action.yml). When bumping a version, see
|
||||
# instructions in CI config comments for how to update that release.
|
||||
ZLIB_VER ?= 1.3.1
|
||||
ZLIB_SHA256 ?= 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23
|
||||
ZLIB_DOWNLOAD_PREFIX ?= http://zlib.net/zlib-
|
||||
ZLIB_DOWNLOAD_BASE ?= http://zlib.net
|
||||
BZIP2_VER ?= 1.0.8
|
||||
BZIP2_SHA256 ?= ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269
|
||||
BZIP2_DOWNLOAD_PREFIX ?= http://sourceware.org/pub/bzip2/bzip2-
|
||||
BZIP2_DOWNLOAD_BASE ?= http://sourceware.org/pub/bzip2
|
||||
SNAPPY_VER ?= 1.2.2
|
||||
SNAPPY_SHA256 ?= 90f74bc1fbf78a6c56b3c4a082a05103b3a56bb17bca1a27e052ea11723292dc
|
||||
SNAPPY_DOWNLOAD_PREFIX ?= https://github.com/google/snappy/archive/
|
||||
SNAPPY_DOWNLOAD_BASE ?= https://github.com/google/snappy/archive
|
||||
LZ4_VER ?= 1.10.0
|
||||
LZ4_SHA256 ?= 537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b
|
||||
LZ4_DOWNLOAD_PREFIX ?= https://github.com/lz4/lz4/archive/v
|
||||
LZ4_DOWNLOAD_BASE ?= https://github.com/lz4/lz4/archive
|
||||
ZSTD_VER ?= 1.5.7
|
||||
ZSTD_SHA256 ?= 37d7284556b20954e56e1ca85b80226768902e2edabd3b649e9e72c0c9012ee3
|
||||
ZSTD_DOWNLOAD_PREFIX ?= https://github.com/facebook/zstd/archive/v
|
||||
# curl with the common options used to fetch the pinned third-party sources above
|
||||
CURL_DOWNLOAD = curl --fail --location --retry 3 --retry-all-errors
|
||||
ZSTD_DOWNLOAD_BASE ?= https://github.com/facebook/zstd/archive
|
||||
CURL_SSL_OPTS ?= --tlsv1
|
||||
|
||||
ifeq ($(PLATFORM), OS_MACOSX)
|
||||
ifeq (,$(findstring librocksdbjni-osx,$(ROCKSDBJNILIB)))
|
||||
@@ -2509,103 +2161,8 @@ ifeq ($(PLATFORM), OS_OPENBSD)
|
||||
endif
|
||||
export SHA256_CMD
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Build parameter change detection
|
||||
# ----------------------------------------------------------------------------
|
||||
# RocksDB writes object files to the same $(OBJ_DIR) paths regardless of
|
||||
# DEBUG_LEVEL, sanitizers (ASAN/TSAN/UBSAN), ASSERT_STATUS_CHECKED, RTTI, LTO,
|
||||
# COERCE_CONTEXT_SWITCH, etc. Most of those are applied in this Makefile after
|
||||
# `include make_config.mk` and are therefore NOT reflected in make_config.mk,
|
||||
# so switching them and rebuilding silently mixes incompatible object files.
|
||||
# To guard against that, we hash the fully-resolved compile/link parameters
|
||||
# (which already embed make_config.mk via PLATFORM_*) and compare against the
|
||||
# value recorded from the previous build. On mismatch the build stops so the
|
||||
# user can `make clean`. Knobs:
|
||||
# AUTO_CLEAN=1
|
||||
# run `make clean-rocks` automatically on mismatch
|
||||
# ALLOW_BUILD_PARAMETER_CHANGE=1
|
||||
# skip the check entirely (e.g. intentionally mixing DEBUG_LEVEL=1 and
|
||||
# DEBUG_LEVEL=2)
|
||||
# The signature is stored per-$(OBJ_DIR), so Java (jl/jls) builds are tracked
|
||||
# independently from the default build.
|
||||
BUILD_SIG_FILE := $(OBJ_DIR)/.build_signature
|
||||
# NOTE: deliberately NOT added to CLEAN_FILES. The signature is removed as the
|
||||
# very last step of clean-rocks so that an interrupted clean keeps it (see
|
||||
# clean-rocks), preserving change detection across a Ctrl+C'd clean.
|
||||
|
||||
# Goals that do not compile object files into the tree (pure utilities,
|
||||
# informational, source/config checks): the change check is irrelevant for them.
|
||||
BUILD_SIG_NONBUILD_GOALS := \
|
||||
clean clean-rocks clean-not-downloaded clean-rocksjava \
|
||||
clean-not-downloaded-rocksjava clean-ext-libraries-all \
|
||||
clean-ext-libraries-bin \
|
||||
format format-auto check-format check-buck-targets check-headers \
|
||||
check-sources check-workflow-yaml check-progress clang-tidy \
|
||||
tags tags0 package jclean checkout_folly build_folly \
|
||||
watch-log dump-log suggest-slow-tests list_all_tests gen-pc \
|
||||
gen_parallel_tests gen_check_scripts check-c-api-gen check-all-python \
|
||||
setup-hooks install-hooks uninstall-hooks uninstall db_crashtest_tests
|
||||
# Goals that clean before building (depend on or invoke `clean`): they manage
|
||||
# their own freshness, so the check must not block them (it would error before
|
||||
# their built-in clean runs).
|
||||
BUILD_SIG_NONBUILD_GOALS += \
|
||||
release coverage build_size analyze analyze_incremental \
|
||||
asan_check asan_crash_test asan_crash_test_with_atomic_flush \
|
||||
asan_crash_test_with_txn asan_crash_test_with_best_efforts_recovery \
|
||||
whitebox_asan_crash_test blackbox_asan_crash_test \
|
||||
ubsan_check ubsan_crash_test ubsan_crash_test_with_atomic_flush \
|
||||
ubsan_crash_test_with_txn ubsan_crash_test_with_best_efforts_recovery \
|
||||
whitebox_ubsan_crash_test blackbox_ubsan_crash_test
|
||||
|
||||
# Goals that explicitly clean; never trip the check when one is requested.
|
||||
BUILD_SIG_CLEAN_GOALS := \
|
||||
clean clean-rocks clean-not-downloaded clean-rocksjava \
|
||||
clean-not-downloaded-rocksjava clean-ext-libraries-all \
|
||||
clean-ext-libraries-bin
|
||||
|
||||
BUILD_SIG_GOALS := $(if $(MAKECMDGOALS),$(MAKECMDGOALS),all)
|
||||
BUILD_SIG_DO_BUILD := $(filter-out $(BUILD_SIG_NONBUILD_GOALS),$(BUILD_SIG_GOALS))
|
||||
BUILD_SIG_CLEANING := $(filter $(BUILD_SIG_CLEAN_GOALS),$(MAKECMDGOALS))
|
||||
# Dry runs (-n/--just-print) must not write the stamp, clean, or error; the
|
||||
# parse-time $(shell) below would otherwise run even under -n. Note that
|
||||
# actual options are canonicalized and shorted as possible such that all
|
||||
# short options are in the first word of MAKEFLAGS.
|
||||
BUILD_SIG_DRYRUN := $(findstring n,$(firstword -$(MAKEFLAGS)))
|
||||
|
||||
# Only enforce at the top level. Sub-makes (e.g. `check` invokes
|
||||
# $(MAKE) gen_parallel_tests / check-c-api-gen / check_0) inherit the parent's
|
||||
# build flags, so the top-level check already covers them; re-checking inside a
|
||||
# sub-make only causes spurious failures.
|
||||
ifneq ($(ALLOW_BUILD_PARAMETER_CHANGE),1)
|
||||
ifeq ($(MAKELEVEL),0)
|
||||
ifeq ($(BUILD_SIG_DRYRUN),)
|
||||
ifeq ($(BUILD_SIG_CLEANING),)
|
||||
ifneq ($(BUILD_SIG_DO_BUILD),)
|
||||
BUILD_SIG := $(shell printf '%s' '$(CC)|$(CXX)|$(CFLAGS)|$(CXXFLAGS)|$(LDFLAGS)|$(EXEC_LDFLAGS)' | $(SHA256_CMD) | cut -d ' ' -f 1)
|
||||
BUILD_SIG_OLD := $(shell cat $(BUILD_SIG_FILE) 2>/dev/null)
|
||||
ifneq ($(BUILD_SIG_OLD),)
|
||||
ifneq ($(BUILD_SIG_OLD),$(BUILD_SIG))
|
||||
ifeq ($(AUTO_CLEAN),1)
|
||||
$(info *** Build parameters changed since last build (OBJ_DIR=$(OBJ_DIR)); running 'make clean-rocks' because AUTO_CLEAN=1)
|
||||
BUILD_SIG_CLEAN_OUTPUT := $(shell $(MAKE) clean-rocks 1>&2)
|
||||
ifneq ($(.SHELLSTATUS),0)
|
||||
$(error AUTO_CLEAN: 'make clean-rocks' failed (exit $(.SHELLSTATUS)); not building against a partially-cleaned tree)
|
||||
endif
|
||||
else
|
||||
$(error Build parameters changed since the last build (OBJ_DIR=$(OBJ_DIR)). Existing object files are stale and must be removed. Run 'make clean', or set AUTO_CLEAN=1 to clean automatically, or ALLOW_BUILD_PARAMETER_CHANGE=1 to build anyway)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
# Record the current signature for the next build.
|
||||
BUILD_SIG_WRITE := $(shell mkdir -p $(OBJ_DIR) 2>/dev/null; printf '%s\n' '$(BUILD_SIG)' > $(BUILD_SIG_FILE))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
zlib-$(ZLIB_VER).tar.gz:
|
||||
$(CURL_DOWNLOAD) --output zlib-$(ZLIB_VER).tar.gz ${ZLIB_DOWNLOAD_PREFIX}$(ZLIB_VER).tar.gz
|
||||
curl --fail --output zlib-$(ZLIB_VER).tar.gz --location ${ZLIB_DOWNLOAD_BASE}/zlib-$(ZLIB_VER).tar.gz
|
||||
ZLIB_SHA256_ACTUAL=`$(SHA256_CMD) zlib-$(ZLIB_VER).tar.gz | cut -d ' ' -f 1`; \
|
||||
if [ "$(ZLIB_SHA256)" != "$$ZLIB_SHA256_ACTUAL" ]; then \
|
||||
echo zlib-$(ZLIB_VER).tar.gz checksum mismatch, expected=\"$(ZLIB_SHA256)\" actual=\"$$ZLIB_SHA256_ACTUAL\"; \
|
||||
@@ -2623,7 +2180,7 @@ libz.a: zlib-$(ZLIB_VER).tar.gz
|
||||
cp zlib-$(ZLIB_VER)/libz.a .
|
||||
|
||||
bzip2-$(BZIP2_VER).tar.gz:
|
||||
$(CURL_DOWNLOAD) --output bzip2-$(BZIP2_VER).tar.gz ${BZIP2_DOWNLOAD_PREFIX}$(BZIP2_VER).tar.gz
|
||||
curl --fail --output bzip2-$(BZIP2_VER).tar.gz --location ${CURL_SSL_OPTS} ${BZIP2_DOWNLOAD_BASE}/bzip2-$(BZIP2_VER).tar.gz
|
||||
BZIP2_SHA256_ACTUAL=`$(SHA256_CMD) bzip2-$(BZIP2_VER).tar.gz | cut -d ' ' -f 1`; \
|
||||
if [ "$(BZIP2_SHA256)" != "$$BZIP2_SHA256_ACTUAL" ]; then \
|
||||
echo bzip2-$(BZIP2_VER).tar.gz checksum mismatch, expected=\"$(BZIP2_SHA256)\" actual=\"$$BZIP2_SHA256_ACTUAL\"; \
|
||||
@@ -2637,7 +2194,7 @@ libbz2.a: bzip2-$(BZIP2_VER).tar.gz
|
||||
cp bzip2-$(BZIP2_VER)/libbz2.a .
|
||||
|
||||
snappy-$(SNAPPY_VER).tar.gz:
|
||||
$(CURL_DOWNLOAD) --output snappy-$(SNAPPY_VER).tar.gz ${SNAPPY_DOWNLOAD_PREFIX}$(SNAPPY_VER).tar.gz
|
||||
curl --fail --output snappy-$(SNAPPY_VER).tar.gz --location ${CURL_SSL_OPTS} ${SNAPPY_DOWNLOAD_BASE}/$(SNAPPY_VER).tar.gz
|
||||
SNAPPY_SHA256_ACTUAL=`$(SHA256_CMD) snappy-$(SNAPPY_VER).tar.gz | cut -d ' ' -f 1`; \
|
||||
if [ "$(SNAPPY_SHA256)" != "$$SNAPPY_SHA256_ACTUAL" ]; then \
|
||||
echo snappy-$(SNAPPY_VER).tar.gz checksum mismatch, expected=\"$(SNAPPY_SHA256)\" actual=\"$$SNAPPY_SHA256_ACTUAL\"; \
|
||||
@@ -2652,7 +2209,7 @@ libsnappy.a: snappy-$(SNAPPY_VER).tar.gz
|
||||
cp snappy-$(SNAPPY_VER)/build/libsnappy.a .
|
||||
|
||||
lz4-$(LZ4_VER).tar.gz:
|
||||
$(CURL_DOWNLOAD) --output lz4-$(LZ4_VER).tar.gz ${LZ4_DOWNLOAD_PREFIX}$(LZ4_VER).tar.gz
|
||||
curl --fail --output lz4-$(LZ4_VER).tar.gz --location ${CURL_SSL_OPTS} ${LZ4_DOWNLOAD_BASE}/v$(LZ4_VER).tar.gz
|
||||
LZ4_SHA256_ACTUAL=`$(SHA256_CMD) lz4-$(LZ4_VER).tar.gz | cut -d ' ' -f 1`; \
|
||||
if [ "$(LZ4_SHA256)" != "$$LZ4_SHA256_ACTUAL" ]; then \
|
||||
echo lz4-$(LZ4_VER).tar.gz checksum mismatch, expected=\"$(LZ4_SHA256)\" actual=\"$$LZ4_SHA256_ACTUAL\"; \
|
||||
@@ -2666,7 +2223,7 @@ liblz4.a: lz4-$(LZ4_VER).tar.gz
|
||||
cp lz4-$(LZ4_VER)/lib/liblz4.a .
|
||||
|
||||
zstd-$(ZSTD_VER).tar.gz:
|
||||
$(CURL_DOWNLOAD) --output zstd-$(ZSTD_VER).tar.gz ${ZSTD_DOWNLOAD_PREFIX}$(ZSTD_VER).tar.gz
|
||||
curl --fail --output zstd-$(ZSTD_VER).tar.gz --location ${CURL_SSL_OPTS} ${ZSTD_DOWNLOAD_BASE}/v$(ZSTD_VER).tar.gz
|
||||
ZSTD_SHA256_ACTUAL=`$(SHA256_CMD) zstd-$(ZSTD_VER).tar.gz | cut -d ' ' -f 1`; \
|
||||
if [ "$(ZSTD_SHA256)" != "$$ZSTD_SHA256_ACTUAL" ]; then \
|
||||
echo zstd-$(ZSTD_VER).tar.gz checksum mismatch, expected=\"$(ZSTD_SHA256)\" actual=\"$$ZSTD_SHA256_ACTUAL\"; \
|
||||
@@ -3004,7 +2561,7 @@ list_all_tests:
|
||||
|
||||
# Remove the rules for which dependencies should not be generated and see if any are left.
|
||||
#If so, include the dependencies; if not, do not include the dependency files
|
||||
ROCKS_DEP_RULES=$(filter-out clean format check-format check-buck-targets check-headers check-sources check-workflow-yaml clang-tidy jclean jtest package analyze tags rocksdbjavastatic% unity.% unity_test checkout_folly, $(MAKECMDGOALS))
|
||||
ROCKS_DEP_RULES=$(filter-out clean format check-format check-buck-targets check-headers check-sources clang-tidy jclean jtest package analyze tags rocksdbjavastatic% unity.% unity_test checkout_folly, $(MAKECMDGOALS))
|
||||
ifneq ("$(ROCKS_DEP_RULES)", "")
|
||||
-include $(DEPFILES)
|
||||
endif
|
||||
@@ -35,49 +35,6 @@ from util import ColorString
|
||||
# tests to export as libraries for inclusion in other projects
|
||||
_EXPORTED_TEST_LIBS = ["env_basic_test"]
|
||||
|
||||
_TEST_LIB_HEADERS = [
|
||||
"db/db_test_util.h",
|
||||
"db/db_with_timestamp_test_util.h",
|
||||
"table/mock_table.h",
|
||||
"test_util/mock_time_env.h",
|
||||
"test_util/secondary_cache_test_util.h",
|
||||
"test_util/simple_external_table_factory.h",
|
||||
"test_util/testharness.h",
|
||||
"test_util/testutil.h",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.h",
|
||||
"tools/trace_analyzer_tool.h",
|
||||
"utilities/agg_merge/test_agg_merge.h",
|
||||
"utilities/cassandra/test_utils.h",
|
||||
]
|
||||
|
||||
_TEST_HEADERS = {
|
||||
"configurable_test": ["options/configurable_test.h"],
|
||||
"persistent_cache_test": ["utilities/persistent_cache/persistent_cache_test.h"],
|
||||
"point_lock_manager_test": [
|
||||
"utilities/transactions/lock/point/point_lock_manager_test.h",
|
||||
],
|
||||
"transaction_test": ["utilities/transactions/transaction_test.h"],
|
||||
}
|
||||
|
||||
_STRESS_LIB_HEADERS = [
|
||||
"db_stress_tool/db_stress_common.h",
|
||||
"db_stress_tool/db_stress_compaction_service.h",
|
||||
"db_stress_tool/db_stress_compression_manager.h",
|
||||
"db_stress_tool/db_stress_driver.h",
|
||||
"db_stress_tool/db_stress_filters.h",
|
||||
"db_stress_tool/db_stress_listener.h",
|
||||
"db_stress_tool/db_stress_shared_state.h",
|
||||
"db_stress_tool/db_stress_test_base.h",
|
||||
"db_stress_tool/db_stress_wide_merge_operator.h",
|
||||
"db_stress_tool/expected_state.h",
|
||||
"db_stress_tool/expected_value.h",
|
||||
"db_stress_tool/multi_ops_txns_stress.h",
|
||||
"test_util/simple_external_table_factory.h",
|
||||
"test_util/testutil.h",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.h",
|
||||
"tools/trace_analyzer_tool.h"
|
||||
]
|
||||
|
||||
# Parse src.mk files as a Dictionary of
|
||||
# VAR_NAME => list of files
|
||||
def parse_src_mk(repo_path):
|
||||
@@ -188,21 +145,11 @@ def generate_buck(repo_path, deps_map):
|
||||
# always add range_tree, it's only excluded on ppc64, which we don't use internally
|
||||
src_mk["RANGE_TREE_SOURCES"] + src_mk["TOOL_LIB_SOURCES"],
|
||||
deps=[
|
||||
"//folly:executor",
|
||||
"//folly/container:f14_hash",
|
||||
"//folly/coro:baton",
|
||||
"//folly/coro:blocking_wait",
|
||||
"//folly/coro:collect",
|
||||
"//folly/coro:coroutine",
|
||||
"//folly/coro:nothrow",
|
||||
"//folly/coro:task",
|
||||
"//folly/executors:io_executor",
|
||||
"//folly/executors:io_thread_pool_executor",
|
||||
"//folly/executors/thread_factory:named_thread_factory",
|
||||
"//folly/io/async:async_base",
|
||||
"//folly/io/async:event_base_manager",
|
||||
"//folly/io/async:io_uring_backend",
|
||||
"//folly/io/async:request_context",
|
||||
"//folly/experimental/coro:blocking_wait",
|
||||
"//folly/experimental/coro:collect",
|
||||
"//folly/experimental/coro:coroutine",
|
||||
"//folly/experimental/coro:task",
|
||||
"//folly/synchronization:distributed_mutex",
|
||||
],
|
||||
headers=LiteralValue("glob([\"**/*.h\"])")
|
||||
@@ -226,34 +173,27 @@ def generate_buck(repo_path, deps_map):
|
||||
":rocksdb_lib",
|
||||
],
|
||||
)
|
||||
test_lib_sources = (
|
||||
src_mk.get("MOCK_LIB_SOURCES", [])
|
||||
+ src_mk.get("TEST_LIB_SOURCES", [])
|
||||
+ src_mk.get("EXP_LIB_SOURCES", [])
|
||||
+ src_mk.get("ANALYZER_LIB_SOURCES", [])
|
||||
)
|
||||
# Older release source lists may not compile every test helper yet.
|
||||
test_lib_headers = [
|
||||
header for header in _TEST_LIB_HEADERS
|
||||
if header[:-2] + ".cc" in test_lib_sources
|
||||
]
|
||||
# rocksdb_test_lib
|
||||
BUCK.add_library(
|
||||
"rocksdb_test_lib",
|
||||
test_lib_sources,
|
||||
src_mk.get("MOCK_LIB_SOURCES", [])
|
||||
+ src_mk.get("TEST_LIB_SOURCES", [])
|
||||
+ src_mk.get("EXP_LIB_SOURCES", [])
|
||||
+ src_mk.get("ANALYZER_LIB_SOURCES", []),
|
||||
[":rocksdb_lib"],
|
||||
extra_test_libs=True,
|
||||
headers=test_lib_headers,
|
||||
)
|
||||
# rocksdb_with_faiss_test_lib
|
||||
BUCK.add_library(
|
||||
"rocksdb_with_faiss_test_lib",
|
||||
test_lib_sources,
|
||||
src_mk.get("MOCK_LIB_SOURCES", [])
|
||||
+ src_mk.get("TEST_LIB_SOURCES", [])
|
||||
+ src_mk.get("EXP_LIB_SOURCES", [])
|
||||
+ src_mk.get("ANALYZER_LIB_SOURCES", []),
|
||||
deps=[
|
||||
":rocksdb_with_faiss_lib",
|
||||
],
|
||||
extra_test_libs=True,
|
||||
headers=test_lib_headers,
|
||||
)
|
||||
# rocksdb_tools_lib
|
||||
BUCK.add_library(
|
||||
@@ -262,12 +202,6 @@ def generate_buck(repo_path, deps_map):
|
||||
+ src_mk.get("ANALYZER_LIB_SOURCES", [])
|
||||
+ ["test_util/testutil.cc"],
|
||||
[":rocksdb_lib"],
|
||||
headers=[
|
||||
"test_util/testutil.h",
|
||||
"tools/block_cache_analyzer/block_cache_trace_analyzer.h",
|
||||
"tools/simulated_hybrid_file_system.h",
|
||||
"tools/trace_analyzer_tool.h",
|
||||
],
|
||||
)
|
||||
# rocksdb_cache_bench_tools_lib
|
||||
BUCK.add_library(
|
||||
@@ -281,19 +215,12 @@ def generate_buck(repo_path, deps_map):
|
||||
src_mk.get("POINT_LOCK_BENCH_LIB_SOURCES", []),
|
||||
[":rocksdb_lib"],
|
||||
)
|
||||
stress_sources = (
|
||||
src_mk.get("ANALYZER_LIB_SOURCES", [])
|
||||
+ src_mk.get("STRESS_LIB_SOURCES", [])
|
||||
+ ["test_util/testutil.cc"]
|
||||
)
|
||||
# rocksdb_stress_lib
|
||||
BUCK.add_rocksdb_library(
|
||||
"rocksdb_stress_lib",
|
||||
stress_sources,
|
||||
headers=[
|
||||
header for header in _STRESS_LIB_HEADERS
|
||||
if header[:-2] + ".cc" in stress_sources
|
||||
],
|
||||
src_mk.get("ANALYZER_LIB_SOURCES", [])
|
||||
+ src_mk.get("STRESS_LIB_SOURCES", [])
|
||||
+ ["test_util/testutil.cc"],
|
||||
)
|
||||
# ldb binary
|
||||
BUCK.add_binary(
|
||||
@@ -416,7 +343,6 @@ def generate_buck(repo_path, deps_map):
|
||||
test_src,
|
||||
deps=json.dumps(deps["extra_deps"] + [":" + test_library]),
|
||||
extra_compiler_flags=json.dumps(deps["extra_compiler_flags"]),
|
||||
source_headers=_TEST_HEADERS.get(test, []),
|
||||
)
|
||||
else:
|
||||
if with_faiss:
|
||||
@@ -425,7 +351,6 @@ def generate_buck(repo_path, deps_map):
|
||||
test_src,
|
||||
deps=json.dumps(deps["extra_deps"] + [":rocksdb_with_faiss_test_lib"]),
|
||||
extra_compiler_flags=json.dumps(deps["extra_compiler_flags"]),
|
||||
source_headers=_TEST_HEADERS.get(test, []),
|
||||
)
|
||||
else:
|
||||
BUCK.register_test(
|
||||
@@ -433,10 +358,8 @@ def generate_buck(repo_path, deps_map):
|
||||
test_src,
|
||||
deps=json.dumps(deps["extra_deps"] + [":rocksdb_test_lib"]),
|
||||
extra_compiler_flags=json.dumps(deps["extra_compiler_flags"]),
|
||||
source_headers=_TEST_HEADERS.get(test, []),
|
||||
)
|
||||
BUCK.export_file("tools/db_crashtest.py")
|
||||
BUCK.export_file("tools/fault_injection_log_parser.py")
|
||||
|
||||
print(ColorString.info("Generated BUCK Summary:"))
|
||||
print(ColorString.info("- %d libs" % BUCK.total_lib))
|
||||
|
||||
@@ -118,12 +118,6 @@ class TARGETSBuilder:
|
||||
self.total_bin = self.total_bin + 1
|
||||
|
||||
def add_c_test(self):
|
||||
# The actual c_test_bin target is defined by add_c_test_wrapper in the
|
||||
# internal //rocks/buckifier:defs.bzl (not in this OSS repo). db/c_test.c
|
||||
# #includes the generated c_api_gen/*.inc fragments, so under Buck's
|
||||
# hermetic sandbox that wrapper must expose them as headers, e.g.
|
||||
# headers = native.glob(["c_api_gen/**/*.inc"])
|
||||
# (Make/CMake resolve the include via -I. / PROJECT_SOURCE_DIR.)
|
||||
with open(self.path, "ab") as targets_file:
|
||||
targets_file.write(
|
||||
b"""
|
||||
@@ -162,17 +156,12 @@ add_c_test_wrapper()
|
||||
).encode("utf-8")
|
||||
)
|
||||
|
||||
def register_test(self, test_name, src, deps, extra_compiler_flags, source_headers):
|
||||
def register_test(self, test_name, src, deps, extra_compiler_flags):
|
||||
with open(self.path, "ab") as targets_file:
|
||||
targets_file.write(
|
||||
targets_cfg.unittests_template.format(
|
||||
test_name=test_name,
|
||||
test_cc=str(src),
|
||||
source_headers=(
|
||||
f" source_headers=[{pretty_list(source_headers, 16)}],\n"
|
||||
if source_headers
|
||||
else ""
|
||||
),
|
||||
deps=deps,
|
||||
extra_compiler_flags=extra_compiler_flags,
|
||||
).encode("utf-8")
|
||||
|
||||
@@ -30,7 +30,7 @@ cpp_binary_wrapper(name="{name}", srcs=[{srcs}], deps=[{deps}], extra_preprocess
|
||||
unittests_template = """
|
||||
cpp_unittest_wrapper(name="{test_name}",
|
||||
srcs=["{test_cc}"],
|
||||
{source_headers} deps={deps},
|
||||
deps={deps},
|
||||
extra_compiler_flags={extra_compiler_flags})
|
||||
|
||||
"""
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
# -DLZ4 if the LZ4 library is present
|
||||
# -DZSTD if the ZSTD library is present
|
||||
# -DNUMA if the NUMA library is present
|
||||
# -DTBB if the TBB library is present
|
||||
# -DMEMKIND if the memkind library is present
|
||||
#
|
||||
# Using gflags in rocksdb:
|
||||
@@ -89,36 +90,13 @@ if test -z "$CC"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# CLANG_CXX is the single clang++ detection point for the whole script: it is
|
||||
# used for CXX when building with clang, for CLANG_ANALYZER (scan-build), and by
|
||||
# tooling that needs clang even in a gcc build (e.g. the C API codegen, which
|
||||
# parses C++ ASTs). The fbcode config above already sets CLANG_CXX; otherwise
|
||||
# resolve it here.
|
||||
if test -z "$CLANG_CXX"; then
|
||||
if [ -n "$CXX" ] && echo | $CXX -dM -E -x c++ - 2>/dev/null | grep -q '\b__clang__\b'; then
|
||||
# Honor an already-configured clang compiler (e.g. CI sets
|
||||
# CXX=clang++-21) so codegen parses headers with the same clang the
|
||||
# build uses, not an unrelated clang++ that merely happens to come first
|
||||
# on PATH (an image may ship both a bare clang++ and clang++-NN).
|
||||
CLANG_CXX="$CXX"
|
||||
else
|
||||
# Otherwise take the first clang++ on PATH. Candidates cover a bare
|
||||
# clang++, versioned names, and clang++.par (a Meta-internal wrapper
|
||||
# often present on dev machines).
|
||||
CLANG_CXX=$(command -v clang++ || command -v clang++-21 || command -v clang++-20 \
|
||||
|| command -v clang++-19 || command -v clang++-18 || command -v clang++-17 \
|
||||
|| command -v clang++-16 || command -v clang++-15 || command -v clang++-14 \
|
||||
|| command -v clang++-13 || command -v clang++.par || true)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$CXX"; then
|
||||
if [ "$USE_CLANG" ] && [ -n "$CLANG_CXX" ]; then
|
||||
CXX="$CLANG_CXX"
|
||||
if [ "$USE_CLANG" -a -x "$(command -v clang++)" ]; then
|
||||
CXX=clang++
|
||||
elif [ -x "$(command -v g++)" ]; then
|
||||
CXX=g++
|
||||
elif [ -n "$CLANG_CXX" ]; then
|
||||
CXX="$CLANG_CXX"
|
||||
elif [ -x "$(command -v clang++)" ]; then
|
||||
CXX=clang++
|
||||
else
|
||||
CXX=g++
|
||||
fi
|
||||
@@ -136,17 +114,6 @@ if test -z "$AR"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# If the selected C++ compiler is actually clang (e.g. clang was the only
|
||||
# compiler available), reflect that as USE_CLANG so clang-specific logic in the
|
||||
# Makefile applies consistently. Detect it via the compiler's own __clang__
|
||||
# predefined macro rather than matching the binary path, which can false-positive
|
||||
# (e.g. a home directory containing "clang").
|
||||
if test -z "$USE_CLANG"; then
|
||||
if echo | $CXX -dM -E -x c++ - 2>/dev/null | grep -q '\b__clang__\b'; then
|
||||
USE_CLANG=1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Detect OS
|
||||
if test -z "$TARGET_OS"; then
|
||||
TARGET_OS=`uname -s`
|
||||
@@ -161,7 +128,7 @@ if test -z "$CLANG_SCAN_BUILD"; then
|
||||
fi
|
||||
|
||||
if test -z "$CLANG_ANALYZER"; then
|
||||
CLANG_ANALYZER="$CLANG_CXX"
|
||||
CLANG_ANALYZER=$(command -v clang++ 2> /dev/null)
|
||||
fi
|
||||
|
||||
if test -z "$FIND"; then
|
||||
@@ -181,24 +148,6 @@ PLATFORM_SHARED_LDFLAGS="-Wl,--no-as-needed -shared -Wl,-soname -Wl,"
|
||||
PLATFORM_SHARED_CFLAGS="-fPIC"
|
||||
PLATFORM_SHARED_VERSIONED=true
|
||||
|
||||
# Prefer lld linker when available on Linux. lld is typically 5-10x faster
|
||||
# than the default ld.bfd for large C++ projects. macOS uses ld64 (or
|
||||
# ld-prime) which is already fast, so we skip lld detection there.
|
||||
# Set ROCKSDB_NO_FAST_LINKER=1 to disable this auto-detection.
|
||||
if [ -z "$ROCKSDB_NO_FAST_LINKER" ] && [ "$TARGET_OS" = "Linux" ]; then
|
||||
if $CXX -fuse-ld=lld -L/usr/local/lib -x c++ - -o /dev/null 2>/dev/null <<EOF
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
then
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -fuse-ld=lld"
|
||||
# Ensure lld can find libraries in /usr/local/lib (lld does not
|
||||
# search there by default, unlike ld.bfd)
|
||||
if [ -d /usr/local/lib ]; then
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -L/usr/local/lib"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# generic port files (working on all platform by #ifdef) go directly in /port
|
||||
GENERIC_PORT_FILES=`cd "$ROCKSDB_ROOT"; find port -name '*.cc' | tr "\n" " "`
|
||||
|
||||
@@ -457,6 +406,19 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! test $ROCKSDB_DISABLE_TBB; then
|
||||
# Test whether tbb is available
|
||||
$CXX $PLATFORM_CXXFLAGS $LDFLAGS -x c++ - -o test.o -ltbb 2>/dev/null <<EOF
|
||||
#include <tbb/tbb.h>
|
||||
int main() {}
|
||||
EOF
|
||||
if [ "$?" = 0 ]; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -DTBB"
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -ltbb"
|
||||
JAVA_LDFLAGS="$JAVA_LDFLAGS -ltbb"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! test $ROCKSDB_DISABLE_JEMALLOC; then
|
||||
# Test whether jemalloc is available
|
||||
if echo 'int main() {}' | $CXX $PLATFORM_CXXFLAGS $LDFLAGS -x c++ - -o test.o -ljemalloc \
|
||||
@@ -852,10 +814,6 @@ echo "ROCKSDB_MINOR=$ROCKSDB_MINOR" >> "$OUTPUT"
|
||||
echo "ROCKSDB_PATCH=$ROCKSDB_PATCH" >> "$OUTPUT"
|
||||
echo "CLANG_SCAN_BUILD=$CLANG_SCAN_BUILD" >> "$OUTPUT"
|
||||
echo "CLANG_ANALYZER=$CLANG_ANALYZER" >> "$OUTPUT"
|
||||
echo "CLANG_CXX=$CLANG_CXX" >> "$OUTPUT"
|
||||
if test -n "$USE_CLANG"; then
|
||||
echo "USE_CLANG=$USE_CLANG" >> "$OUTPUT"
|
||||
fi
|
||||
echo "PROFILING_FLAGS=$PROFILING_FLAGS" >> "$OUTPUT"
|
||||
echo "FIND=$FIND" >> "$OUTPUT"
|
||||
echo "WATCH=$WATCH" >> "$OUTPUT"
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# This source code is licensed under both the GPLv2 (found in the
|
||||
# COPYING file in the root directory) and Apache 2.0 License
|
||||
# (found in the LICENSE.Apache file in the root directory).
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
|
||||
#
|
||||
# Check for some simple mistakes in public headers (on the command line)
|
||||
# that should prevent commit or push
|
||||
|
||||
@@ -37,7 +37,7 @@ if [ "$?" != "1" ]; then
|
||||
BAD=1
|
||||
fi
|
||||
|
||||
LC_ALL=C git grep -n $'[\x80-\xff]' -- ':!docs' ':!*.md' ':!.github'
|
||||
git grep -n -P "[\x80-\xFF]" -- ':!docs' ':!*.md'
|
||||
if [ "$?" != "1" ]; then
|
||||
echo '^^^^ Use only ASCII characters in source files'
|
||||
BAD=1
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Validate GitHub Actions workflow YAML before it reaches CI runtime.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if ! command -v ruby >/dev/null 2>&1; then
|
||||
echo "ruby is required to validate GitHub Actions workflow YAML"
|
||||
echo "On CentOS Stream: sudo dnf install ruby rubygems rubygem-psych"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! ruby -e 'require "psych"' 2>/dev/null; then
|
||||
echo "ruby is installed but cannot load required library 'psych'"
|
||||
echo "On CentOS Stream: sudo dnf install rubygems rubygem-psych"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ruby <<'RUBY'
|
||||
require "psych"
|
||||
|
||||
bad = false
|
||||
workflow_files = Dir[".github/workflows/*.{yml,yaml}"].sort
|
||||
|
||||
if workflow_files.empty?
|
||||
warn "No workflow YAML files found under .github/workflows"
|
||||
exit 1
|
||||
end
|
||||
|
||||
workflow_files.each do |path|
|
||||
begin
|
||||
Psych.parse_file(path)
|
||||
puts "OK #{path}"
|
||||
rescue Psych::Exception => e
|
||||
warn "Invalid YAML in #{path}: #{e.message}"
|
||||
bad = true
|
||||
end
|
||||
end
|
||||
|
||||
exit(bad ? 1 : 0)
|
||||
RUBY
|
||||
@@ -1,20 +1,21 @@
|
||||
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||
# The file is generated using update_dependencies.sh.
|
||||
GCC_BASE=/mnt/gvfs/third-party2/gcc/e9cb2d4550b5a95024125084420342d256b349cd/11.x/centos9-native/3bed279
|
||||
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/4e46e6967e15412702e51960c69790a78933856f/21/platform010/72a2ff8
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/63c5179edc90fec473e53c1b2f92269c65c39e07/11.x/platform010/5684a5a
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/b4a6248a76a163bcccb1e4751e247712c535846e/2.34/platform010/f259413
|
||||
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/ef895164499fdfedb9d9b9c85520de10aa8ff9ca/1.1.8/platform010/76ebdda
|
||||
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/643dbf0136f869562485cfcb2953f5cab60447ef/1.2.8/platform010/76ebdda
|
||||
GCC_BASE=/mnt/gvfs/third-party2/gcc/62de5a92e5f23c661c3d4b9f322e04eb14e7a5bd/11.x/centos8-native/886b5eb
|
||||
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/1f6edd1ff15c99c861afc8f3cd69054cd974dd64/15/platform010/72a2ff8
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/d1129753c8361ac8e9453c0f4291337a4507ebe6/11.x/platform010/5684a5a
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/fed6e93d87571fb162734c86636119d45a398963/2.34/platform010/f259413
|
||||
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/31a346126a1f3b64812c362511cb04cc1bd40855/1.1.8/platform010/76ebdda
|
||||
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/0c65c05468b5a38cef1a106a1f526463e120c8dd/1.2.8/platform010/76ebdda
|
||||
BZIP2_BASE=/mnt/gvfs/third-party2/bzip2/09703139cfc376bd8a82642385a0e97726b28287/1.0.6/platform010/76ebdda
|
||||
LZ4_BASE=/mnt/gvfs/third-party2/lz4/823bf8e000654abef784311296ffc8166d9d3986/1.9.4/platform010/76ebdda
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/0cda78647b5712bec7ec6d9ba2f0dcdabfb6f44f/1.4.x/platform010/64091f4
|
||||
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/a02e0de00945729ad553c187c64e86b57f45a33b/2.2.0/platform010/76ebdda
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/a1a50742bec7195bfafb594e174ea45dc197a420/master/platform010/779a252
|
||||
LZ4_BASE=/mnt/gvfs/third-party2/lz4/ff23d17b932725cc1734a14896a8b67c518ba169/1.9.4/platform010/76ebdda
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/576397d8b1d9cea7306ad1e454d5e55caaa2ff1c/1.4.x/platform010/64091f4
|
||||
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/fecac07861cb829f5e60dbeff0503d3272db73c0/2.2.0/platform010/76ebdda
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/0bb3f5756788ce26e2e16a1cb2f2af2c59b51abe/master/platform010/f57cc4a
|
||||
NUMA_BASE=/mnt/gvfs/third-party2/numa/5b602edd46fda54cdd7ea45f77dbe4061206e174/2.0.11/platform010/76ebdda
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/f3cce2e1a79ac8d64e102886603a6997d6e88640/1.8/platform010/76ebdda
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/97cac22a149c2e202917e05d44e87e516b68216f/1.4/platform010/5074a48
|
||||
TBB_BASE=/mnt/gvfs/third-party2/tbb/53953ebc4e3eda85ad6fc3e429ba146035e97b90/2018_U5/platform010/76ebdda
|
||||
LIBURING_BASE=/mnt/gvfs/third-party2/liburing/a98e2d137007e3ebf7f33bd6f99c2c56bdaf8488/20210212/platform010/76ebdda
|
||||
BENCHMARK_BASE=/mnt/gvfs/third-party2/benchmark/780c7a0f9cf0967961e69ad08e61cddd85d61821/trunk/platform010/76ebdda
|
||||
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/0883cccda758e68b47e4c04e4fa01142e1f60f32/fb/platform010/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/1d5d19135a406a941d3a441eb2bf506bb9d19210/2.43/centos9-native/be7139e
|
||||
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/3e2b7ccc315c9a0f2b678ce6fd774f4970f9bf3b/3.22.0/platform010/76ebdda
|
||||
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/624a2f8f6c93c3c1df8aa4a6255d8202631a6c80/fb/platform010/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/39579e8603b48b3540f8b0633f43adf29acccb8b/2.37/centos8-native/da39a3e
|
||||
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/cd9cc656d49ecb53797ce4d055e49fde29fd57ff/3.19.0/platform010/76ebdda
|
||||
@@ -87,6 +87,15 @@ if test -z $PIC_BUILD; then
|
||||
LIBUNWIND="$LIBUNWIND_BASE/lib/libunwind.a"
|
||||
fi
|
||||
|
||||
# location of TBB
|
||||
TBB_INCLUDE=" -isystem $TBB_BASE/include/"
|
||||
if test -z $PIC_BUILD; then
|
||||
TBB_LIBS="$TBB_BASE/lib/libtbb.a"
|
||||
else
|
||||
TBB_LIBS="$TBB_BASE/lib/libtbb_pic.a"
|
||||
fi
|
||||
CFLAGS+=" -DTBB"
|
||||
|
||||
test "$USE_SSE" || USE_SSE=1
|
||||
export USE_SSE
|
||||
test "$PORTABLE" || PORTABLE=1
|
||||
@@ -95,7 +104,7 @@ export PORTABLE
|
||||
BINUTILS="$BINUTILS_BASE/bin"
|
||||
AR="$BINUTILS/ar"
|
||||
|
||||
DEPS_INCLUDE="$SNAPPY_INCLUDE $ZLIB_INCLUDE $BZIP_INCLUDE $LZ4_INCLUDE $ZSTD_INCLUDE $GFLAGS_INCLUDE $NUMA_INCLUDE"
|
||||
DEPS_INCLUDE="$SNAPPY_INCLUDE $ZLIB_INCLUDE $BZIP_INCLUDE $LZ4_INCLUDE $ZSTD_INCLUDE $GFLAGS_INCLUDE $NUMA_INCLUDE $TBB_INCLUDE"
|
||||
|
||||
STDLIBS="-L $GCC_BASE/lib64"
|
||||
|
||||
@@ -141,17 +150,17 @@ CFLAGS+=" $DEPS_INCLUDE"
|
||||
CFLAGS+=" -DROCKSDB_PLATFORM_POSIX -DROCKSDB_LIB_IO_POSIX -DROCKSDB_FALLOCATE_PRESENT -DROCKSDB_MALLOC_USABLE_SIZE -DROCKSDB_RANGESYNC_PRESENT -DROCKSDB_SCHED_GETCPU_PRESENT"
|
||||
CXXFLAGS+=" $CFLAGS"
|
||||
|
||||
EXEC_LDFLAGS=" $SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $NUMA_LIB"
|
||||
EXEC_LDFLAGS=" $SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $NUMA_LIB $TBB_LIBS"
|
||||
EXEC_LDFLAGS+=" -B$BINUTILS/gold"
|
||||
EXEC_LDFLAGS+=" -Wl,--dynamic-linker,/usr/local/fbcode/gcc-5-glibc-2.23/lib/ld.so"
|
||||
EXEC_LDFLAGS+=" $LIBUNWIND"
|
||||
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/gcc-5-glibc-2.23/lib"
|
||||
# dynamic loading
|
||||
# required by libtbb
|
||||
EXEC_LDFLAGS+=" -ldl"
|
||||
|
||||
PLATFORM_LDFLAGS="$LIBGCC_LIBS $GLIBC_LIBS $STDLIBS -lgcc -lstdc++"
|
||||
|
||||
EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS"
|
||||
EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $TBB_LIBS"
|
||||
|
||||
VALGRIND_VER="$VALGRIND_BASE/bin/"
|
||||
|
||||
|
||||
@@ -82,6 +82,11 @@ CFLAGS+=" -DNUMA"
|
||||
# location of libunwind
|
||||
LIBUNWIND="$LIBUNWIND_BASE/lib/libunwind${MAYBE_PIC}.a"
|
||||
|
||||
# location of TBB
|
||||
TBB_INCLUDE=" -isystem $TBB_BASE/include/"
|
||||
TBB_LIBS="$TBB_BASE/lib/libtbb${MAYBE_PIC}.a"
|
||||
CFLAGS+=" -DTBB"
|
||||
|
||||
# location of LIBURING
|
||||
LIBURING_INCLUDE=" -isystem $LIBURING_BASE/include/"
|
||||
LIBURING_LIBS="$LIBURING_BASE/lib/liburing${MAYBE_PIC}.a"
|
||||
@@ -96,7 +101,7 @@ BINUTILS="$BINUTILS_BASE/bin"
|
||||
AR="$BINUTILS/ar"
|
||||
AS="$BINUTILS/as"
|
||||
|
||||
DEPS_INCLUDE="$SNAPPY_INCLUDE $ZLIB_INCLUDE $BZIP_INCLUDE $LZ4_INCLUDE $ZSTD_INCLUDE $GFLAGS_INCLUDE $NUMA_INCLUDE $LIBURING_INCLUDE $BENCHMARK_INCLUDE"
|
||||
DEPS_INCLUDE="$SNAPPY_INCLUDE $ZLIB_INCLUDE $BZIP_INCLUDE $LZ4_INCLUDE $ZSTD_INCLUDE $GFLAGS_INCLUDE $NUMA_INCLUDE $TBB_INCLUDE $LIBURING_INCLUDE $BENCHMARK_INCLUDE"
|
||||
|
||||
STDLIBS="-L $GCC_BASE/lib64"
|
||||
|
||||
@@ -104,10 +109,6 @@ CLANG_BIN="$CLANG_BASE/bin"
|
||||
CLANG_LIB="$CLANG_BASE/lib"
|
||||
CLANG_SRC="$CLANG_BASE/../../src"
|
||||
|
||||
# A clang++ is always available in the fbcode toolchain regardless of whether
|
||||
# the build itself uses gcc or clang. CLANG_CXX exposes it for tooling (e.g. the
|
||||
# C API codegen, which parses C++ ASTs) that needs clang even in a gcc build.
|
||||
CLANG_CXX="$CLANG_BIN/clang++"
|
||||
CLANG_ANALYZER="$CLANG_BIN/clang++"
|
||||
CLANG_SCAN_BUILD="$CLANG_BIN/scan-build"
|
||||
|
||||
@@ -156,19 +157,19 @@ CFLAGS+=" $DEPS_INCLUDE"
|
||||
CFLAGS+=" -DROCKSDB_PLATFORM_POSIX -DROCKSDB_LIB_IO_POSIX -DROCKSDB_FALLOCATE_PRESENT -DROCKSDB_MALLOC_USABLE_SIZE -DROCKSDB_RANGESYNC_PRESENT -DROCKSDB_SCHED_GETCPU_PRESENT -DROCKSDB_IOURING_PRESENT"
|
||||
CXXFLAGS+=" $CFLAGS"
|
||||
|
||||
EXEC_LDFLAGS=" $SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $NUMA_LIB $LIBURING_LIBS $BENCHMARK_LIBS"
|
||||
EXEC_LDFLAGS=" $SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $NUMA_LIB $TBB_LIBS $LIBURING_LIBS $BENCHMARK_LIBS"
|
||||
EXEC_LDFLAGS+=" -Wl,--dynamic-linker,/usr/local/fbcode/platform010/lib/ld.so"
|
||||
EXEC_LDFLAGS+=" $LIBUNWIND"
|
||||
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/platform010/lib"
|
||||
EXEC_LDFLAGS+=" -Wl,-rpath=$GCC_BASE/lib64"
|
||||
# dynamic loading
|
||||
# required by libtbb
|
||||
EXEC_LDFLAGS+=" -ldl"
|
||||
|
||||
PLATFORM_LDFLAGS="$LIBGCC_LIBS $GLIBC_LIBS $STDLIBS -lgcc -lstdc++"
|
||||
PLATFORM_LDFLAGS+=" -B$BINUTILS"
|
||||
|
||||
EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $LIBURING_LIBS $BENCHMARK_LIBS"
|
||||
EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $TBB_LIBS $LIBURING_LIBS $BENCHMARK_LIBS"
|
||||
|
||||
VALGRIND_VER="$VALGRIND_BASE/bin/"
|
||||
|
||||
export CC CXX AR AS CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_CXX CLANG_ANALYZER CLANG_SCAN_BUILD
|
||||
export CC CXX AR AS CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_ANALYZER CLANG_SCAN_BUILD
|
||||
@@ -1,188 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# This source code is licensed under both the GPLv2 (found in the COPYING file in the root directory)
|
||||
# and the Apache 2.0 License (found in the LICENSE.Apache file in the root directory).
|
||||
"""
|
||||
Pre-download packages with unreliable mirrors using fallback mirrors.
|
||||
Reads package info from folly's getdeps manifest files.
|
||||
"""
|
||||
import configparser
|
||||
import hashlib
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
DOWNLOAD_TIMEOUT_SECONDS = 120
|
||||
DOWNLOAD_CHUNK_BYTES = 64 * 1024
|
||||
MAX_DOWNLOAD_BYTES = 50 * 1024 * 1024
|
||||
|
||||
MIRROR_FALLBACKS = {
|
||||
"ftpmirror.gnu.org/gnu/": [
|
||||
"https://mirrors.kernel.org/gnu/",
|
||||
"https://ftpmirror.gnu.org/gnu/",
|
||||
"https://ftp.gnu.org/gnu/",
|
||||
],
|
||||
"ftp.gnu.org/gnu/": [
|
||||
"https://mirrors.kernel.org/gnu/",
|
||||
"https://ftpmirror.gnu.org/gnu/",
|
||||
"https://ftp.gnu.org/gnu/",
|
||||
],
|
||||
}
|
||||
|
||||
# These packages must have URLs matching MIRROR_FALLBACKS; other packages are
|
||||
# left for getdeps.py's normal download path.
|
||||
PACKAGES_TO_CHECK = ("autoconf", "automake", "libtool", "libiberty")
|
||||
|
||||
import os
|
||||
import hashlib
|
||||
import subprocess
|
||||
import configparser
|
||||
|
||||
def sha256_file(path):
|
||||
"""Calculate SHA256 hash of a file."""
|
||||
h = hashlib.sha256()
|
||||
try:
|
||||
with open(path, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(65536), b""):
|
||||
with open(path, 'rb') as f:
|
||||
for chunk in iter(lambda: f.read(65536), b''):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def parse_manifest(manifest_path):
|
||||
"""Parse a getdeps manifest file to extract download info."""
|
||||
# folly manifests can contain bare keys in sections unrelated to downloads.
|
||||
config = configparser.ConfigParser(allow_no_value=True, interpolation=None)
|
||||
config = configparser.ConfigParser()
|
||||
try:
|
||||
with open(manifest_path, encoding="utf-8") as manifest_file:
|
||||
config.read_file(manifest_file)
|
||||
except Exception as ex:
|
||||
print(f" {os.path.basename(manifest_path)}: WARNING - parse failed: {ex}")
|
||||
return None
|
||||
|
||||
if "download" in config:
|
||||
return {
|
||||
"url": config["download"].get("url", ""),
|
||||
"sha256": config["download"].get("sha256", ""),
|
||||
}
|
||||
return None
|
||||
|
||||
|
||||
def file_size(path):
|
||||
try:
|
||||
return os.path.getsize(path)
|
||||
config.read(manifest_path)
|
||||
if 'download' in config:
|
||||
return {
|
||||
'url': config['download'].get('url', ''),
|
||||
'sha256': config['download'].get('sha256', ''),
|
||||
}
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
pass
|
||||
return None
|
||||
|
||||
def get_fallback_mirrors(url):
|
||||
"""Get fallback mirror URLs for a given URL."""
|
||||
for pattern, mirrors in MIRROR_FALLBACKS.items():
|
||||
# Fallback mirror patterns for known unreliable hosts
|
||||
mirror_fallbacks = {
|
||||
"ftp.gnu.org/gnu/": [
|
||||
"https://mirrors.kernel.org/gnu/",
|
||||
"https://ftpmirror.gnu.org/gnu/",
|
||||
"https://ftp.gnu.org/gnu/",
|
||||
],
|
||||
"ftpmirror.gnu.org/gnu/": [
|
||||
"https://mirrors.kernel.org/gnu/",
|
||||
"https://ftpmirror.gnu.org/gnu/",
|
||||
"https://ftp.gnu.org/gnu/",
|
||||
],
|
||||
}
|
||||
|
||||
for pattern, mirrors in mirror_fallbacks.items():
|
||||
if pattern in url:
|
||||
# Extract the path after the pattern
|
||||
path_start = url.find(pattern) + len(pattern)
|
||||
path = url[path_start:]
|
||||
return [mirror + path for mirror in mirrors]
|
||||
return []
|
||||
|
||||
|
||||
def download_url(url, filepath):
|
||||
"""Download URL to filepath without leaving partial files behind."""
|
||||
tmp_filepath = filepath + ".tmp"
|
||||
if os.path.exists(tmp_filepath):
|
||||
os.remove(tmp_filepath)
|
||||
|
||||
request = urllib.request.Request(
|
||||
url, headers={"User-Agent": "rocksdb-getdeps-fallback/1.0"}
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(
|
||||
request, timeout=DOWNLOAD_TIMEOUT_SECONDS
|
||||
) as response, open(tmp_filepath, "wb") as output:
|
||||
copied = 0
|
||||
while True:
|
||||
chunk = response.read(DOWNLOAD_CHUNK_BYTES)
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
copied += len(chunk)
|
||||
if copied > MAX_DOWNLOAD_BYTES:
|
||||
raise Exception(
|
||||
f"download exceeds {MAX_DOWNLOAD_BYTES} bytes"
|
||||
)
|
||||
output.write(chunk)
|
||||
os.replace(tmp_filepath, filepath)
|
||||
finally:
|
||||
if os.path.exists(tmp_filepath):
|
||||
os.remove(tmp_filepath)
|
||||
|
||||
|
||||
def prepare_download(package, info, download_dir, cache_dir):
|
||||
url = info["url"]
|
||||
expected_sha256 = info["sha256"]
|
||||
mirrors = get_fallback_mirrors(url)
|
||||
if not mirrors:
|
||||
return False
|
||||
|
||||
if not expected_sha256:
|
||||
print(f" {package}: WARNING - skipped fallback without sha256")
|
||||
return False
|
||||
|
||||
# getdeps uses format: {package}-{filename}
|
||||
filename = f"{package}-{os.path.basename(url)}"
|
||||
filepath = os.path.join(download_dir, filename)
|
||||
cache_path = os.path.join(cache_dir, filename)
|
||||
|
||||
# Check if already valid.
|
||||
actual_sha256 = sha256_file(filepath) if os.path.exists(filepath) else None
|
||||
if actual_sha256 == expected_sha256:
|
||||
print(f" {filename}: OK (already downloaded)")
|
||||
return True
|
||||
if actual_sha256 is not None:
|
||||
print(
|
||||
f" {filename}: WARNING - removing invalid download "
|
||||
f"sha256={actual_sha256}"
|
||||
)
|
||||
os.remove(filepath)
|
||||
|
||||
# The cache is only an opportunistic single-build accelerator; callers
|
||||
# should not share it across concurrent builds without external locking.
|
||||
actual_sha256 = sha256_file(cache_path) if os.path.exists(cache_path) else None
|
||||
if actual_sha256 == expected_sha256:
|
||||
print(f" {filename}: OK (from cache)")
|
||||
shutil.copy2(cache_path, filepath)
|
||||
return True
|
||||
if actual_sha256 is not None:
|
||||
print(
|
||||
f" {filename}: WARNING - removing invalid cache "
|
||||
f"sha256={actual_sha256}"
|
||||
)
|
||||
os.remove(cache_path)
|
||||
|
||||
# Try fallback mirrors.
|
||||
for mirror_url in mirrors:
|
||||
print(f" {filename}: trying {mirror_url}...")
|
||||
try:
|
||||
download_url(mirror_url, filepath)
|
||||
except Exception as ex:
|
||||
print(f" {filename}: WARNING - download failed: {ex}")
|
||||
continue
|
||||
|
||||
actual_sha256 = sha256_file(filepath)
|
||||
if actual_sha256 == expected_sha256:
|
||||
size = file_size(filepath)
|
||||
print(f" {filename}: OK (downloaded, {size} bytes)")
|
||||
shutil.copy2(filepath, cache_path)
|
||||
return True
|
||||
|
||||
size = file_size(filepath)
|
||||
print(
|
||||
f" {filename}: WARNING - sha256 mismatch from {mirror_url}: "
|
||||
f"expected={expected_sha256} actual={actual_sha256} size={size}"
|
||||
)
|
||||
os.remove(filepath)
|
||||
|
||||
print(f" {filename}: WARNING - all mirrors failed")
|
||||
return False
|
||||
|
||||
return [url] # No fallback, use original
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 4:
|
||||
@@ -190,39 +64,60 @@ def main():
|
||||
sys.exit(1)
|
||||
|
||||
download_dir, cache_dir, manifests_dir = sys.argv[1], sys.argv[2], sys.argv[3]
|
||||
os.makedirs(download_dir, exist_ok=True)
|
||||
os.makedirs(cache_dir, exist_ok=True)
|
||||
|
||||
checked = 0
|
||||
ready = 0
|
||||
for package in PACKAGES_TO_CHECK:
|
||||
# Packages known to have unreliable mirrors
|
||||
packages_to_check = ["autoconf", "automake", "libtool"]
|
||||
|
||||
for package in packages_to_check:
|
||||
manifest_path = os.path.join(manifests_dir, package)
|
||||
if not os.path.isfile(manifest_path):
|
||||
if not os.path.exists(manifest_path):
|
||||
continue
|
||||
|
||||
info = parse_manifest(manifest_path)
|
||||
if not info or not info["url"]:
|
||||
if not info or not info['url'] or not info['sha256']:
|
||||
continue
|
||||
|
||||
if not info["sha256"]:
|
||||
print(f" {package}: WARNING - skipped fallback without sha256")
|
||||
# Determine filename from URL
|
||||
url = info['url']
|
||||
expected_sha256 = info['sha256']
|
||||
url_filename = os.path.basename(url)
|
||||
|
||||
# getdeps uses format: {package}-{filename}
|
||||
filename = f"{package}-{url_filename}"
|
||||
filepath = os.path.join(download_dir, filename)
|
||||
cache_path = os.path.join(cache_dir, filename)
|
||||
|
||||
# Check if already valid
|
||||
if os.path.exists(filepath) and sha256_file(filepath) == expected_sha256:
|
||||
print(f" {filename}: OK (already downloaded)")
|
||||
continue
|
||||
|
||||
if not get_fallback_mirrors(info["url"]):
|
||||
print(
|
||||
f" {package}: WARNING - skipped fallback without known mirror "
|
||||
f"for {info['url']}"
|
||||
)
|
||||
# Check cache
|
||||
if os.path.exists(cache_path) and sha256_file(cache_path) == expected_sha256:
|
||||
print(f" {filename}: OK (from cache)")
|
||||
subprocess.run(['cp', cache_path, filepath], check=True)
|
||||
continue
|
||||
|
||||
checked += 1
|
||||
try:
|
||||
if prepare_download(package, info, download_dir, cache_dir):
|
||||
ready += 1
|
||||
except Exception as ex:
|
||||
print(f" {package}: WARNING - fallback preparation failed: {ex}")
|
||||
# Try fallback mirrors
|
||||
mirrors = get_fallback_mirrors(url)
|
||||
downloaded = False
|
||||
for mirror_url in mirrors:
|
||||
print(f" {filename}: trying {mirror_url}...")
|
||||
try:
|
||||
subprocess.run(['wget', '-q', '-O', filepath, mirror_url], check=True, timeout=120)
|
||||
if sha256_file(filepath) == expected_sha256:
|
||||
print(f" {filename}: OK (downloaded)")
|
||||
subprocess.run(['cp', filepath, cache_path], check=False)
|
||||
downloaded = True
|
||||
break
|
||||
else:
|
||||
os.remove(filepath)
|
||||
except Exception:
|
||||
if os.path.exists(filepath):
|
||||
os.remove(filepath)
|
||||
|
||||
print(f" fallback mirror downloads ready: {ready}/{checked}")
|
||||
if not downloaded:
|
||||
print(f" {filename}: WARNING - all mirrors failed")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1913,7 +1913,7 @@ sub drain_job_queue {
|
||||
}
|
||||
$last_progress_time = time();
|
||||
$ps_reported = 0;
|
||||
} elsif (not $ps_reported and (time() - $last_progress_time) >= 300) {
|
||||
} elsif (not $ps_reported and (time() - $last_progress_time) >= 60) {
|
||||
# No progress in at least 60 seconds: run ps
|
||||
print $Global::original_stderr "\n";
|
||||
my $script_dir = ::dirname($0);
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright 2017 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import gtest_parallel
|
||||
import sys
|
||||
|
||||
sys.exit(gtest_parallel.main())
|
||||
@@ -1,959 +0,0 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# This source code is licensed under both the GPLv2 (found in the COPYING file in the root directory)
|
||||
# and the Apache 2.0 License (found in the LICENSE.Apache file in the root directory).
|
||||
|
||||
# Copyright 2013 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import errno
|
||||
from functools import total_ordering
|
||||
import gzip
|
||||
import io
|
||||
import json
|
||||
import multiprocessing
|
||||
import optparse
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
|
||||
if sys.version_info.major >= 3:
|
||||
long = int
|
||||
import _pickle as cPickle
|
||||
import _thread as thread
|
||||
else:
|
||||
import cPickle
|
||||
import thread
|
||||
|
||||
from pickle import HIGHEST_PROTOCOL as PICKLE_HIGHEST_PROTOCOL
|
||||
|
||||
if sys.platform == 'win32':
|
||||
import msvcrt
|
||||
else:
|
||||
import fcntl
|
||||
|
||||
|
||||
# An object that catches SIGINT sent to the Python process and notices
|
||||
# if processes passed to wait() die by SIGINT (we need to look for
|
||||
# both of those cases, because pressing Ctrl+C can result in either
|
||||
# the main process or one of the subprocesses getting the signal).
|
||||
#
|
||||
# Before a SIGINT is seen, wait(p) will simply call p.wait() and
|
||||
# return the result. Once a SIGINT has been seen (in the main process
|
||||
# or a subprocess, including the one the current call is waiting for),
|
||||
# wait(p) will call p.terminate() and raise ProcessWasInterrupted.
|
||||
class SigintHandler(object):
|
||||
class ProcessWasInterrupted(Exception):
|
||||
pass
|
||||
|
||||
sigint_returncodes = {
|
||||
-signal.SIGINT, # Unix
|
||||
-1073741510, # Windows
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.__lock = threading.Lock()
|
||||
self.__processes = set()
|
||||
self.__got_sigint = False
|
||||
signal.signal(signal.SIGINT, lambda signal_num, frame: self.interrupt())
|
||||
|
||||
def __on_sigint(self):
|
||||
self.__got_sigint = True
|
||||
while self.__processes:
|
||||
try:
|
||||
self.__processes.pop().terminate()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def interrupt(self):
|
||||
with self.__lock:
|
||||
self.__on_sigint()
|
||||
|
||||
def got_sigint(self):
|
||||
with self.__lock:
|
||||
return self.__got_sigint
|
||||
|
||||
def wait(self, p, timeout_per_test):
|
||||
with self.__lock:
|
||||
if self.__got_sigint:
|
||||
p.terminate()
|
||||
self.__processes.add(p)
|
||||
try:
|
||||
code = p.wait(timeout_per_test)
|
||||
except subprocess.TimeoutExpired :
|
||||
p.terminate()
|
||||
self.__processes.remove(p)
|
||||
code = -errno.ETIME
|
||||
with self.__lock:
|
||||
self.__processes.discard(p)
|
||||
if code in self.sigint_returncodes:
|
||||
self.__on_sigint()
|
||||
if self.__got_sigint:
|
||||
raise self.ProcessWasInterrupted
|
||||
return code
|
||||
|
||||
|
||||
sigint_handler = SigintHandler()
|
||||
|
||||
|
||||
# Return the width of the terminal, or None if it couldn't be
|
||||
# determined (e.g. because we're not being run interactively).
|
||||
def term_width(out):
|
||||
if not out.isatty():
|
||||
return None
|
||||
try:
|
||||
p = subprocess.Popen(["stty", "size"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(out, err) = p.communicate()
|
||||
if p.returncode != 0 or err:
|
||||
return None
|
||||
return int(out.split()[1])
|
||||
except (IndexError, OSError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
# Output transient and permanent lines of text. If several transient
|
||||
# lines are written in sequence, the new will overwrite the old. We
|
||||
# use this to ensure that lots of unimportant info (tests passing)
|
||||
# won't drown out important info (tests failing).
|
||||
class Outputter(object):
|
||||
def __init__(self, out_file):
|
||||
self.__out_file = out_file
|
||||
self.__previous_line_was_transient = False
|
||||
self.__width = term_width(out_file) # Line width, or None if not a tty.
|
||||
|
||||
def transient_line(self, msg):
|
||||
if self.__width is None:
|
||||
self.__out_file.write(msg + "\n")
|
||||
self.__out_file.flush()
|
||||
else:
|
||||
self.__out_file.write("\r" + msg[:self.__width].ljust(self.__width))
|
||||
self.__previous_line_was_transient = True
|
||||
|
||||
def flush_transient_output(self):
|
||||
if self.__previous_line_was_transient:
|
||||
self.__out_file.write("\n")
|
||||
self.__previous_line_was_transient = False
|
||||
|
||||
def permanent_line(self, msg):
|
||||
self.flush_transient_output()
|
||||
self.__out_file.write(msg + "\n")
|
||||
if self.__width is None:
|
||||
self.__out_file.flush()
|
||||
|
||||
|
||||
def get_save_file_path():
|
||||
"""Return path to file for saving transient data."""
|
||||
if sys.platform == 'win32':
|
||||
default_cache_path = os.path.join(os.path.expanduser('~'), 'AppData',
|
||||
'Local')
|
||||
cache_path = os.environ.get('LOCALAPPDATA', default_cache_path)
|
||||
else:
|
||||
# We don't use xdg module since it's not a standard.
|
||||
default_cache_path = os.path.join(os.path.expanduser('~'), '.cache')
|
||||
cache_path = os.environ.get('XDG_CACHE_HOME', default_cache_path)
|
||||
|
||||
if os.path.isdir(cache_path):
|
||||
return os.path.join(cache_path, 'gtest-parallel')
|
||||
else:
|
||||
sys.stderr.write('Directory {} does not exist'.format(cache_path))
|
||||
return os.path.join(os.path.expanduser('~'), '.gtest-parallel-times')
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Task(object):
|
||||
"""Stores information about a task (single execution of a test).
|
||||
|
||||
This class stores information about the test to be executed (gtest binary and
|
||||
test name), and its result (log file, exit code and runtime).
|
||||
Each task is uniquely identified by the gtest binary, the test name and an
|
||||
execution number that increases each time the test is executed.
|
||||
Additionaly we store the last execution time, so that next time the test is
|
||||
executed, the slowest tests are run first.
|
||||
"""
|
||||
|
||||
def __init__(self, test_binary, test_name, test_command, execution_number,
|
||||
last_execution_time, output_dir):
|
||||
self.test_name = test_name
|
||||
self.output_dir = output_dir
|
||||
self.test_binary = test_binary
|
||||
self.test_command = test_command
|
||||
self.execution_number = execution_number
|
||||
self.last_execution_time = last_execution_time
|
||||
|
||||
self.exit_code = None
|
||||
self.runtime_ms = None
|
||||
|
||||
self.test_id = (test_binary, test_name)
|
||||
self.task_id = (test_binary, test_name, self.execution_number)
|
||||
|
||||
self.log_file = Task._logname(self.output_dir, self.test_binary, test_name,
|
||||
self.execution_number)
|
||||
|
||||
def __sorting_key(self):
|
||||
# Unseen or failing tests (both missing execution time) take precedence over
|
||||
# execution time. Tests are greater (seen as slower) when missing times so
|
||||
# that they are executed first.
|
||||
return (1 if self.last_execution_time is None else 0,
|
||||
self.last_execution_time)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.__sorting_key() == other.__sorting_key()
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.__sorting_key() < other.__sorting_key()
|
||||
|
||||
@staticmethod
|
||||
def _normalize(string):
|
||||
return re.sub('[^A-Za-z0-9]', '_', string)
|
||||
|
||||
@staticmethod
|
||||
def _logname(output_dir, test_binary, test_name, execution_number):
|
||||
# Store logs to temporary files if there is no output_dir.
|
||||
if output_dir is None:
|
||||
(log_handle, log_name) = tempfile.mkstemp(prefix='gtest_parallel_',
|
||||
suffix=".log")
|
||||
os.close(log_handle)
|
||||
return log_name
|
||||
|
||||
log_name = '%s-%s-%d.log' % (Task._normalize(os.path.basename(test_binary)),
|
||||
Task._normalize(test_name), execution_number)
|
||||
|
||||
return os.path.join(output_dir, log_name)
|
||||
|
||||
def run(self, timeout_per_test):
|
||||
begin = time.time()
|
||||
with open(self.log_file, 'w') as log:
|
||||
task = subprocess.Popen(self.test_command, stdout=log, stderr=log)
|
||||
try:
|
||||
self.exit_code = sigint_handler.wait(task, timeout_per_test)
|
||||
except sigint_handler.ProcessWasInterrupted:
|
||||
thread.exit()
|
||||
self.runtime_ms = int(1000 * (time.time() - begin))
|
||||
self.last_execution_time = None if self.exit_code else self.runtime_ms
|
||||
|
||||
|
||||
class TaskManager(object):
|
||||
"""Executes the tasks and stores the passed, failed and interrupted tasks.
|
||||
|
||||
When a task is run, this class keeps track if it passed, failed or was
|
||||
interrupted. After a task finishes it calls the relevant functions of the
|
||||
Logger, TestResults and TestTimes classes, and in case of failure, retries the
|
||||
test as specified by the --retry_failed flag.
|
||||
"""
|
||||
|
||||
def __init__(self, times, logger, test_results, task_factory, times_to_retry,
|
||||
initial_execution_number):
|
||||
self.times = times
|
||||
self.logger = logger
|
||||
self.test_results = test_results
|
||||
self.task_factory = task_factory
|
||||
self.times_to_retry = times_to_retry
|
||||
self.initial_execution_number = initial_execution_number
|
||||
|
||||
self.global_exit_code = 0
|
||||
|
||||
self.passed = []
|
||||
self.failed = []
|
||||
self.started = {}
|
||||
self.timed_out = []
|
||||
self.execution_number = {}
|
||||
|
||||
self.lock = threading.Lock()
|
||||
|
||||
def __get_next_execution_number(self, test_id):
|
||||
with self.lock:
|
||||
next_execution_number = self.execution_number.setdefault(
|
||||
test_id, self.initial_execution_number)
|
||||
self.execution_number[test_id] += 1
|
||||
return next_execution_number
|
||||
|
||||
def __register_start(self, task):
|
||||
with self.lock:
|
||||
self.started[task.task_id] = task
|
||||
|
||||
def register_exit(self, task):
|
||||
self.logger.log_exit(task)
|
||||
self.times.record_test_time(task.test_binary, task.test_name,
|
||||
task.last_execution_time)
|
||||
if self.test_results:
|
||||
self.test_results.log(task.test_name, task.runtime_ms / 1000.0,
|
||||
task.exit_code)
|
||||
|
||||
with self.lock:
|
||||
self.started.pop(task.task_id)
|
||||
if task.exit_code == 0:
|
||||
self.passed.append(task)
|
||||
elif task.exit_code == -errno.ETIME:
|
||||
self.timed_out.append(task)
|
||||
else:
|
||||
self.failed.append(task)
|
||||
|
||||
def run_task(self, task, timeout_per_test):
|
||||
for try_number in range(self.times_to_retry + 1):
|
||||
self.__register_start(task)
|
||||
task.run(timeout_per_test)
|
||||
self.register_exit(task)
|
||||
|
||||
if task.exit_code == 0:
|
||||
break
|
||||
|
||||
if try_number < self.times_to_retry:
|
||||
execution_number = self.__get_next_execution_number(task.test_id)
|
||||
# We need create a new Task instance. Each task represents a single test
|
||||
# execution, with its own runtime, exit code and log file.
|
||||
task = self.task_factory(task.test_binary, task.test_name,
|
||||
task.test_command, execution_number,
|
||||
task.last_execution_time, task.output_dir)
|
||||
|
||||
with self.lock:
|
||||
if task.exit_code != 0:
|
||||
self.global_exit_code = task.exit_code
|
||||
|
||||
|
||||
class FilterFormat(object):
|
||||
def __init__(self, output_dir):
|
||||
if sys.stdout.isatty():
|
||||
# stdout needs to be unbuffered since the output is interactive.
|
||||
if isinstance(sys.stdout, io.TextIOWrapper):
|
||||
# workaround for https://bugs.python.org/issue17404
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.detach(),
|
||||
line_buffering=True,
|
||||
write_through=True,
|
||||
newline='\n')
|
||||
else:
|
||||
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
|
||||
|
||||
self.output_dir = output_dir
|
||||
|
||||
self.total_tasks = 0
|
||||
self.finished_tasks = 0
|
||||
self.out = Outputter(sys.stdout)
|
||||
self.stdout_lock = threading.Lock()
|
||||
|
||||
def move_to(self, destination_dir, tasks):
|
||||
if self.output_dir is None:
|
||||
return
|
||||
|
||||
destination_dir = os.path.join(self.output_dir, destination_dir)
|
||||
os.makedirs(destination_dir)
|
||||
for task in tasks:
|
||||
shutil.move(task.log_file, destination_dir)
|
||||
|
||||
def print_tests(self, message, tasks, print_try_number, print_test_command):
|
||||
self.out.permanent_line("%s (%s/%s):" %
|
||||
(message, len(tasks), self.total_tasks))
|
||||
for task in sorted(tasks):
|
||||
runtime_ms = 'Interrupted'
|
||||
if task.runtime_ms is not None:
|
||||
runtime_ms = '%d ms' % task.runtime_ms
|
||||
if print_test_command:
|
||||
try:
|
||||
cmd_str = " ".join(task.test_command)
|
||||
except TypeError:
|
||||
cmd_str = task.test_command
|
||||
self.out.permanent_line(
|
||||
"%11s: %s%s" %
|
||||
(runtime_ms, cmd_str,
|
||||
(" (try #%d)" % task.execution_number) if print_try_number else ""))
|
||||
else:
|
||||
self.out.permanent_line(
|
||||
"%11s: %s %s%s" %
|
||||
(runtime_ms, task.test_binary, task.test_name,
|
||||
(" (try #%d)" % task.execution_number) if print_try_number else ""))
|
||||
|
||||
def log_exit(self, task):
|
||||
with self.stdout_lock:
|
||||
self.finished_tasks += 1
|
||||
self.out.transient_line("[%d/%d] %s (%d ms)" %
|
||||
(self.finished_tasks, self.total_tasks,
|
||||
task.test_name, task.runtime_ms))
|
||||
if task.exit_code != 0:
|
||||
signal_name = None
|
||||
if task.exit_code < 0:
|
||||
try:
|
||||
signal_name = signal.Signals(-task.exit_code).name
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
with open(task.log_file) as f:
|
||||
for line in f.readlines():
|
||||
self.out.permanent_line(line.rstrip())
|
||||
if task.exit_code is None:
|
||||
self.out.permanent_line("[%d/%d] %s aborted after %d ms" %
|
||||
(self.finished_tasks, self.total_tasks,
|
||||
task.test_name, task.runtime_ms))
|
||||
elif task.exit_code == -errno.ETIME:
|
||||
self.out.permanent_line(
|
||||
"\033[31m[ TIMEOUT ]\033[0m %s timed out after %d s"
|
||||
% (task.test_name, task.runtime_ms/1000))
|
||||
elif signal_name is not None:
|
||||
self.out.permanent_line(
|
||||
"[%d/%d] %s killed by signal %s (%d ms)" %
|
||||
(self.finished_tasks, self.total_tasks, task.test_name,
|
||||
signal_name, task.runtime_ms))
|
||||
else:
|
||||
self.out.permanent_line(
|
||||
"[%d/%d] %s returned with exit code %d (%d ms)" %
|
||||
(self.finished_tasks, self.total_tasks, task.test_name,
|
||||
task.exit_code, task.runtime_ms))
|
||||
|
||||
if self.output_dir is None:
|
||||
# Try to remove the file 100 times (sleeping for 0.1 second in between).
|
||||
# This is a workaround for a process handle seemingly holding on to the
|
||||
# file for too long inside os.subprocess. This workaround is in place
|
||||
# until we figure out a minimal repro to report upstream (or a better
|
||||
# suspect) to prevent os.remove exceptions.
|
||||
num_tries = 100
|
||||
for i in range(num_tries):
|
||||
try:
|
||||
os.remove(task.log_file)
|
||||
except OSError as e:
|
||||
if e.errno is not errno.ENOENT:
|
||||
if i is num_tries - 1:
|
||||
self.out.permanent_line('Could not remove temporary log file: ' +
|
||||
str(e))
|
||||
else:
|
||||
time.sleep(0.1)
|
||||
continue
|
||||
break
|
||||
|
||||
def log_tasks(self, total_tasks):
|
||||
self.total_tasks += total_tasks
|
||||
self.out.transient_line("[0/%d] Running tests..." % self.total_tasks)
|
||||
|
||||
def summarize(self, passed_tasks, failed_tasks, interrupted_tasks):
|
||||
stats = {}
|
||||
|
||||
def add_stats(stats, task, idx):
|
||||
task_key = (task.test_binary, task.test_name)
|
||||
if not task_key in stats:
|
||||
# (passed, failed, interrupted) task_key is added as tie breaker to get
|
||||
# alphabetic sorting on equally-stable tests
|
||||
stats[task_key] = [0, 0, 0, task_key]
|
||||
stats[task_key][idx] += 1
|
||||
|
||||
for task in passed_tasks:
|
||||
add_stats(stats, task, 0)
|
||||
for task in failed_tasks:
|
||||
add_stats(stats, task, 1)
|
||||
for task in interrupted_tasks:
|
||||
add_stats(stats, task, 2)
|
||||
|
||||
self.out.permanent_line("SUMMARY:")
|
||||
for task_key in sorted(stats, key=stats.__getitem__):
|
||||
(num_passed, num_failed, num_interrupted, _) = stats[task_key]
|
||||
(test_binary, task_name) = task_key
|
||||
total_runs = num_passed + num_failed + num_interrupted
|
||||
if num_passed == total_runs:
|
||||
continue
|
||||
self.out.permanent_line(" %s %s passed %d / %d times%s." %
|
||||
(test_binary, task_name, num_passed, total_runs,
|
||||
"" if num_interrupted == 0 else
|
||||
(" (%d interrupted)" % num_interrupted)))
|
||||
|
||||
def flush(self):
|
||||
self.out.flush_transient_output()
|
||||
|
||||
|
||||
class CollectTestResults(object):
|
||||
def __init__(self, json_dump_filepath):
|
||||
self.test_results_lock = threading.Lock()
|
||||
self.json_dump_file = open(json_dump_filepath, 'w')
|
||||
self.test_results = {
|
||||
"interrupted": False,
|
||||
"path_delimiter": ".",
|
||||
# Third version of the file format. See the link in the flag description
|
||||
# for details.
|
||||
"version": 3,
|
||||
"seconds_since_epoch": int(time.time()),
|
||||
"num_failures_by_type": {
|
||||
"PASS": 0,
|
||||
"FAIL": 0,
|
||||
"TIMEOUT": 0,
|
||||
},
|
||||
"tests": {},
|
||||
}
|
||||
|
||||
def log(self, test, runtime_seconds, exit_code):
|
||||
if exit_code is None:
|
||||
actual_result = "TIMEOUT"
|
||||
elif exit_code == 0:
|
||||
actual_result = "PASS"
|
||||
else:
|
||||
actual_result = "FAIL"
|
||||
with self.test_results_lock:
|
||||
self.test_results['num_failures_by_type'][actual_result] += 1
|
||||
results = self.test_results['tests']
|
||||
for name in test.split('.'):
|
||||
results = results.setdefault(name, {})
|
||||
|
||||
if results:
|
||||
results['actual'] += ' ' + actual_result
|
||||
results['times'].append(runtime_seconds)
|
||||
else: # This is the first invocation of the test
|
||||
results['actual'] = actual_result
|
||||
results['times'] = [runtime_seconds]
|
||||
results['time'] = runtime_seconds
|
||||
results['expected'] = 'PASS'
|
||||
|
||||
def dump_to_file_and_close(self):
|
||||
json.dump(self.test_results, self.json_dump_file)
|
||||
self.json_dump_file.close()
|
||||
|
||||
|
||||
# Record of test runtimes. Has built-in locking.
|
||||
class TestTimes(object):
|
||||
class LockedFile(object):
|
||||
def __init__(self, filename, mode):
|
||||
self._filename = filename
|
||||
self._mode = mode
|
||||
self._fo = None
|
||||
|
||||
def __enter__(self):
|
||||
self._fo = open(self._filename, self._mode)
|
||||
|
||||
# Regardless of opening mode we always seek to the beginning of file.
|
||||
# This simplifies code working with LockedFile and also ensures that
|
||||
# we lock (and unlock below) always the same region in file on win32.
|
||||
self._fo.seek(0)
|
||||
|
||||
try:
|
||||
if sys.platform == 'win32':
|
||||
# We are locking here fixed location in file to use it as
|
||||
# an exclusive lock on entire file.
|
||||
msvcrt.locking(self._fo.fileno(), msvcrt.LK_LOCK, 1)
|
||||
else:
|
||||
fcntl.flock(self._fo.fileno(), fcntl.LOCK_EX)
|
||||
except IOError:
|
||||
self._fo.close()
|
||||
raise
|
||||
|
||||
return self._fo
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
# Flush any buffered data to disk. This is needed to prevent race
|
||||
# condition which happens from the moment of releasing file lock
|
||||
# till closing the file.
|
||||
self._fo.flush()
|
||||
|
||||
try:
|
||||
if sys.platform == 'win32':
|
||||
self._fo.seek(0)
|
||||
msvcrt.locking(self._fo.fileno(), msvcrt.LK_UNLCK, 1)
|
||||
else:
|
||||
fcntl.flock(self._fo.fileno(), fcntl.LOCK_UN)
|
||||
finally:
|
||||
self._fo.close()
|
||||
|
||||
return exc_value is None
|
||||
|
||||
def __init__(self, save_file):
|
||||
"Create new object seeded with saved test times from the given file."
|
||||
self.__times = {} # (test binary, test name) -> runtime in ms
|
||||
|
||||
# Protects calls to record_test_time(); other calls are not
|
||||
# expected to be made concurrently.
|
||||
self.__lock = threading.Lock()
|
||||
|
||||
try:
|
||||
with TestTimes.LockedFile(save_file, 'rb') as fd:
|
||||
times = TestTimes.__read_test_times_file(fd)
|
||||
except IOError:
|
||||
# We couldn't obtain the lock.
|
||||
return
|
||||
|
||||
# Discard saved times if the format isn't right.
|
||||
if type(times) is not dict:
|
||||
return
|
||||
for ((test_binary, test_name), runtime) in times.items():
|
||||
if (type(test_binary) is not str or type(test_name) is not str
|
||||
or type(runtime) not in {int, long, type(None)}):
|
||||
return
|
||||
|
||||
self.__times = times
|
||||
|
||||
def get_test_time(self, binary, testname):
|
||||
"""Return the last duration for the given test as an integer number of
|
||||
milliseconds, or None if the test failed or if there's no record for it."""
|
||||
return self.__times.get((binary, testname), None)
|
||||
|
||||
def record_test_time(self, binary, testname, runtime_ms):
|
||||
"""Record that the given test ran in the specified number of
|
||||
milliseconds. If the test failed, runtime_ms should be None."""
|
||||
with self.__lock:
|
||||
self.__times[(binary, testname)] = runtime_ms
|
||||
|
||||
def write_to_file(self, save_file):
|
||||
"Write all the times to file."
|
||||
try:
|
||||
with TestTimes.LockedFile(save_file, 'a+b') as fd:
|
||||
times = TestTimes.__read_test_times_file(fd)
|
||||
|
||||
if times is None:
|
||||
times = self.__times
|
||||
else:
|
||||
times.update(self.__times)
|
||||
|
||||
# We erase data from file while still holding a lock to it. This
|
||||
# way reading old test times and appending new ones are atomic
|
||||
# for external viewer.
|
||||
fd.seek(0)
|
||||
fd.truncate()
|
||||
with gzip.GzipFile(fileobj=fd, mode='wb') as gzf:
|
||||
cPickle.dump(times, gzf, PICKLE_HIGHEST_PROTOCOL)
|
||||
except IOError:
|
||||
pass # ignore errors---saving the times isn't that important
|
||||
|
||||
@staticmethod
|
||||
def __read_test_times_file(fd):
|
||||
try:
|
||||
with gzip.GzipFile(fileobj=fd, mode='rb') as gzf:
|
||||
times = cPickle.load(gzf)
|
||||
except Exception:
|
||||
# File doesn't exist, isn't readable, is malformed---whatever.
|
||||
# Just ignore it.
|
||||
return None
|
||||
else:
|
||||
return times
|
||||
|
||||
|
||||
def find_tests(binaries, additional_args, options, times):
|
||||
test_count = 0
|
||||
tasks = []
|
||||
for test_binary in binaries:
|
||||
command = [test_binary] + additional_args
|
||||
if options.gtest_also_run_disabled_tests:
|
||||
command += ['--gtest_also_run_disabled_tests']
|
||||
|
||||
list_command = command + ['--gtest_list_tests']
|
||||
if options.gtest_filter != '':
|
||||
list_command += ['--gtest_filter=' + options.gtest_filter]
|
||||
|
||||
try:
|
||||
test_list = subprocess.check_output(list_command,
|
||||
stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
sys.exit("%s: %s\n%s" % (test_binary, str(e), e.output))
|
||||
|
||||
try:
|
||||
test_list = test_list.split('\n')
|
||||
except TypeError:
|
||||
# subprocess.check_output() returns bytes in python3
|
||||
test_list = test_list.decode(sys.stdout.encoding).split('\n')
|
||||
|
||||
command += ['--gtest_color=' + options.gtest_color]
|
||||
|
||||
test_group = ''
|
||||
for line in test_list:
|
||||
if not line.strip():
|
||||
continue
|
||||
if line[0] != " ":
|
||||
# Remove comments for typed tests and strip whitespace.
|
||||
test_group = line.split('#')[0].strip()
|
||||
continue
|
||||
# Remove comments for parameterized tests and strip whitespace.
|
||||
line = line.split('#')[0].strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
test_name = test_group + line
|
||||
if not options.gtest_also_run_disabled_tests and 'DISABLED_' in test_name:
|
||||
continue
|
||||
|
||||
# Skip PRE_ tests which are used by Chromium.
|
||||
if '.PRE_' in test_name:
|
||||
continue
|
||||
|
||||
last_execution_time = times.get_test_time(test_binary, test_name)
|
||||
if options.failed and last_execution_time is not None:
|
||||
continue
|
||||
|
||||
test_command = command + ['--gtest_filter=' + test_name]
|
||||
if (test_count - options.shard_index) % options.shard_count == 0:
|
||||
for execution_number in range(options.repeat):
|
||||
tasks.append(
|
||||
Task(test_binary, test_name, test_command, execution_number + 1,
|
||||
last_execution_time, options.output_dir))
|
||||
|
||||
test_count += 1
|
||||
|
||||
# Sort the tasks to run the slowest tests first, so that faster ones can be
|
||||
# finished in parallel.
|
||||
return sorted(tasks, reverse=True)
|
||||
|
||||
|
||||
def execute_tasks(tasks, pool_size, task_manager, timeout_seconds,
|
||||
timeout_per_test, serialize_test_cases):
|
||||
class WorkerFn(object):
|
||||
def __init__(self, tasks, running_groups, timeout_per_test):
|
||||
self.tasks = tasks
|
||||
self.running_groups = running_groups
|
||||
self.timeout_per_test = timeout_per_test
|
||||
self.task_lock = threading.Lock()
|
||||
|
||||
def __call__(self):
|
||||
while True:
|
||||
with self.task_lock:
|
||||
for task_id in range(len(self.tasks)):
|
||||
task = self.tasks[task_id]
|
||||
|
||||
if self.running_groups is not None:
|
||||
test_group = task.test_name.split('.')[0]
|
||||
if test_group in self.running_groups:
|
||||
# Try to find other non-running test group.
|
||||
continue
|
||||
else:
|
||||
self.running_groups.add(test_group)
|
||||
|
||||
del self.tasks[task_id]
|
||||
break
|
||||
else:
|
||||
# Either there is no tasks left or number or remaining test
|
||||
# cases (groups) is less than number or running threads.
|
||||
return
|
||||
|
||||
task_manager.run_task(task, self.timeout_per_test)
|
||||
|
||||
if self.running_groups is not None:
|
||||
with self.task_lock:
|
||||
self.running_groups.remove(test_group)
|
||||
|
||||
def start_daemon(func):
|
||||
t = threading.Thread(target=func)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
return t
|
||||
|
||||
timeout = None
|
||||
try:
|
||||
if timeout_seconds:
|
||||
timeout = threading.Timer(timeout_seconds, sigint_handler.interrupt)
|
||||
timeout.start()
|
||||
running_groups = set() if serialize_test_cases else None
|
||||
worker_fn = WorkerFn(tasks, running_groups, timeout_per_test)
|
||||
workers = [start_daemon(worker_fn) for _ in range(pool_size)]
|
||||
for worker in workers:
|
||||
worker.join()
|
||||
finally:
|
||||
if timeout:
|
||||
timeout.cancel()
|
||||
for task in list(task_manager.started.values()):
|
||||
task.runtime_ms = timeout_seconds * 1000
|
||||
task_manager.register_exit(task)
|
||||
|
||||
|
||||
def default_options_parser():
|
||||
parser = optparse.OptionParser(
|
||||
usage='usage: %prog [options] binary [binary ...] -- [additional args]')
|
||||
|
||||
parser.add_option('-d',
|
||||
'--output_dir',
|
||||
type='string',
|
||||
default=None,
|
||||
help='Output directory for test logs. Logs will be '
|
||||
'available under gtest-parallel-logs/, so '
|
||||
'--output_dir=/tmp will results in all logs being '
|
||||
'available under /tmp/gtest-parallel-logs/.')
|
||||
parser.add_option('-r',
|
||||
'--repeat',
|
||||
type='int',
|
||||
default=1,
|
||||
help='Number of times to execute all the tests.')
|
||||
parser.add_option('--retry_failed',
|
||||
type='int',
|
||||
default=0,
|
||||
help='Number of times to repeat failed tests.')
|
||||
parser.add_option('--failed',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='run only failed and new tests')
|
||||
parser.add_option('-w',
|
||||
'--workers',
|
||||
type='int',
|
||||
default=multiprocessing.cpu_count(),
|
||||
help='number of workers to spawn')
|
||||
parser.add_option('--gtest_color',
|
||||
type='string',
|
||||
default='yes',
|
||||
help='color output')
|
||||
parser.add_option('--gtest_filter',
|
||||
type='string',
|
||||
default='',
|
||||
help='test filter')
|
||||
parser.add_option('--gtest_also_run_disabled_tests',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='run disabled tests too')
|
||||
parser.add_option(
|
||||
'--print_test_times',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='list the run time of each test at the end of execution')
|
||||
parser.add_option(
|
||||
'--print_test_command',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Print full test command instead of name')
|
||||
parser.add_option('--shard_count',
|
||||
type='int',
|
||||
default=1,
|
||||
help='total number of shards (for sharding test execution '
|
||||
'between multiple machines)')
|
||||
parser.add_option('--shard_index',
|
||||
type='int',
|
||||
default=0,
|
||||
help='zero-indexed number identifying this shard (for '
|
||||
'sharding test execution between multiple machines)')
|
||||
parser.add_option(
|
||||
'--dump_json_test_results',
|
||||
type='string',
|
||||
default=None,
|
||||
help='Saves the results of the tests as a JSON machine-'
|
||||
'readable file. The format of the file is specified at '
|
||||
'https://www.chromium.org/developers/the-json-test-results-format')
|
||||
parser.add_option('--timeout',
|
||||
type='int',
|
||||
default=None,
|
||||
help='Interrupt all remaining processes after the given '
|
||||
'time (in seconds).')
|
||||
parser.add_option('--timeout_per_test',
|
||||
type='int',
|
||||
default=None,
|
||||
help='Interrupt single processes after the given '
|
||||
'time (in seconds).')
|
||||
parser.add_option('--serialize_test_cases',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Do not run tests from the same test '
|
||||
'case in parallel.')
|
||||
return parser
|
||||
|
||||
|
||||
def main():
|
||||
# Remove additional arguments (anything after --).
|
||||
additional_args = []
|
||||
|
||||
for i in range(len(sys.argv)):
|
||||
if sys.argv[i] == '--':
|
||||
additional_args = sys.argv[i + 1:]
|
||||
sys.argv = sys.argv[:i]
|
||||
break
|
||||
|
||||
parser = default_options_parser()
|
||||
(options, binaries) = parser.parse_args()
|
||||
|
||||
if (options.output_dir is not None and not os.path.isdir(options.output_dir)):
|
||||
parser.error('--output_dir value must be an existing directory, '
|
||||
'current value is "%s"' % options.output_dir)
|
||||
|
||||
# Append gtest-parallel-logs to log output, this is to avoid deleting user
|
||||
# data if an user passes a directory where files are already present. If a
|
||||
# user specifies --output_dir=Docs/, we'll create Docs/gtest-parallel-logs
|
||||
# and clean that directory out on startup, instead of nuking Docs/.
|
||||
if options.output_dir:
|
||||
options.output_dir = os.path.join(options.output_dir, 'gtest-parallel-logs')
|
||||
|
||||
if binaries == []:
|
||||
parser.print_usage()
|
||||
sys.exit(1)
|
||||
|
||||
if options.shard_count < 1:
|
||||
parser.error("Invalid number of shards: %d. Must be at least 1." %
|
||||
options.shard_count)
|
||||
if not (0 <= options.shard_index < options.shard_count):
|
||||
parser.error("Invalid shard index: %d. Must be between 0 and %d "
|
||||
"(less than the number of shards)." %
|
||||
(options.shard_index, options.shard_count - 1))
|
||||
|
||||
# Check that all test binaries have an unique basename. That way we can ensure
|
||||
# the logs are saved to unique files even when two different binaries have
|
||||
# common tests.
|
||||
unique_binaries = set(os.path.basename(binary) for binary in binaries)
|
||||
assert len(unique_binaries) == len(binaries), (
|
||||
"All test binaries must have an unique basename.")
|
||||
|
||||
if options.output_dir:
|
||||
# Remove files from old test runs.
|
||||
if os.path.isdir(options.output_dir):
|
||||
shutil.rmtree(options.output_dir)
|
||||
# Create directory for test log output.
|
||||
try:
|
||||
os.makedirs(options.output_dir)
|
||||
except OSError as e:
|
||||
# Ignore errors if this directory already exists.
|
||||
if e.errno != errno.EEXIST or not os.path.isdir(options.output_dir):
|
||||
raise e
|
||||
|
||||
test_results = None
|
||||
if options.dump_json_test_results is not None:
|
||||
test_results = CollectTestResults(options.dump_json_test_results)
|
||||
|
||||
save_file = get_save_file_path()
|
||||
|
||||
times = TestTimes(save_file)
|
||||
logger = FilterFormat(options.output_dir)
|
||||
|
||||
task_manager = TaskManager(times, logger, test_results, Task,
|
||||
options.retry_failed, options.repeat + 1)
|
||||
|
||||
tasks = find_tests(binaries, additional_args, options, times)
|
||||
logger.log_tasks(len(tasks))
|
||||
execute_tasks(tasks, options.workers, task_manager, options.timeout,
|
||||
options.timeout_per_test, options.serialize_test_cases)
|
||||
|
||||
print_try_number = options.retry_failed > 0 or options.repeat > 1
|
||||
if task_manager.passed:
|
||||
logger.move_to('passed', task_manager.passed)
|
||||
if options.print_test_times:
|
||||
logger.print_tests('PASSED TESTS', task_manager.passed, print_try_number, options.print_test_command)
|
||||
|
||||
if task_manager.failed:
|
||||
logger.print_tests('FAILED TESTS', task_manager.failed, print_try_number, options.print_test_command)
|
||||
logger.move_to('failed', task_manager.failed)
|
||||
|
||||
if task_manager.timed_out:
|
||||
logger.print_tests('TIMED OUT TESTS', task_manager.timed_out, print_try_number, options.print_test_command)
|
||||
logger.move_to('timed_out', task_manager.timed_out)
|
||||
|
||||
if task_manager.started:
|
||||
logger.print_tests('INTERRUPTED TESTS', task_manager.started.values(),
|
||||
print_try_number, options.print_test_command)
|
||||
logger.move_to('interrupted', task_manager.started.values())
|
||||
|
||||
if options.repeat > 1 and (task_manager.failed or task_manager.started):
|
||||
logger.summarize(task_manager.passed, task_manager.failed,
|
||||
task_manager.started.values())
|
||||
|
||||
logger.flush()
|
||||
times.write_to_file(save_file)
|
||||
if test_results:
|
||||
test_results.dump_to_file_and_close()
|
||||
|
||||
if sigint_handler.got_sigint():
|
||||
return -signal.SIGINT
|
||||
|
||||
return task_manager.global_exit_code
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# This source code is licensed under both the GPLv2 (found in the
|
||||
# COPYING file in the root directory) and Apache 2.0 License
|
||||
# (found in the LICENSE.Apache file in the root directory).
|
||||
#
|
||||
# Build RocksDB unit test binaries and run them under gtest-parallel,
|
||||
# which shards the test cases across CPUs for faster execution.
|
||||
#
|
||||
# Hardened version of a simple `make <bin> && gtest-parallel ./<bin>` helper:
|
||||
# * AUTO_CLEAN=1 so the Makefile automatically runs a clean when the build
|
||||
# parameters (DEBUG_LEVEL, sanitizers, ASSERT_STATUS_CHECKED, RTTI, etc.)
|
||||
# have changed since the last build, preventing stale/mixed object files.
|
||||
# * Parallel build with -j<NCORES>, computed the same way the Makefile does.
|
||||
# * Uses the gtest-parallel checked in alongside this script (build_tools/),
|
||||
# so it works regardless of PATH.
|
||||
# * `set -euo pipefail` so any failure stops the script.
|
||||
#
|
||||
# Run from the repository root.
|
||||
#
|
||||
# Accepts one or more test binaries (gtest-parallel pools all their test cases
|
||||
# into one shared worker queue). The leading non-option arguments are treated as
|
||||
# binaries; everything from the first option onward is forwarded to
|
||||
# gtest-parallel / the test binaries.
|
||||
#
|
||||
# Example usage:
|
||||
# build_tools/rocksptest.sh db_test
|
||||
# build_tools/rocksptest.sh db_test -r1000 --gtest_filter=*MixedSlowdown*
|
||||
# build_tools/rocksptest.sh db_test env_test db_basic_test
|
||||
# build_tools/rocksptest.sh db_test env_test --gtest_filter=*Foo*
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "usage: $0 <test_binary> [more_test_binaries...] [gtest-parallel/test args...]" >&2
|
||||
echo "example: $0 db_test env_test -r1000 --gtest_filter=*MixedSlowdown*" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# First argument must be a test binary, not an option (catches a forgotten name).
|
||||
if [ "${1#-}" != "$1" ]; then
|
||||
echo "$0: first argument must be a test binary name, not an option ('$1')" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Collect the leading non-option arguments as test binaries; everything from the
|
||||
# first option onward is forwarded to gtest-parallel / the test binaries.
|
||||
BINS=()
|
||||
while [ "$#" -gt 0 ] && [ "${1#-}" = "$1" ]; do
|
||||
BINS+=("$1")
|
||||
shift
|
||||
done
|
||||
|
||||
# Paths as gtest-parallel expects them (relative to the current directory).
|
||||
BIN_PATHS=()
|
||||
for b in "${BINS[@]}"; do
|
||||
BIN_PATHS+=("./$b")
|
||||
done
|
||||
|
||||
# Directory of this script, so we use the gtest-parallel checked in next to it.
|
||||
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
|
||||
# Compute parallelism the same way the Makefile computes NCORES.
|
||||
NCORES=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
|
||||
|
||||
make AUTO_CLEAN=1 -j"$NCORES" "${BINS[@]}"
|
||||
"$SCRIPT_DIR/gtest-parallel" "${BIN_PATHS[@]}" "$@"
|
||||
@@ -1,76 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# This source code is licensed under both the GPLv2 (found in the
|
||||
# COPYING file in the root directory) and Apache 2.0 License
|
||||
# (found in the LICENSE.Apache file in the root directory).
|
||||
#
|
||||
# Build a single RocksDB unit test binary and run it directly (serially).
|
||||
# Only recommended with --gtest_filter=... because of speed. See also
|
||||
# build_tools/rocksptest.sh
|
||||
#
|
||||
# Hardened version of a simple `make <bin> && ./<bin>` helper:
|
||||
# * AUTO_CLEAN=1 so the Makefile automatically runs a clean when the build
|
||||
# parameters (DEBUG_LEVEL, sanitizers, ASSERT_STATUS_CHECKED, RTTI, etc.)
|
||||
# have changed since the last build, preventing stale/mixed object files.
|
||||
# * Parallel build with -j<NCORES>, computed the same way the Makefile does.
|
||||
# * `set -euo pipefail` so any failure stops the script.
|
||||
#
|
||||
# Run from the repository root.
|
||||
#
|
||||
# Example usage:
|
||||
# build_tools/rockstest.sh db_test --gtest_filter=*MixedSlowdown*
|
||||
# build_tools/rockstest.sh env_test # Slow to run many tests serially
|
||||
#
|
||||
# Install mode:
|
||||
# build_tools/rockstest.sh install
|
||||
# Creates ~/bin/rockstest and ~/bin/rocksptest shims that defer to
|
||||
# build_tools/rockstest.sh / rocksptest.sh in whatever directory you run
|
||||
# them from, so you can just type `rockstest db_test` from any rocksdb
|
||||
# source root.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Install mode: write thin ~/bin shims that defer to the build_tools scripts in
|
||||
# the current directory.
|
||||
if [ "${1:-}" = "install" ]; then
|
||||
mkdir -p "$HOME/bin"
|
||||
for name in rockstest rocksptest; do
|
||||
dest="$HOME/bin/$name"
|
||||
cat > "$dest" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
# Auto-generated by 'build_tools/rockstest.sh install'. Defers to
|
||||
# build_tools/$name.sh in the current rocksdb source root.
|
||||
if [ -x build_tools/$name.sh ]; then
|
||||
exec build_tools/$name.sh "\$@"
|
||||
else
|
||||
echo "build_tools/$name.sh not found (Not in a rocksdb source root directory?)" >&2
|
||||
exit 1
|
||||
fi
|
||||
EOF
|
||||
chmod +x "$dest"
|
||||
echo "Installed $dest"
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "usage: $0 <test_binary> [test args...]" >&2
|
||||
echo " $0 install # create ~/bin/rockstest and ~/bin/rocksptest shims" >&2
|
||||
echo "example: $0 db_test --gtest_filter=*MixedSlowdown*" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# First argument must be a test binary, not an option (catches a forgotten name).
|
||||
if [ "${1#-}" != "$1" ]; then
|
||||
echo "$0: first argument must be a test binary name, not an option ('$1')" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BIN=$1
|
||||
shift
|
||||
|
||||
# Compute parallelism the same way the Makefile computes NCORES.
|
||||
NCORES=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
|
||||
|
||||
make AUTO_CLEAN=1 -j"$NCORES" "$BIN"
|
||||
./"$BIN" "$@"
|
||||
@@ -5,8 +5,6 @@
|
||||
# the docker and docker-registry groups, and logging out and back in to pick
|
||||
# those up.)
|
||||
#
|
||||
# Meta employees: see https://fburl.com/rocksdb-docker to build this on a devvm.
|
||||
#
|
||||
# Follow https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic
|
||||
# to login with your GitHub credentials, as in
|
||||
#
|
||||
@@ -17,8 +15,8 @@
|
||||
# Then in the build_tools/ubuntu22_image directory, (bump minor version for
|
||||
# random docker file updates, major version tracks Ubuntu release)
|
||||
#
|
||||
# $ docker build -t ghcr.io/facebook/rocksdb_ubuntu:22.2
|
||||
# $ docker push ghcr.io/facebook/rocksdb_ubuntu:22.2
|
||||
# $ docker build -t ghcr.io/facebook/rocksdb_ubuntu:22.0
|
||||
# $ docker push ghcr.io/facebook/rocksdb_ubuntu:22.0
|
||||
#
|
||||
# Might need to change visibility to public through
|
||||
# https://github.com/orgs/facebook/packages/container/rocksdb_ubuntu/settings
|
||||
@@ -30,7 +28,7 @@ FROM ubuntu:22.04
|
||||
RUN apt-get update
|
||||
RUN apt-get upgrade -y
|
||||
# install basic tools
|
||||
RUN apt-get install -y vim wget curl ccache
|
||||
RUN apt-get install -y vim wget curl
|
||||
# install tzdata noninteractive
|
||||
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata
|
||||
# install git and default compilers
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
# the docker and docker-registry groups, and logging out and back in to pick
|
||||
# those up.)
|
||||
#
|
||||
# Meta employees: see https://fburl.com/rocksdb-docker to build this on a devvm.
|
||||
#
|
||||
# Follow https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic
|
||||
# to login with your GitHub credentials, as in
|
||||
#
|
||||
@@ -17,8 +15,8 @@
|
||||
# Then in the build_tools/ubuntu24_image directory, (bump minor version for
|
||||
# random docker file updates, major version tracks Ubuntu release)
|
||||
#
|
||||
# $ docker build -t ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
# $ docker push ghcr.io/facebook/rocksdb_ubuntu:24.1
|
||||
# $ docker build -t ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
# $ docker push ghcr.io/facebook/rocksdb_ubuntu:24.0
|
||||
#
|
||||
# Might need to change visibility to public through
|
||||
# https://github.com/orgs/facebook/packages/container/rocksdb_ubuntu/settings
|
||||
@@ -30,15 +28,11 @@ FROM ubuntu:24.04
|
||||
RUN apt-get update
|
||||
RUN apt-get upgrade -y
|
||||
# install basic tools
|
||||
RUN apt-get install -y vim wget curl ccache
|
||||
RUN apt-get install -y vim wget curl
|
||||
# install tzdata noninteractive
|
||||
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata
|
||||
# install git and default compilers
|
||||
RUN apt-get install -y git gcc g++ clang clang-tools
|
||||
# install clang-21 from LLVM snapshot repo
|
||||
RUN curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/llvm.gpg && \
|
||||
echo "deb https://apt.llvm.org/noble/ llvm-toolchain-noble-21 main" > /etc/apt/sources.list.d/llvm-21.list && \
|
||||
apt-get update && apt-get install -y clang-21
|
||||
# install basic package
|
||||
RUN apt-get install -y lsb-release software-properties-common gnupg
|
||||
# install gflags, tbb
|
||||
|
||||
@@ -32,7 +32,7 @@ function get_lib_base()
|
||||
local lib_platform=$3
|
||||
|
||||
local result="$TP2_LATEST/$lib_name/"
|
||||
|
||||
|
||||
# Lib Version
|
||||
if [ -z "$lib_version" ] || [ "$lib_version" = "LATEST" ]; then
|
||||
# version is not provided, use latest
|
||||
@@ -40,7 +40,7 @@ function get_lib_base()
|
||||
else
|
||||
result="$result/$lib_version/"
|
||||
fi
|
||||
|
||||
|
||||
# Lib Platform
|
||||
if [ -z "$lib_platform" ]; then
|
||||
# platform is not provided, use latest gcc
|
||||
@@ -49,17 +49,17 @@ function get_lib_base()
|
||||
echo $lib_platform
|
||||
result="$result/$lib_platform/"
|
||||
fi
|
||||
|
||||
|
||||
result=`ls -1d $result/*/ | head -n1`
|
||||
|
||||
echo Finding link $result
|
||||
|
||||
|
||||
# lib_name => LIB_NAME_BASE
|
||||
local __res_var=${lib_name^^}"_BASE"
|
||||
__res_var=`echo $__res_var | tr - _`
|
||||
# LIB_NAME_BASE=$result
|
||||
eval $__res_var=`readlink -f $result`
|
||||
|
||||
|
||||
log_variable $__res_var
|
||||
}
|
||||
|
||||
@@ -75,33 +75,17 @@ touch "$OUTPUT"
|
||||
echo "Writing dependencies to $OUTPUT"
|
||||
|
||||
# Compilers locations
|
||||
# GCC is pinned to 11.x because the only newer GCC in third-party2 (13.x) is
|
||||
# built for centos9/glibc>=2.35 -- its libgcc_s.so.1 has a hard reference
|
||||
# to _dl_find_object@GLIBC_2.35, but platform010 ships glibc 2.34. Bumping
|
||||
# GCC requires a platform with glibc >= 2.35.
|
||||
GCC_BASE=`readlink -f $TP2_LATEST/gcc/11.x/centos9-native/*/`
|
||||
# Clang is pinned to the latest tested major (21). Bump deliberately.
|
||||
CLANG_BASE=`readlink -f $TP2_LATEST/llvm-fb/21/platform010/*/`
|
||||
GCC_BASE=`readlink -f $TP2_LATEST/gcc/11.x/centos8-native/*/`
|
||||
CLANG_BASE=`readlink -f $TP2_LATEST/llvm-fb/15/platform010/*/`
|
||||
|
||||
log_header
|
||||
log_variable GCC_BASE
|
||||
log_variable CLANG_BASE
|
||||
|
||||
# Libraries locations
|
||||
# libgcc is pinned to 11.x to match the GCC 11 compiler above (libstdc++/
|
||||
# libgcc runtime, ABI, and C++ headers). Bump in lockstep with GCC_BASE.
|
||||
get_lib_base libgcc 11.x platform010
|
||||
# glibc 2.34 is the platform010 ABI baseline (ld.so + libc); it is also the
|
||||
# only version available in third-party2, and defines the platform -- do
|
||||
# not bump independently.
|
||||
get_lib_base glibc 2.34 platform010
|
||||
get_lib_base snappy LATEST platform010
|
||||
# zlib is pinned to 1.2.8: it is the latest version with an x86_64
|
||||
# platform010 build (1.2.13 / 1.3.1 are centos9 / aarch64 only). At time of
|
||||
# writing, LATEST here doesn't work: get_lib_base picks the newest version
|
||||
# dir first and only then appends the platform, with no fallback -- so
|
||||
# LATEST would resolve to 1.3.1, find no platform010 build, and emit an
|
||||
# empty ZLIB_BASE.
|
||||
get_lib_base zlib 1.2.8 platform010
|
||||
get_lib_base bzip2 LATEST platform010
|
||||
get_lib_base lz4 LATEST platform010
|
||||
@@ -110,11 +94,12 @@ get_lib_base gflags LATEST platform010
|
||||
get_lib_base jemalloc LATEST platform010
|
||||
get_lib_base numa LATEST platform010
|
||||
get_lib_base libunwind LATEST platform010
|
||||
get_lib_base tbb 2018_U5 platform010
|
||||
get_lib_base liburing LATEST platform010
|
||||
get_lib_base benchmark LATEST platform010
|
||||
|
||||
get_lib_base kernel-headers fb platform010
|
||||
get_lib_base binutils LATEST centos9-native
|
||||
get_lib_base binutils LATEST centos8-native
|
||||
get_lib_base valgrind LATEST platform010
|
||||
|
||||
git diff $OUTPUT
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'BlockBasedOptions simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_block_based_options_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_block_based_options_subset.cc.inc
|
||||
|
||||
/* BlockBasedOptions simple */
|
||||
|
||||
void rocksdb_block_based_options_set_data_block_hash_ratio(
|
||||
rocksdb_block_based_table_options_t* options, double v) {
|
||||
options->rep.data_block_hash_table_util_ratio = v;
|
||||
}
|
||||
|
||||
void rocksdb_block_based_options_set_top_level_index_pinning_tier(
|
||||
rocksdb_block_based_table_options_t* options, int v) {
|
||||
options->rep.metadata_cache_options.top_level_index_pinning =
|
||||
static_cast<ROCKSDB_NAMESPACE::PinningTier>(v);
|
||||
}
|
||||
|
||||
void rocksdb_block_based_options_set_partition_pinning_tier(
|
||||
rocksdb_block_based_table_options_t* options, int v) {
|
||||
options->rep.metadata_cache_options.partition_pinning =
|
||||
static_cast<ROCKSDB_NAMESPACE::PinningTier>(v);
|
||||
}
|
||||
|
||||
void rocksdb_block_based_options_set_unpartitioned_pinning_tier(
|
||||
rocksdb_block_based_table_options_t* options, int v) {
|
||||
options->rep.metadata_cache_options.unpartitioned_pinning =
|
||||
static_cast<ROCKSDB_NAMESPACE::PinningTier>(v);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'BlockBasedOptions simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_block_based_options_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_block_based_options_subset.cc.inc
|
||||
|
||||
/* BlockBasedOptions simple */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_block_based_options_set_data_block_hash_ratio(
|
||||
rocksdb_block_based_table_options_t* options, double v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_block_based_options_set_top_level_index_pinning_tier(
|
||||
rocksdb_block_based_table_options_t* options, int v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_block_based_options_set_partition_pinning_tier(
|
||||
rocksdb_block_based_table_options_t* options, int v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_block_based_options_set_unpartitioned_pinning_tier(
|
||||
rocksdb_block_based_table_options_t* options, int v);
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'CuckooOptions simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_cuckoo_options_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_cuckoo_options_subset.cc.inc
|
||||
|
||||
/* CuckooOptions simple */
|
||||
|
||||
void rocksdb_cuckoo_options_set_hash_ratio(
|
||||
rocksdb_cuckoo_table_options_t* options, double v) {
|
||||
options->rep.hash_table_ratio = v;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'CuckooOptions simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_cuckoo_options_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_cuckoo_options_subset.cc.inc
|
||||
|
||||
/* CuckooOptions simple */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_cuckoo_options_set_hash_ratio(
|
||||
rocksdb_cuckoo_table_options_t* options, double v);
|
||||
@@ -1,193 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'DB data operations'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_db_simple_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_db_simple_subset.cc.inc
|
||||
|
||||
/* DB data operations */
|
||||
|
||||
void rocksdb_put(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr,
|
||||
db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_put_cf(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, const char* val,
|
||||
size_t vallen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Put(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete_cf(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Delete(options->rep, column_family->rep,
|
||||
Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_merge(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, const char* val,
|
||||
size_t vallen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Merge(options->rep, Slice(key, keylen),
|
||||
Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_merge_cf(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, const char* val,
|
||||
size_t vallen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Merge(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_write(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_t* batch, char** errptr) {
|
||||
SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
|
||||
}
|
||||
|
||||
void rocksdb_put_with_ts(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, const char* ts,
|
||||
size_t tslen, const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->Put(options->rep, Slice(key, keylen),
|
||||
Slice(ts, tslen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_put_cf_with_ts(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, const char* ts,
|
||||
size_t tslen, const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr,
|
||||
db->rep->Put(options->rep, column_family->rep, Slice(key, keylen),
|
||||
Slice(ts, tslen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete_with_ts(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, const char* ts,
|
||||
size_t tslen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen),
|
||||
Slice(ts, tslen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete_cf_with_ts(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, const char* ts,
|
||||
size_t tslen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Delete(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(ts, tslen)));
|
||||
}
|
||||
|
||||
void rocksdb_singledelete(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, char** errptr) {
|
||||
SaveError(errptr, db->rep->SingleDelete(options->rep, Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_singledelete_cf(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, char** errptr) {
|
||||
SaveError(errptr, db->rep->SingleDelete(options->rep, column_family->rep,
|
||||
Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_singledelete_with_ts(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen,
|
||||
const char* ts, size_t tslen, char** errptr) {
|
||||
SaveError(errptr, db->rep->SingleDelete(options->rep, Slice(key, keylen),
|
||||
Slice(ts, tslen)));
|
||||
}
|
||||
|
||||
void rocksdb_singledelete_cf_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr) {
|
||||
SaveError(errptr,
|
||||
db->rep->SingleDelete(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(ts, tslen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete_range_cf(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* start_key, size_t start_key_len,
|
||||
const char* end_key, size_t end_key_len,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->DeleteRange(options->rep, column_family->rep,
|
||||
Slice(start_key, start_key_len),
|
||||
Slice(end_key, end_key_len)));
|
||||
}
|
||||
|
||||
void rocksdb_flush(rocksdb_t* db, const rocksdb_flushoptions_t* options,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->Flush(options->rep));
|
||||
}
|
||||
|
||||
void rocksdb_flush_cf(rocksdb_t* db, const rocksdb_flushoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->Flush(options->rep, column_family->rep));
|
||||
}
|
||||
|
||||
void rocksdb_flush_wal(rocksdb_t* db, unsigned char sync, char** errptr) {
|
||||
SaveError(errptr, db->rep->FlushWAL(sync));
|
||||
}
|
||||
|
||||
void rocksdb_pause_background_work(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->PauseBackgroundWork());
|
||||
}
|
||||
|
||||
void rocksdb_continue_background_work(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->ContinueBackgroundWork());
|
||||
}
|
||||
|
||||
void rocksdb_disable_file_deletions(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->DisableFileDeletions());
|
||||
}
|
||||
|
||||
void rocksdb_enable_file_deletions(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->EnableFileDeletions());
|
||||
}
|
||||
|
||||
void rocksdb_verify_checksum(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->VerifyChecksum());
|
||||
}
|
||||
|
||||
void rocksdb_verify_file_checksums(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->VerifyFileChecksums(ReadOptions()));
|
||||
}
|
||||
|
||||
void rocksdb_destroy_db(const rocksdb_options_t* options, const char* name,
|
||||
char** errptr) {
|
||||
SaveError(errptr, DestroyDB(name, options->rep));
|
||||
}
|
||||
|
||||
void rocksdb_repair_db(const rocksdb_options_t* options, const char* name,
|
||||
char** errptr) {
|
||||
SaveError(errptr, RepairDB(name, options->rep));
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'DB data operations'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_db_simple_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_db_simple_subset.cc.inc
|
||||
|
||||
/* DB data operations */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_put(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_put_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_merge(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_merge_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_write(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_t* batch, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_put_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, const char* val, size_t vallen,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_put_cf_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, const char* val, size_t vallen,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete_cf_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_singledelete(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_singledelete_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_singledelete_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_singledelete_cf_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete_range_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* start_key,
|
||||
size_t start_key_len, const char* end_key, size_t end_key_len,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_flush(
|
||||
rocksdb_t* db, const rocksdb_flushoptions_t* options, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_flush_cf(
|
||||
rocksdb_t* db, const rocksdb_flushoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_flush_wal(rocksdb_t* db,
|
||||
unsigned char sync,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_pause_background_work(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_continue_background_work(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_disable_file_deletions(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_enable_file_deletions(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_verify_checksum(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_verify_file_checksums(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_destroy_db(
|
||||
const rocksdb_options_t* options, const char* name, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_repair_db(
|
||||
const rocksdb_options_t* options, const char* name, char** errptr);
|
||||
@@ -1,259 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/auto_simple_bindings.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Sources:
|
||||
// - include/rocksdb/listener.h
|
||||
// - tools/c_api_gen/auto_simple_bindings_blocklist.json
|
||||
// - include/rocksdb/c.h
|
||||
// - tools/c_api_gen/c_base.cc
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/auto_simple_bindings.py
|
||||
|
||||
// Output group: Auto-discovered JobInfo metadata simple
|
||||
|
||||
/* FlushJobInfo */
|
||||
|
||||
uint32_t rocksdb_flushjobinfo_cf_id(const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.cf_id;
|
||||
}
|
||||
|
||||
const char* rocksdb_flushjobinfo_cf_name(const rocksdb_flushjobinfo_t* info,
|
||||
size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_flushjobinfo_file_path(const rocksdb_flushjobinfo_t* info,
|
||||
size_t* size) {
|
||||
*size = info->rep.file_path.size();
|
||||
return info->rep.file_path.data();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_flushjobinfo_file_number(const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.file_number;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_flushjobinfo_oldest_blob_file_number(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.oldest_blob_file_number;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_flushjobinfo_thread_id(const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.thread_id;
|
||||
}
|
||||
|
||||
int rocksdb_flushjobinfo_job_id(const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.job_id;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_flushjobinfo_triggered_writes_slowdown(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.triggered_writes_slowdown;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_flushjobinfo_triggered_writes_stop(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.triggered_writes_stop;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_flushjobinfo_smallest_seqno(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.smallest_seqno;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_flushjobinfo_largest_seqno(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.largest_seqno;
|
||||
}
|
||||
|
||||
uint32_t rocksdb_flushjobinfo_flush_reason(const rocksdb_flushjobinfo_t* info) {
|
||||
return static_cast<uint32_t>(info->rep.flush_reason);
|
||||
}
|
||||
|
||||
uint32_t rocksdb_flushjobinfo_blob_compression_type(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return static_cast<uint32_t>(info->rep.blob_compression_type);
|
||||
}
|
||||
|
||||
/* CompactionJobInfo */
|
||||
|
||||
uint32_t rocksdb_compactionjobinfo_cf_id(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.cf_id;
|
||||
}
|
||||
|
||||
const char* rocksdb_compactionjobinfo_cf_name(
|
||||
const rocksdb_compactionjobinfo_t* info, size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
void rocksdb_compactionjobinfo_status(const rocksdb_compactionjobinfo_t* info,
|
||||
char** errptr) {
|
||||
SaveError(errptr, info->rep.status);
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_thread_id(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.thread_id;
|
||||
}
|
||||
|
||||
int rocksdb_compactionjobinfo_job_id(const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.job_id;
|
||||
}
|
||||
|
||||
int rocksdb_compactionjobinfo_num_l0_files(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.num_l0_files;
|
||||
}
|
||||
|
||||
int rocksdb_compactionjobinfo_base_input_level(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.base_input_level;
|
||||
}
|
||||
|
||||
int rocksdb_compactionjobinfo_output_level(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.output_level;
|
||||
}
|
||||
|
||||
uint32_t rocksdb_compactionjobinfo_compaction_reason(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return static_cast<uint32_t>(info->rep.compaction_reason);
|
||||
}
|
||||
|
||||
uint32_t rocksdb_compactionjobinfo_compression(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return static_cast<uint32_t>(info->rep.compression);
|
||||
}
|
||||
|
||||
uint32_t rocksdb_compactionjobinfo_blob_compression_type(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return static_cast<uint32_t>(info->rep.blob_compression_type);
|
||||
}
|
||||
|
||||
unsigned char rocksdb_compactionjobinfo_aborted(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.aborted;
|
||||
}
|
||||
|
||||
/* SubcompactionJobInfo */
|
||||
|
||||
uint32_t rocksdb_subcompactionjobinfo_cf_id(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return info->rep.cf_id;
|
||||
}
|
||||
|
||||
const char* rocksdb_subcompactionjobinfo_cf_name(
|
||||
const rocksdb_subcompactionjobinfo_t* info, size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
void rocksdb_subcompactionjobinfo_status(
|
||||
const rocksdb_subcompactionjobinfo_t* info, char** errptr) {
|
||||
SaveError(errptr, info->rep.status);
|
||||
}
|
||||
|
||||
uint64_t rocksdb_subcompactionjobinfo_thread_id(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return info->rep.thread_id;
|
||||
}
|
||||
|
||||
int rocksdb_subcompactionjobinfo_job_id(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return info->rep.job_id;
|
||||
}
|
||||
|
||||
int rocksdb_subcompactionjobinfo_subcompaction_job_id(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return info->rep.subcompaction_job_id;
|
||||
}
|
||||
|
||||
int rocksdb_subcompactionjobinfo_base_input_level(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return info->rep.base_input_level;
|
||||
}
|
||||
|
||||
int rocksdb_subcompactionjobinfo_output_level(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return info->rep.output_level;
|
||||
}
|
||||
|
||||
uint32_t rocksdb_subcompactionjobinfo_compaction_reason(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return static_cast<uint32_t>(info->rep.compaction_reason);
|
||||
}
|
||||
|
||||
uint32_t rocksdb_subcompactionjobinfo_compression(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return static_cast<uint32_t>(info->rep.compression);
|
||||
}
|
||||
|
||||
uint32_t rocksdb_subcompactionjobinfo_blob_compression_type(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return static_cast<uint32_t>(info->rep.blob_compression_type);
|
||||
}
|
||||
|
||||
/* ExternalFileIngestionInfo */
|
||||
|
||||
const char* rocksdb_externalfileingestioninfo_cf_name(
|
||||
const rocksdb_externalfileingestioninfo_t* info, size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_externalfileingestioninfo_external_file_path(
|
||||
const rocksdb_externalfileingestioninfo_t* info, size_t* size) {
|
||||
*size = info->rep.external_file_path.size();
|
||||
return info->rep.external_file_path.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_externalfileingestioninfo_internal_file_path(
|
||||
const rocksdb_externalfileingestioninfo_t* info, size_t* size) {
|
||||
*size = info->rep.internal_file_path.size();
|
||||
return info->rep.internal_file_path.data();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_externalfileingestioninfo_global_seqno(
|
||||
const rocksdb_externalfileingestioninfo_t* info) {
|
||||
return info->rep.global_seqno;
|
||||
}
|
||||
|
||||
/* MemTableInfo */
|
||||
|
||||
const char* rocksdb_memtableinfo_cf_name(const rocksdb_memtableinfo_t* info,
|
||||
size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_memtableinfo_first_seqno(const rocksdb_memtableinfo_t* info) {
|
||||
return info->rep.first_seqno;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_memtableinfo_earliest_seqno(
|
||||
const rocksdb_memtableinfo_t* info) {
|
||||
return info->rep.earliest_seqno;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_memtableinfo_num_entries(const rocksdb_memtableinfo_t* info) {
|
||||
return info->rep.num_entries;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_memtableinfo_num_deletes(const rocksdb_memtableinfo_t* info) {
|
||||
return info->rep.num_deletes;
|
||||
}
|
||||
|
||||
const char* rocksdb_memtableinfo_newest_udt(const rocksdb_memtableinfo_t* info,
|
||||
size_t* size) {
|
||||
*size = info->rep.newest_udt.size();
|
||||
return info->rep.newest_udt.data();
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/auto_simple_bindings.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Sources:
|
||||
// - include/rocksdb/listener.h
|
||||
// - tools/c_api_gen/auto_simple_bindings_blocklist.json
|
||||
// - include/rocksdb/c.h
|
||||
// - tools/c_api_gen/c_base.cc
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/auto_simple_bindings.py
|
||||
|
||||
// Output group: Auto-discovered JobInfo metadata simple
|
||||
|
||||
/* FlushJobInfo */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t
|
||||
rocksdb_flushjobinfo_cf_id(const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_flushjobinfo_cf_name(
|
||||
const rocksdb_flushjobinfo_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_flushjobinfo_file_path(
|
||||
const rocksdb_flushjobinfo_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_flushjobinfo_file_number(const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_flushjobinfo_oldest_blob_file_number(
|
||||
const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_flushjobinfo_thread_id(const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_flushjobinfo_job_id(
|
||||
const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_flushjobinfo_triggered_writes_slowdown(
|
||||
const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_flushjobinfo_triggered_writes_stop(const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_flushjobinfo_smallest_seqno(const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_flushjobinfo_largest_seqno(const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t
|
||||
rocksdb_flushjobinfo_flush_reason(const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t
|
||||
rocksdb_flushjobinfo_blob_compression_type(const rocksdb_flushjobinfo_t* info);
|
||||
|
||||
/* CompactionJobInfo */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t
|
||||
rocksdb_compactionjobinfo_cf_id(const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_compactionjobinfo_cf_name(
|
||||
const rocksdb_compactionjobinfo_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_compactionjobinfo_status(
|
||||
const rocksdb_compactionjobinfo_t* info, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compactionjobinfo_thread_id(const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_compactionjobinfo_job_id(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_compactionjobinfo_num_l0_files(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_compactionjobinfo_base_input_level(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_compactionjobinfo_output_level(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t rocksdb_compactionjobinfo_compaction_reason(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t
|
||||
rocksdb_compactionjobinfo_compression(const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t
|
||||
rocksdb_compactionjobinfo_blob_compression_type(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char rocksdb_compactionjobinfo_aborted(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
/* SubcompactionJobInfo */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t
|
||||
rocksdb_subcompactionjobinfo_cf_id(const rocksdb_subcompactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_subcompactionjobinfo_cf_name(
|
||||
const rocksdb_subcompactionjobinfo_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_subcompactionjobinfo_status(
|
||||
const rocksdb_subcompactionjobinfo_t* info, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_subcompactionjobinfo_thread_id(
|
||||
const rocksdb_subcompactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_subcompactionjobinfo_job_id(
|
||||
const rocksdb_subcompactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int
|
||||
rocksdb_subcompactionjobinfo_subcompaction_job_id(
|
||||
const rocksdb_subcompactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_subcompactionjobinfo_base_input_level(
|
||||
const rocksdb_subcompactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_subcompactionjobinfo_output_level(
|
||||
const rocksdb_subcompactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t
|
||||
rocksdb_subcompactionjobinfo_compaction_reason(
|
||||
const rocksdb_subcompactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t rocksdb_subcompactionjobinfo_compression(
|
||||
const rocksdb_subcompactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint32_t
|
||||
rocksdb_subcompactionjobinfo_blob_compression_type(
|
||||
const rocksdb_subcompactionjobinfo_t* info);
|
||||
|
||||
/* ExternalFileIngestionInfo */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_externalfileingestioninfo_cf_name(
|
||||
const rocksdb_externalfileingestioninfo_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_externalfileingestioninfo_external_file_path(
|
||||
const rocksdb_externalfileingestioninfo_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_externalfileingestioninfo_internal_file_path(
|
||||
const rocksdb_externalfileingestioninfo_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_externalfileingestioninfo_global_seqno(
|
||||
const rocksdb_externalfileingestioninfo_t* info);
|
||||
|
||||
/* MemTableInfo */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_memtableinfo_cf_name(
|
||||
const rocksdb_memtableinfo_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_memtableinfo_first_seqno(const rocksdb_memtableinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_memtableinfo_earliest_seqno(const rocksdb_memtableinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_memtableinfo_num_entries(const rocksdb_memtableinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_memtableinfo_num_deletes(const rocksdb_memtableinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_memtableinfo_newest_udt(
|
||||
const rocksdb_memtableinfo_t* info, size_t* size);
|
||||
@@ -1,88 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'JobInfo metadata simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_jobinfo_metadata_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_jobinfo_metadata_subset.cc.inc
|
||||
|
||||
/* JobInfo metadata simple */
|
||||
|
||||
size_t rocksdb_compactionjobinfo_input_files_count(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.input_files.size();
|
||||
}
|
||||
|
||||
size_t rocksdb_compactionjobinfo_output_files_count(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.output_files.size();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_elapsed_micros(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.elapsed_micros;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_num_corrupt_keys(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_corrupt_keys;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_input_records(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_input_records;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_output_records(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_output_records;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_total_input_bytes(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.total_input_bytes;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_total_output_bytes(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.total_output_bytes;
|
||||
}
|
||||
|
||||
size_t rocksdb_compactionjobinfo_num_input_files(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_input_files;
|
||||
}
|
||||
|
||||
size_t rocksdb_compactionjobinfo_num_input_files_at_output_level(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_input_files_at_output_level;
|
||||
}
|
||||
|
||||
const char* rocksdb_writestallinfo_cf_name(const rocksdb_writestallinfo_t* info,
|
||||
size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
const rocksdb_writestallcondition_t* rocksdb_writestallinfo_cur(
|
||||
const rocksdb_writestallinfo_t* info) {
|
||||
return reinterpret_cast<const rocksdb_writestallcondition_t*>(
|
||||
&info->rep.condition.cur);
|
||||
}
|
||||
|
||||
const rocksdb_writestallcondition_t* rocksdb_writestallinfo_prev(
|
||||
const rocksdb_writestallinfo_t* info) {
|
||||
return reinterpret_cast<const rocksdb_writestallcondition_t*>(
|
||||
&info->rep.condition.prev);
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'JobInfo metadata simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_jobinfo_metadata_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_jobinfo_metadata_subset.cc.inc
|
||||
|
||||
/* JobInfo metadata simple */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t rocksdb_compactionjobinfo_input_files_count(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t rocksdb_compactionjobinfo_output_files_count(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_compactionjobinfo_elapsed_micros(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_compactionjobinfo_num_corrupt_keys(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_compactionjobinfo_input_records(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_compactionjobinfo_output_records(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_compactionjobinfo_total_input_bytes(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compactionjobinfo_total_output_bytes(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t rocksdb_compactionjobinfo_num_input_files(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t
|
||||
rocksdb_compactionjobinfo_num_input_files_at_output_level(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_writestallinfo_cf_name(
|
||||
const rocksdb_writestallinfo_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const rocksdb_writestallcondition_t*
|
||||
rocksdb_writestallinfo_cur(const rocksdb_writestallinfo_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const rocksdb_writestallcondition_t*
|
||||
rocksdb_writestallinfo_prev(const rocksdb_writestallinfo_t* info);
|
||||
@@ -1,532 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/auto_simple_bindings.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Sources:
|
||||
// - include/rocksdb/compaction_job_stats.h
|
||||
// - include/rocksdb/listener.h
|
||||
// - include/rocksdb/table_properties.h
|
||||
// - tools/c_api_gen/auto_simple_bindings_blocklist.json
|
||||
// - include/rocksdb/c.h
|
||||
// - tools/c_api_gen/c_base.cc
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/auto_simple_bindings.py
|
||||
|
||||
// Output group: Auto-discovered metadata view structs simple
|
||||
|
||||
/* TableProperties */
|
||||
|
||||
uint64_t rocksdb_table_properties_orig_file_number(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.orig_file_number;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_data_size(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.data_size;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_uncompressed_data_size(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.uncompressed_data_size;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_index_size(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.index_size;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_index_partitions(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.index_partitions;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_top_level_index_size(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.top_level_index_size;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_index_key_is_user_key(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.index_key_is_user_key;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_index_value_is_delta_encoded(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.index_value_is_delta_encoded;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_udi_is_primary_index(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.udi_is_primary_index;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_filter_size(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.filter_size;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_raw_key_size(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.raw_key_size;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_raw_value_size(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.raw_value_size;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_num_data_blocks(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.num_data_blocks;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_num_data_blocks_compression_rejected(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.num_data_blocks_compression_rejected;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_num_data_blocks_compression_bypassed(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.num_data_blocks_compression_bypassed;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_num_uniform_blocks(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.num_uniform_blocks;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_num_entries(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.num_entries;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_num_filter_entries(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.num_filter_entries;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_num_deletions(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.num_deletions;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_num_merge_operands(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.num_merge_operands;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_num_range_deletions(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.num_range_deletions;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_format_version(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.format_version;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_fixed_key_len(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.fixed_key_len;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_column_family_id(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.column_family_id;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_oldest_ancestor_time(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.oldest_ancestor_time;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_creation_time(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.creation_time;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_oldest_key_time(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.oldest_key_time;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_newest_key_time(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.newest_key_time;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_file_creation_time(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.file_creation_time;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_slow_compression_estimated_data_size(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.slow_compression_estimated_data_size;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_fast_compression_estimated_data_size(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.fast_compression_estimated_data_size;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_tail_start_offset(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.tail_start_offset;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_user_defined_timestamps_persisted(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.user_defined_timestamps_persisted;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_key_largest_seqno(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.key_largest_seqno;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_key_smallest_seqno(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.key_smallest_seqno;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_data_block_restart_interval(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.data_block_restart_interval;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_index_block_restart_interval(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.index_block_restart_interval;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_separate_key_value_in_data_block(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.separate_key_value_in_data_block;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_table_properties_lsm_info_at_creation(
|
||||
const rocksdb_table_properties_t* props) {
|
||||
return props->rep.lsm_info_at_creation;
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_db_id(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.db_id.size();
|
||||
return props->rep.db_id.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_db_session_id(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.db_session_id.size();
|
||||
return props->rep.db_session_id.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_db_host_id(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.db_host_id.size();
|
||||
return props->rep.db_host_id.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_column_family_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.column_family_name.size();
|
||||
return props->rep.column_family_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_filter_policy_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.filter_policy_name.size();
|
||||
return props->rep.filter_policy_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_comparator_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.comparator_name.size();
|
||||
return props->rep.comparator_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_merge_operator_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.merge_operator_name.size();
|
||||
return props->rep.merge_operator_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_prefix_extractor_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.prefix_extractor_name.size();
|
||||
return props->rep.prefix_extractor_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_property_collectors_names(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.property_collectors_names.size();
|
||||
return props->rep.property_collectors_names.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_compression_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.compression_name.size();
|
||||
return props->rep.compression_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_compression_options(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.compression_options.size();
|
||||
return props->rep.compression_options.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_table_properties_seqno_to_time_mapping(
|
||||
const rocksdb_table_properties_t* props, size_t* size) {
|
||||
*size = props->rep.seqno_to_time_mapping.size();
|
||||
return props->rep.seqno_to_time_mapping.data();
|
||||
}
|
||||
|
||||
/* CompactionJobStats */
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_elapsed_micros(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.elapsed_micros;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_cpu_micros(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.cpu_micros;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_compaction_job_stats_has_accurate_num_input_records(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.has_accurate_num_input_records;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_num_input_records(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_input_records;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_num_blobs_read(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_blobs_read;
|
||||
}
|
||||
|
||||
size_t rocksdb_compaction_job_stats_num_input_files(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_input_files;
|
||||
}
|
||||
|
||||
size_t rocksdb_compaction_job_stats_num_input_files_trivially_moved(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_input_files_trivially_moved;
|
||||
}
|
||||
|
||||
size_t rocksdb_compaction_job_stats_num_input_files_at_output_level(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_input_files_at_output_level;
|
||||
}
|
||||
|
||||
size_t rocksdb_compaction_job_stats_num_filtered_input_files(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_filtered_input_files;
|
||||
}
|
||||
|
||||
size_t rocksdb_compaction_job_stats_num_filtered_input_files_at_output_level(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_filtered_input_files_at_output_level;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_num_output_records(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_output_records;
|
||||
}
|
||||
|
||||
size_t rocksdb_compaction_job_stats_num_output_files(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_output_files;
|
||||
}
|
||||
|
||||
size_t rocksdb_compaction_job_stats_num_output_files_blob(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_output_files_blob;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_compaction_job_stats_is_full_compaction(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.is_full_compaction;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_compaction_job_stats_is_manual_compaction(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.is_manual_compaction;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_compaction_job_stats_is_remote_compaction(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.is_remote_compaction;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_total_input_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.total_input_bytes;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_total_blob_bytes_read(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.total_blob_bytes_read;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_total_output_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.total_output_bytes;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_total_output_bytes_blob(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.total_output_bytes_blob;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_total_skipped_input_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.total_skipped_input_bytes;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_num_records_replaced(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_records_replaced;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_total_input_raw_key_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.total_input_raw_key_bytes;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_total_input_raw_value_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.total_input_raw_value_bytes;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_num_input_deletion_records(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_input_deletion_records;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_num_expired_deletion_records(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_expired_deletion_records;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_num_corrupt_keys(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_corrupt_keys;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_file_write_nanos(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.file_write_nanos;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_file_range_sync_nanos(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.file_range_sync_nanos;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_file_fsync_nanos(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.file_fsync_nanos;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_file_prepare_write_nanos(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.file_prepare_write_nanos;
|
||||
}
|
||||
|
||||
const char* rocksdb_compaction_job_stats_smallest_output_key_prefix(
|
||||
const rocksdb_compaction_job_stats_t* stats, size_t* size) {
|
||||
*size = stats->rep.smallest_output_key_prefix.size();
|
||||
return stats->rep.smallest_output_key_prefix.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_compaction_job_stats_largest_output_key_prefix(
|
||||
const rocksdb_compaction_job_stats_t* stats, size_t* size) {
|
||||
*size = stats->rep.largest_output_key_prefix.size();
|
||||
return stats->rep.largest_output_key_prefix.data();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_num_single_del_fallthru(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_single_del_fallthru;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_job_stats_num_single_del_mismatch(
|
||||
const rocksdb_compaction_job_stats_t* stats) {
|
||||
return stats->rep.num_single_del_mismatch;
|
||||
}
|
||||
|
||||
/* CompactionFileInfo */
|
||||
|
||||
int rocksdb_compaction_file_info_level(
|
||||
const rocksdb_compaction_file_info_t* info) {
|
||||
return info->rep.level;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_file_info_file_number(
|
||||
const rocksdb_compaction_file_info_t* info) {
|
||||
return info->rep.file_number;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compaction_file_info_oldest_blob_file_number(
|
||||
const rocksdb_compaction_file_info_t* info) {
|
||||
return info->rep.oldest_blob_file_number;
|
||||
}
|
||||
|
||||
/* BlobFileAdditionInfo */
|
||||
|
||||
const char* rocksdb_blob_file_addition_info_blob_file_path(
|
||||
const rocksdb_blob_file_addition_info_t* info, size_t* size) {
|
||||
*size = info->rep.blob_file_path.size();
|
||||
return info->rep.blob_file_path.data();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_blob_file_addition_info_blob_file_number(
|
||||
const rocksdb_blob_file_addition_info_t* info) {
|
||||
return info->rep.blob_file_number;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_blob_file_addition_info_total_blob_count(
|
||||
const rocksdb_blob_file_addition_info_t* info) {
|
||||
return info->rep.total_blob_count;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_blob_file_addition_info_total_blob_bytes(
|
||||
const rocksdb_blob_file_addition_info_t* info) {
|
||||
return info->rep.total_blob_bytes;
|
||||
}
|
||||
|
||||
/* BlobFileGarbageInfo */
|
||||
|
||||
const char* rocksdb_blob_file_garbage_info_blob_file_path(
|
||||
const rocksdb_blob_file_garbage_info_t* info, size_t* size) {
|
||||
*size = info->rep.blob_file_path.size();
|
||||
return info->rep.blob_file_path.data();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_blob_file_garbage_info_blob_file_number(
|
||||
const rocksdb_blob_file_garbage_info_t* info) {
|
||||
return info->rep.blob_file_number;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_blob_file_garbage_info_garbage_blob_count(
|
||||
const rocksdb_blob_file_garbage_info_t* info) {
|
||||
return info->rep.garbage_blob_count;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_blob_file_garbage_info_garbage_blob_bytes(
|
||||
const rocksdb_blob_file_garbage_info_t* info) {
|
||||
return info->rep.garbage_blob_bytes;
|
||||
}
|
||||
@@ -1,385 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/auto_simple_bindings.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Sources:
|
||||
// - include/rocksdb/compaction_job_stats.h
|
||||
// - include/rocksdb/listener.h
|
||||
// - include/rocksdb/table_properties.h
|
||||
// - tools/c_api_gen/auto_simple_bindings_blocklist.json
|
||||
// - include/rocksdb/c.h
|
||||
// - tools/c_api_gen/c_base.cc
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/auto_simple_bindings.py
|
||||
|
||||
// Output group: Auto-discovered metadata view structs simple
|
||||
|
||||
/* TableProperties */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_orig_file_number(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_data_size(const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_uncompressed_data_size(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_index_size(const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_index_partitions(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_top_level_index_size(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_index_key_is_user_key(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_index_value_is_delta_encoded(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_udi_is_primary_index(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_filter_size(const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_raw_key_size(const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_raw_value_size(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_num_data_blocks(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_num_data_blocks_compression_rejected(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_num_data_blocks_compression_bypassed(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_num_uniform_blocks(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_num_entries(const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_num_filter_entries(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_num_deletions(const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_num_merge_operands(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_num_range_deletions(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_format_version(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_fixed_key_len(const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_column_family_id(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_oldest_ancestor_time(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_creation_time(const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_oldest_key_time(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_newest_key_time(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_file_creation_time(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_slow_compression_estimated_data_size(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_fast_compression_estimated_data_size(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_tail_start_offset(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_user_defined_timestamps_persisted(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_key_largest_seqno(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_table_properties_key_smallest_seqno(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_data_block_restart_interval(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_index_block_restart_interval(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_separate_key_value_in_data_block(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_table_properties_lsm_info_at_creation(
|
||||
const rocksdb_table_properties_t* props);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_table_properties_db_id(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_table_properties_db_session_id(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_table_properties_db_host_id(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_table_properties_column_family_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_table_properties_filter_policy_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_table_properties_comparator_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_table_properties_merge_operator_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_table_properties_prefix_extractor_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_table_properties_property_collectors_names(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_table_properties_compression_name(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_table_properties_compression_options(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_table_properties_seqno_to_time_mapping(
|
||||
const rocksdb_table_properties_t* props, size_t* size);
|
||||
|
||||
/* CompactionJobStats */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_compaction_job_stats_elapsed_micros(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_compaction_job_stats_cpu_micros(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_compaction_job_stats_has_accurate_num_input_records(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_num_input_records(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_compaction_job_stats_num_blobs_read(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t rocksdb_compaction_job_stats_num_input_files(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t
|
||||
rocksdb_compaction_job_stats_num_input_files_trivially_moved(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t
|
||||
rocksdb_compaction_job_stats_num_input_files_at_output_level(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t
|
||||
rocksdb_compaction_job_stats_num_filtered_input_files(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t
|
||||
rocksdb_compaction_job_stats_num_filtered_input_files_at_output_level(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_num_output_records(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t rocksdb_compaction_job_stats_num_output_files(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t
|
||||
rocksdb_compaction_job_stats_num_output_files_blob(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_compaction_job_stats_is_full_compaction(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_compaction_job_stats_is_manual_compaction(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_compaction_job_stats_is_remote_compaction(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_total_input_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_total_blob_bytes_read(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_total_output_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_total_output_bytes_blob(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_total_skipped_input_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_num_records_replaced(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_total_input_raw_key_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_total_input_raw_value_bytes(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_num_input_deletion_records(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_num_expired_deletion_records(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_num_corrupt_keys(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_file_write_nanos(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_file_range_sync_nanos(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_file_fsync_nanos(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_file_prepare_write_nanos(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_compaction_job_stats_smallest_output_key_prefix(
|
||||
const rocksdb_compaction_job_stats_t* stats, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_compaction_job_stats_largest_output_key_prefix(
|
||||
const rocksdb_compaction_job_stats_t* stats, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_num_single_del_fallthru(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_job_stats_num_single_del_mismatch(
|
||||
const rocksdb_compaction_job_stats_t* stats);
|
||||
|
||||
/* CompactionFileInfo */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_compaction_file_info_level(
|
||||
const rocksdb_compaction_file_info_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_compaction_file_info_file_number(
|
||||
const rocksdb_compaction_file_info_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compaction_file_info_oldest_blob_file_number(
|
||||
const rocksdb_compaction_file_info_t* info);
|
||||
|
||||
/* BlobFileAdditionInfo */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_blob_file_addition_info_blob_file_path(
|
||||
const rocksdb_blob_file_addition_info_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_blob_file_addition_info_blob_file_number(
|
||||
const rocksdb_blob_file_addition_info_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_blob_file_addition_info_total_blob_count(
|
||||
const rocksdb_blob_file_addition_info_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_blob_file_addition_info_total_blob_bytes(
|
||||
const rocksdb_blob_file_addition_info_t* info);
|
||||
|
||||
/* BlobFileGarbageInfo */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_blob_file_garbage_info_blob_file_path(
|
||||
const rocksdb_blob_file_garbage_info_t* info, size_t* size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_blob_file_garbage_info_blob_file_number(
|
||||
const rocksdb_blob_file_garbage_info_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_blob_file_garbage_info_garbage_blob_count(
|
||||
const rocksdb_blob_file_garbage_info_t* info);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_blob_file_garbage_info_garbage_blob_bytes(
|
||||
const rocksdb_blob_file_garbage_info_t* info);
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,88 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'Options simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_options_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_options_subset.cc.inc
|
||||
|
||||
/* Options simple */
|
||||
|
||||
void rocksdb_options_set_compression_options_zstd_max_train_bytes(
|
||||
rocksdb_options_t* opt, int zstd_max_train_bytes) {
|
||||
opt->rep.compression_opts.zstd_max_train_bytes = zstd_max_train_bytes;
|
||||
}
|
||||
|
||||
int rocksdb_options_get_compression_options_zstd_max_train_bytes(
|
||||
rocksdb_options_t* opt) {
|
||||
return opt->rep.compression_opts.zstd_max_train_bytes;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_compression_options_use_zstd_dict_trainer(
|
||||
rocksdb_options_t* opt, unsigned char use_zstd_dict_trainer) {
|
||||
opt->rep.compression_opts.use_zstd_dict_trainer = use_zstd_dict_trainer;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_options_get_compression_options_use_zstd_dict_trainer(
|
||||
rocksdb_options_t* opt) {
|
||||
return opt->rep.compression_opts.use_zstd_dict_trainer;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_compression_options_parallel_threads(
|
||||
rocksdb_options_t* opt, int value) {
|
||||
opt->rep.compression_opts.parallel_threads = value;
|
||||
}
|
||||
|
||||
int rocksdb_options_get_compression_options_parallel_threads(
|
||||
rocksdb_options_t* opt) {
|
||||
return opt->rep.compression_opts.parallel_threads;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_compression_options_max_dict_buffer_bytes(
|
||||
rocksdb_options_t* opt, uint64_t max_dict_buffer_bytes) {
|
||||
opt->rep.compression_opts.max_dict_buffer_bytes = max_dict_buffer_bytes;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_options_get_compression_options_max_dict_buffer_bytes(
|
||||
rocksdb_options_t* opt) {
|
||||
return opt->rep.compression_opts.max_dict_buffer_bytes;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
rocksdb_options_get_bottommost_compression_options_use_zstd_dict_trainer(
|
||||
rocksdb_options_t* opt) {
|
||||
return opt->rep.bottommost_compression_opts.use_zstd_dict_trainer;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_use_fsync(rocksdb_options_t* opt, int use_fsync) {
|
||||
opt->rep.use_fsync = use_fsync;
|
||||
}
|
||||
|
||||
int rocksdb_options_get_use_fsync(rocksdb_options_t* opt) {
|
||||
return opt->rep.use_fsync;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_disable_auto_compactions(rocksdb_options_t* opt,
|
||||
int disable) {
|
||||
opt->rep.disable_auto_compactions = disable;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_optimize_filters_for_hits(rocksdb_options_t* opt,
|
||||
int v) {
|
||||
opt->rep.optimize_filters_for_hits = v;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_report_bg_io_stats(rocksdb_options_t* opt, int v) {
|
||||
opt->rep.report_bg_io_stats = v;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'Options simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_options_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_options_subset.cc.inc
|
||||
|
||||
/* Options simple */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_options_set_compression_options_zstd_max_train_bytes(
|
||||
rocksdb_options_t* opt, int zstd_max_train_bytes);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int
|
||||
rocksdb_options_get_compression_options_zstd_max_train_bytes(
|
||||
rocksdb_options_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_options_set_compression_options_use_zstd_dict_trainer(
|
||||
rocksdb_options_t* opt, unsigned char use_zstd_dict_trainer);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_options_get_compression_options_use_zstd_dict_trainer(
|
||||
rocksdb_options_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_options_set_compression_options_parallel_threads(rocksdb_options_t* opt,
|
||||
int value);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int
|
||||
rocksdb_options_get_compression_options_parallel_threads(
|
||||
rocksdb_options_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_options_set_compression_options_max_dict_buffer_bytes(
|
||||
rocksdb_options_t* opt, uint64_t max_dict_buffer_bytes);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_options_get_compression_options_max_dict_buffer_bytes(
|
||||
rocksdb_options_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_options_get_bottommost_compression_options_use_zstd_dict_trainer(
|
||||
rocksdb_options_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_use_fsync(
|
||||
rocksdb_options_t* opt, int use_fsync);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_options_get_use_fsync(
|
||||
rocksdb_options_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_disable_auto_compactions(
|
||||
rocksdb_options_t* opt, int disable);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_optimize_filters_for_hits(
|
||||
rocksdb_options_t* opt, int v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_report_bg_io_stats(
|
||||
rocksdb_options_t* opt, int v);
|
||||
@@ -1,240 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/auto_simple_bindings.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Sources:
|
||||
// - include/rocksdb/options.h
|
||||
// - tools/c_api_gen/auto_simple_bindings_blocklist.json
|
||||
// - include/rocksdb/c.h
|
||||
// - tools/c_api_gen/c_base.cc
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/auto_simple_bindings.py
|
||||
|
||||
// Output group: Auto-discovered ReadOptions simple
|
||||
|
||||
/* ReadOptions */
|
||||
|
||||
void rocksdb_readoptions_set_deadline(rocksdb_readoptions_t* opt,
|
||||
uint64_t microseconds) {
|
||||
opt->rep.deadline = std::chrono::microseconds(microseconds);
|
||||
}
|
||||
|
||||
uint64_t rocksdb_readoptions_get_deadline(rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.deadline.count();
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_io_timeout(rocksdb_readoptions_t* opt,
|
||||
uint64_t microseconds) {
|
||||
opt->rep.io_timeout = std::chrono::microseconds(microseconds);
|
||||
}
|
||||
|
||||
uint64_t rocksdb_readoptions_get_io_timeout(rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.io_timeout.count();
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_read_tier(rocksdb_readoptions_t* opt, int v) {
|
||||
opt->rep.read_tier = static_cast<decltype(opt->rep.read_tier)>(v);
|
||||
}
|
||||
|
||||
int rocksdb_readoptions_get_read_tier(rocksdb_readoptions_t* opt) {
|
||||
return static_cast<int>(opt->rep.read_tier);
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_rate_limiter_priority(rocksdb_readoptions_t* opt,
|
||||
int v) {
|
||||
opt->rep.rate_limiter_priority =
|
||||
static_cast<decltype(opt->rep.rate_limiter_priority)>(v);
|
||||
}
|
||||
|
||||
int rocksdb_readoptions_get_rate_limiter_priority(rocksdb_readoptions_t* opt) {
|
||||
return static_cast<int>(opt->rep.rate_limiter_priority);
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_value_size_soft_limit(rocksdb_readoptions_t* opt,
|
||||
uint64_t v) {
|
||||
opt->rep.value_size_soft_limit = v;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_readoptions_get_value_size_soft_limit(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.value_size_soft_limit;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_verify_checksums(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.verify_checksums = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_verify_checksums(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.verify_checksums;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_fill_cache(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.fill_cache = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_fill_cache(rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.fill_cache;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_ignore_range_deletions(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.ignore_range_deletions = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_ignore_range_deletions(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.ignore_range_deletions;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_async_io(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.async_io = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_async_io(rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.async_io;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_optimize_multiget_for_io(
|
||||
rocksdb_readoptions_t* opt, unsigned char v) {
|
||||
opt->rep.optimize_multiget_for_io = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_optimize_multiget_for_io(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.optimize_multiget_for_io;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_readahead_size(rocksdb_readoptions_t* opt,
|
||||
size_t v) {
|
||||
opt->rep.readahead_size = v;
|
||||
}
|
||||
|
||||
size_t rocksdb_readoptions_get_readahead_size(rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.readahead_size;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_max_skippable_internal_keys(
|
||||
rocksdb_readoptions_t* opt, uint64_t v) {
|
||||
opt->rep.max_skippable_internal_keys = v;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_readoptions_get_max_skippable_internal_keys(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.max_skippable_internal_keys;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_tailing(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.tailing = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_tailing(rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.tailing;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_total_order_seek(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.total_order_seek = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_total_order_seek(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.total_order_seek;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_auto_prefix_mode(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.auto_prefix_mode = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_auto_prefix_mode(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.auto_prefix_mode;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_prefix_same_as_start(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.prefix_same_as_start = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_prefix_same_as_start(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.prefix_same_as_start;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_pin_data(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.pin_data = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_pin_data(rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.pin_data;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_adaptive_readahead(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.adaptive_readahead = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_adaptive_readahead(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.adaptive_readahead;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_background_purge_on_iterator_cleanup(
|
||||
rocksdb_readoptions_t* opt, unsigned char v) {
|
||||
opt->rep.background_purge_on_iterator_cleanup = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_background_purge_on_iterator_cleanup(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.background_purge_on_iterator_cleanup;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_auto_readahead_size(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.auto_readahead_size = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_auto_readahead_size(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.auto_readahead_size;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_allow_unprepared_value(rocksdb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.allow_unprepared_value = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_allow_unprepared_value(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.allow_unprepared_value;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_auto_refresh_iterator_with_snapshot(
|
||||
rocksdb_readoptions_t* opt, unsigned char v) {
|
||||
opt->rep.auto_refresh_iterator_with_snapshot = v;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_readoptions_get_auto_refresh_iterator_with_snapshot(
|
||||
rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.auto_refresh_iterator_with_snapshot;
|
||||
}
|
||||
|
||||
void rocksdb_readoptions_set_io_activity(rocksdb_readoptions_t* opt, int v) {
|
||||
opt->rep.io_activity = static_cast<decltype(opt->rep.io_activity)>(v);
|
||||
}
|
||||
|
||||
int rocksdb_readoptions_get_io_activity(rocksdb_readoptions_t* opt) {
|
||||
return static_cast<int>(opt->rep.io_activity);
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/auto_simple_bindings.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Sources:
|
||||
// - include/rocksdb/options.h
|
||||
// - tools/c_api_gen/auto_simple_bindings_blocklist.json
|
||||
// - include/rocksdb/c.h
|
||||
// - tools/c_api_gen/c_base.cc
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/auto_simple_bindings.py
|
||||
|
||||
// Output group: Auto-discovered ReadOptions simple
|
||||
|
||||
/* ReadOptions */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_deadline(
|
||||
rocksdb_readoptions_t* opt, uint64_t microseconds);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_readoptions_get_deadline(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_io_timeout(
|
||||
rocksdb_readoptions_t* opt, uint64_t microseconds);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_readoptions_get_io_timeout(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_read_tier(
|
||||
rocksdb_readoptions_t* opt, int v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_readoptions_get_read_tier(
|
||||
rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_rate_limiter_priority(
|
||||
rocksdb_readoptions_t* opt, int v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_readoptions_get_rate_limiter_priority(
|
||||
rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_value_size_soft_limit(
|
||||
rocksdb_readoptions_t* opt, uint64_t v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_readoptions_get_value_size_soft_limit(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_verify_checksums(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_verify_checksums(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_fill_cache(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char rocksdb_readoptions_get_fill_cache(
|
||||
rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_ignore_range_deletions(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_ignore_range_deletions(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_async_io(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char rocksdb_readoptions_get_async_io(
|
||||
rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_readoptions_set_optimize_multiget_for_io(rocksdb_readoptions_t* opt,
|
||||
unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_optimize_multiget_for_io(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_readahead_size(
|
||||
rocksdb_readoptions_t* opt, size_t v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API size_t
|
||||
rocksdb_readoptions_get_readahead_size(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_readoptions_set_max_skippable_internal_keys(rocksdb_readoptions_t* opt,
|
||||
uint64_t v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_readoptions_get_max_skippable_internal_keys(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_tailing(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char rocksdb_readoptions_get_tailing(
|
||||
rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_total_order_seek(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_total_order_seek(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_auto_prefix_mode(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_auto_prefix_mode(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_prefix_same_as_start(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_prefix_same_as_start(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_pin_data(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char rocksdb_readoptions_get_pin_data(
|
||||
rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_adaptive_readahead(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_adaptive_readahead(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_readoptions_set_background_purge_on_iterator_cleanup(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_background_purge_on_iterator_cleanup(
|
||||
rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_auto_readahead_size(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_auto_readahead_size(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_allow_unprepared_value(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_allow_unprepared_value(rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_readoptions_set_auto_refresh_iterator_with_snapshot(
|
||||
rocksdb_readoptions_t* opt, unsigned char v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_readoptions_get_auto_refresh_iterator_with_snapshot(
|
||||
rocksdb_readoptions_t* opt);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_io_activity(
|
||||
rocksdb_readoptions_t* opt, int v);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_readoptions_get_io_activity(
|
||||
rocksdb_readoptions_t* opt);
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,375 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'DB data operations'
|
||||
// --section 'WriteBatch' --section 'Transaction'
|
||||
// --section 'TransactionDB simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_subset.cc.inc
|
||||
|
||||
/* DB data operations */
|
||||
|
||||
void rocksdb_put(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr,
|
||||
db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_put_cf(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, const char* val,
|
||||
size_t vallen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Put(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete_cf(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Delete(options->rep, column_family->rep,
|
||||
Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_merge(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, const char* val,
|
||||
size_t vallen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Merge(options->rep, Slice(key, keylen),
|
||||
Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_merge_cf(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, const char* val,
|
||||
size_t vallen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Merge(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_write(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_t* batch, char** errptr) {
|
||||
SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
|
||||
}
|
||||
|
||||
void rocksdb_put_with_ts(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, const char* ts,
|
||||
size_t tslen, const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->Put(options->rep, Slice(key, keylen),
|
||||
Slice(ts, tslen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_put_cf_with_ts(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, const char* ts,
|
||||
size_t tslen, const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr,
|
||||
db->rep->Put(options->rep, column_family->rep, Slice(key, keylen),
|
||||
Slice(ts, tslen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete_with_ts(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, const char* ts,
|
||||
size_t tslen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen),
|
||||
Slice(ts, tslen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete_cf_with_ts(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, const char* ts,
|
||||
size_t tslen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Delete(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(ts, tslen)));
|
||||
}
|
||||
|
||||
void rocksdb_singledelete(rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, char** errptr) {
|
||||
SaveError(errptr, db->rep->SingleDelete(options->rep, Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_singledelete_cf(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen, char** errptr) {
|
||||
SaveError(errptr, db->rep->SingleDelete(options->rep, column_family->rep,
|
||||
Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_singledelete_with_ts(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t keylen,
|
||||
const char* ts, size_t tslen, char** errptr) {
|
||||
SaveError(errptr, db->rep->SingleDelete(options->rep, Slice(key, keylen),
|
||||
Slice(ts, tslen)));
|
||||
}
|
||||
|
||||
void rocksdb_singledelete_cf_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr) {
|
||||
SaveError(errptr,
|
||||
db->rep->SingleDelete(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(ts, tslen)));
|
||||
}
|
||||
|
||||
void rocksdb_delete_range_cf(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* start_key, size_t start_key_len,
|
||||
const char* end_key, size_t end_key_len,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->DeleteRange(options->rep, column_family->rep,
|
||||
Slice(start_key, start_key_len),
|
||||
Slice(end_key, end_key_len)));
|
||||
}
|
||||
|
||||
void rocksdb_flush(rocksdb_t* db, const rocksdb_flushoptions_t* options,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->Flush(options->rep));
|
||||
}
|
||||
|
||||
void rocksdb_flush_cf(rocksdb_t* db, const rocksdb_flushoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->Flush(options->rep, column_family->rep));
|
||||
}
|
||||
|
||||
void rocksdb_flush_wal(rocksdb_t* db, unsigned char sync, char** errptr) {
|
||||
SaveError(errptr, db->rep->FlushWAL(sync));
|
||||
}
|
||||
|
||||
void rocksdb_pause_background_work(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->PauseBackgroundWork());
|
||||
}
|
||||
|
||||
void rocksdb_continue_background_work(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->ContinueBackgroundWork());
|
||||
}
|
||||
|
||||
void rocksdb_disable_file_deletions(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->DisableFileDeletions());
|
||||
}
|
||||
|
||||
void rocksdb_enable_file_deletions(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->EnableFileDeletions());
|
||||
}
|
||||
|
||||
void rocksdb_verify_checksum(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->VerifyChecksum());
|
||||
}
|
||||
|
||||
void rocksdb_verify_file_checksums(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->VerifyFileChecksums(ReadOptions()));
|
||||
}
|
||||
|
||||
void rocksdb_destroy_db(const rocksdb_options_t* options, const char* name,
|
||||
char** errptr) {
|
||||
SaveError(errptr, DestroyDB(name, options->rep));
|
||||
}
|
||||
|
||||
void rocksdb_repair_db(const rocksdb_options_t* options, const char* name,
|
||||
char** errptr) {
|
||||
SaveError(errptr, RepairDB(name, options->rep));
|
||||
}
|
||||
|
||||
/* WriteBatch */
|
||||
|
||||
void rocksdb_writebatch_clear(rocksdb_writebatch_t* b) { b->rep.Clear(); }
|
||||
|
||||
void rocksdb_writebatch_put(rocksdb_writebatch_t* b, const char* key,
|
||||
size_t klen, const char* val, size_t vlen) {
|
||||
b->rep.Put(Slice(key, klen), Slice(val, vlen));
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_put_cf(rocksdb_writebatch_t* b,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen) {
|
||||
b->rep.Put(column_family->rep, Slice(key, klen), Slice(val, vlen));
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_delete(rocksdb_writebatch_t* b, const char* key,
|
||||
size_t klen) {
|
||||
b->rep.Delete(Slice(key, klen));
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_put_log_data(rocksdb_writebatch_t* b, const char* blob,
|
||||
size_t len) {
|
||||
b->rep.PutLogData(Slice(blob, len));
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_set_save_point(rocksdb_writebatch_t* b) {
|
||||
b->rep.SetSavePoint();
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_rollback_to_save_point(rocksdb_writebatch_t* b,
|
||||
char** errptr) {
|
||||
SaveError(errptr, b->rep.RollbackToSavePoint());
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_pop_save_point(rocksdb_writebatch_t* b, char** errptr) {
|
||||
SaveError(errptr, b->rep.PopSavePoint());
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_verify_checksum(rocksdb_writebatch_t* b,
|
||||
char** errptr) {
|
||||
SaveError(errptr, b->rep.VerifyChecksum());
|
||||
}
|
||||
|
||||
/* Transaction */
|
||||
|
||||
void rocksdb_transaction_put(rocksdb_transaction_t* txn, const char* key,
|
||||
size_t klen, const char* val, size_t vlen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn->rep->Put(Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_put_cf(rocksdb_transaction_t* txn,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Put(column_family->rep, Slice(key, klen),
|
||||
Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_merge(rocksdb_transaction_t* txn, const char* key,
|
||||
size_t klen, const char* val, size_t vlen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn->rep->Merge(Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_merge_cf(rocksdb_transaction_t* txn,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Merge(column_family->rep, Slice(key, klen),
|
||||
Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_delete(rocksdb_transaction_t* txn, const char* key,
|
||||
size_t klen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Delete(Slice(key, klen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_delete_cf(
|
||||
rocksdb_transaction_t* txn, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Delete(column_family->rep, Slice(key, klen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_commit(rocksdb_transaction_t* txn, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Commit());
|
||||
}
|
||||
|
||||
void rocksdb_transaction_rollback(rocksdb_transaction_t* txn, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Rollback());
|
||||
}
|
||||
|
||||
void rocksdb_transaction_put_log_data(rocksdb_transaction_t* txn,
|
||||
const char* blob, size_t len) {
|
||||
txn->rep->PutLogData(Slice(blob, len));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_set_savepoint(rocksdb_transaction_t* txn) {
|
||||
txn->rep->SetSavePoint();
|
||||
}
|
||||
|
||||
void rocksdb_transaction_rollback_to_savepoint(rocksdb_transaction_t* txn,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn->rep->RollbackToSavePoint());
|
||||
}
|
||||
|
||||
/* TransactionDB simple */
|
||||
|
||||
void rocksdb_transactiondb_put(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr,
|
||||
txn_db->rep->Put(options->rep, Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_put_cf(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen,
|
||||
const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Put(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_write(rocksdb_transactiondb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_t* batch, char** errptr) {
|
||||
SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_merge(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Merge(options->rep, Slice(key, klen),
|
||||
Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_merge_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key, size_t klen,
|
||||
const char* val, size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Merge(options->rep, column_family->rep,
|
||||
Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_delete(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Delete(options->rep, Slice(key, klen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_delete_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Delete(options->rep, column_family->rep,
|
||||
Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_flush_wal(rocksdb_transactiondb_t* txn_db,
|
||||
unsigned char sync, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->FlushWAL(sync));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_flush(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_flushoptions_t* options,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Flush(options->rep));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_flush_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_flushoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Flush(options->rep, column_family->rep));
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'DB data operations'
|
||||
// --section 'WriteBatch' --section 'Transaction'
|
||||
// --section 'TransactionDB simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_subset.cc.inc
|
||||
|
||||
/* DB data operations */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_put(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_put_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_merge(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_merge_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_write(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_t* batch, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_put_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, const char* val, size_t vallen,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_put_cf_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, const char* val, size_t vallen,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete_cf_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_singledelete(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_singledelete_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_singledelete_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_singledelete_cf_with_ts(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* ts, size_t tslen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_delete_range_cf(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* start_key,
|
||||
size_t start_key_len, const char* end_key, size_t end_key_len,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_flush(
|
||||
rocksdb_t* db, const rocksdb_flushoptions_t* options, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_flush_cf(
|
||||
rocksdb_t* db, const rocksdb_flushoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_flush_wal(rocksdb_t* db,
|
||||
unsigned char sync,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_pause_background_work(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_continue_background_work(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_disable_file_deletions(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_enable_file_deletions(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_verify_checksum(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_verify_file_checksums(rocksdb_t* db,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_destroy_db(
|
||||
const rocksdb_options_t* options, const char* name, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_repair_db(
|
||||
const rocksdb_options_t* options, const char* name, char** errptr);
|
||||
|
||||
/* WriteBatch */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_clear(
|
||||
rocksdb_writebatch_t* b);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_put(rocksdb_writebatch_t* b,
|
||||
const char* key,
|
||||
size_t klen,
|
||||
const char* val,
|
||||
size_t vlen);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_put_cf(
|
||||
rocksdb_writebatch_t* b, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val, size_t vlen);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_delete(
|
||||
rocksdb_writebatch_t* b, const char* key, size_t klen);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_put_log_data(
|
||||
rocksdb_writebatch_t* b, const char* blob, size_t len);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_set_save_point(
|
||||
rocksdb_writebatch_t* b);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_rollback_to_save_point(
|
||||
rocksdb_writebatch_t* b, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_pop_save_point(
|
||||
rocksdb_writebatch_t* b, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_verify_checksum(
|
||||
rocksdb_writebatch_t* b, char** errptr);
|
||||
|
||||
/* Transaction */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_put(
|
||||
rocksdb_transaction_t* txn, const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_put_cf(
|
||||
rocksdb_transaction_t* txn, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_merge(
|
||||
rocksdb_transaction_t* txn, const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_merge_cf(
|
||||
rocksdb_transaction_t* txn, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_delete(
|
||||
rocksdb_transaction_t* txn, const char* key, size_t klen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_delete_cf(
|
||||
rocksdb_transaction_t* txn, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_commit(
|
||||
rocksdb_transaction_t* txn, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_rollback(
|
||||
rocksdb_transaction_t* txn, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_put_log_data(
|
||||
rocksdb_transaction_t* txn, const char* blob, size_t len);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_set_savepoint(
|
||||
rocksdb_transaction_t* txn);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_rollback_to_savepoint(
|
||||
rocksdb_transaction_t* txn, char** errptr);
|
||||
|
||||
/* TransactionDB simple */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_put(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_put_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_write(
|
||||
rocksdb_transactiondb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_t* batch, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_merge(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_merge_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key, size_t klen,
|
||||
const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_delete(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_delete_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_flush_wal(
|
||||
rocksdb_transactiondb_t* txn_db, unsigned char sync, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_flush(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_flushoptions_t* options,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_flush_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_flushoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, char** errptr);
|
||||
@@ -1,81 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'Transaction'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_transaction_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_transaction_subset.cc.inc
|
||||
|
||||
/* Transaction */
|
||||
|
||||
void rocksdb_transaction_put(rocksdb_transaction_t* txn, const char* key,
|
||||
size_t klen, const char* val, size_t vlen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn->rep->Put(Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_put_cf(rocksdb_transaction_t* txn,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Put(column_family->rep, Slice(key, klen),
|
||||
Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_merge(rocksdb_transaction_t* txn, const char* key,
|
||||
size_t klen, const char* val, size_t vlen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn->rep->Merge(Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_merge_cf(rocksdb_transaction_t* txn,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Merge(column_family->rep, Slice(key, klen),
|
||||
Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_delete(rocksdb_transaction_t* txn, const char* key,
|
||||
size_t klen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Delete(Slice(key, klen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_delete_cf(
|
||||
rocksdb_transaction_t* txn, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Delete(column_family->rep, Slice(key, klen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_commit(rocksdb_transaction_t* txn, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Commit());
|
||||
}
|
||||
|
||||
void rocksdb_transaction_rollback(rocksdb_transaction_t* txn, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Rollback());
|
||||
}
|
||||
|
||||
void rocksdb_transaction_put_log_data(rocksdb_transaction_t* txn,
|
||||
const char* blob, size_t len) {
|
||||
txn->rep->PutLogData(Slice(blob, len));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_set_savepoint(rocksdb_transaction_t* txn) {
|
||||
txn->rep->SetSavePoint();
|
||||
}
|
||||
|
||||
void rocksdb_transaction_rollback_to_savepoint(rocksdb_transaction_t* txn,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn->rep->RollbackToSavePoint());
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'Transaction'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_transaction_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_transaction_subset.cc.inc
|
||||
|
||||
/* Transaction */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_put(
|
||||
rocksdb_transaction_t* txn, const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_put_cf(
|
||||
rocksdb_transaction_t* txn, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_merge(
|
||||
rocksdb_transaction_t* txn, const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_merge_cf(
|
||||
rocksdb_transaction_t* txn, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_delete(
|
||||
rocksdb_transaction_t* txn, const char* key, size_t klen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_delete_cf(
|
||||
rocksdb_transaction_t* txn, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_commit(
|
||||
rocksdb_transaction_t* txn, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_rollback(
|
||||
rocksdb_transaction_t* txn, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_put_log_data(
|
||||
rocksdb_transaction_t* txn, const char* blob, size_t len);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_set_savepoint(
|
||||
rocksdb_transaction_t* txn);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transaction_rollback_to_savepoint(
|
||||
rocksdb_transaction_t* txn, char** errptr);
|
||||
@@ -1,91 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'TransactionDB simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_transactiondb_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_transactiondb_subset.cc.inc
|
||||
|
||||
/* TransactionDB simple */
|
||||
|
||||
void rocksdb_transactiondb_put(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr,
|
||||
txn_db->rep->Put(options->rep, Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_put_cf(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen,
|
||||
const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Put(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_write(rocksdb_transactiondb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_t* batch, char** errptr) {
|
||||
SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_merge(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Merge(options->rep, Slice(key, klen),
|
||||
Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_merge_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key, size_t klen,
|
||||
const char* val, size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Merge(options->rep, column_family->rep,
|
||||
Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_delete(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Delete(options->rep, Slice(key, klen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_delete_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Delete(options->rep, column_family->rep,
|
||||
Slice(key, keylen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_flush_wal(rocksdb_transactiondb_t* txn_db,
|
||||
unsigned char sync, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->FlushWAL(sync));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_flush(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_flushoptions_t* options,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Flush(options->rep));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_flush_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_flushoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Flush(options->rep, column_family->rep));
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'TransactionDB simple'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_transactiondb_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_transactiondb_subset.cc.inc
|
||||
|
||||
/* TransactionDB simple */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_put(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_put_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_write(
|
||||
rocksdb_transactiondb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_t* batch, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_merge(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_merge_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key, size_t klen,
|
||||
const char* val, size_t vlen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_delete(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_delete_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_flush_wal(
|
||||
rocksdb_transactiondb_t* txn_db, unsigned char sync, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_flush(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_flushoptions_t* options,
|
||||
char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_transactiondb_flush_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_flushoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, char** errptr);
|
||||
@@ -1,62 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'WriteBatch'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_writebatch_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_writebatch_subset.cc.inc
|
||||
|
||||
/* WriteBatch */
|
||||
|
||||
void rocksdb_writebatch_clear(rocksdb_writebatch_t* b) { b->rep.Clear(); }
|
||||
|
||||
void rocksdb_writebatch_put(rocksdb_writebatch_t* b, const char* key,
|
||||
size_t klen, const char* val, size_t vlen) {
|
||||
b->rep.Put(Slice(key, klen), Slice(val, vlen));
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_put_cf(rocksdb_writebatch_t* b,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen) {
|
||||
b->rep.Put(column_family->rep, Slice(key, klen), Slice(val, vlen));
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_delete(rocksdb_writebatch_t* b, const char* key,
|
||||
size_t klen) {
|
||||
b->rep.Delete(Slice(key, klen));
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_put_log_data(rocksdb_writebatch_t* b, const char* blob,
|
||||
size_t len) {
|
||||
b->rep.PutLogData(Slice(blob, len));
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_set_save_point(rocksdb_writebatch_t* b) {
|
||||
b->rep.SetSavePoint();
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_rollback_to_save_point(rocksdb_writebatch_t* b,
|
||||
char** errptr) {
|
||||
SaveError(errptr, b->rep.RollbackToSavePoint());
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_pop_save_point(rocksdb_writebatch_t* b, char** errptr) {
|
||||
SaveError(errptr, b->rep.PopSavePoint());
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_verify_checksum(rocksdb_writebatch_t* b,
|
||||
char** errptr) {
|
||||
SaveError(errptr, b->rep.VerifyChecksum());
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// @generated
|
||||
// -----------------------------------------------------------------------------
|
||||
// Auto-generated by tools/c_api_gen/generate_c_api.py.
|
||||
// DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Source: tools/c_api_gen/spec.json
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// To regenerate this file:
|
||||
// python3 tools/c_api_gen/generate_c_api.py
|
||||
// --spec tools/c_api_gen/spec.json --section 'WriteBatch'
|
||||
// --header-out
|
||||
// c_api_gen/c_generated_writebatch_subset.h.inc
|
||||
// --source-out
|
||||
// c_api_gen/c_generated_writebatch_subset.cc.inc
|
||||
|
||||
/* WriteBatch */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_clear(
|
||||
rocksdb_writebatch_t* b);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_put(rocksdb_writebatch_t* b,
|
||||
const char* key,
|
||||
size_t klen,
|
||||
const char* val,
|
||||
size_t vlen);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_put_cf(
|
||||
rocksdb_writebatch_t* b, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val, size_t vlen);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_delete(
|
||||
rocksdb_writebatch_t* b, const char* key, size_t klen);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_put_log_data(
|
||||
rocksdb_writebatch_t* b, const char* blob, size_t len);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_set_save_point(
|
||||
rocksdb_writebatch_t* b);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_rollback_to_save_point(
|
||||
rocksdb_writebatch_t* b, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_pop_save_point(
|
||||
rocksdb_writebatch_t* b, char** errptr);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_verify_checksum(
|
||||
rocksdb_writebatch_t* b, char** errptr);
|
||||
Vendored
+1
-2
@@ -276,8 +276,7 @@ struct KeyGen {
|
||||
// location, so we fix hash bits starting at the bottom of that word.
|
||||
auto hi_hash = uint64_t{0x9e3779b97f4a7c13U} ^
|
||||
(key_hash << 1 << (FLAGS_degenerate_hash_bits - 1));
|
||||
uint64_t un_hi;
|
||||
uint64_t un_lo;
|
||||
uint64_t un_hi, un_lo;
|
||||
BijectiveUnhash2x64(hi_hash, key_hash, &un_hi, &un_lo);
|
||||
un_lo ^= BitwiseAnd(FLAGS_seed, INT32_MAX);
|
||||
EncodeFixed64(key_data, un_lo);
|
||||
|
||||
Vendored
-18
@@ -127,24 +127,6 @@ class OffsetableCacheKey : private CacheKey {
|
||||
return CacheKey(file_num_etc64_, offset_etc64_ ^ offset);
|
||||
}
|
||||
|
||||
// Construct a CacheKey for a record located at byte `offset` within a file in
|
||||
// which every distinct cached region is at least 5 bytes long. The low two
|
||||
// offset bits are dropped, which is collision-free under that >= 5-byte (>= 4
|
||||
// would suffice) guarantee and lets different kinds of records in the same
|
||||
// file share a single keyspace without colliding.
|
||||
//
|
||||
// This is the canonical cache-key scheme for byte-offset records that carry
|
||||
// the block-based "min 5 byte" guarantee: block-based SST blocks (see
|
||||
// BlockBasedTable::GetCacheKey) and SimpleGen2Blob records (which always
|
||||
// include a >= 5-byte trailer; see db/blob/blob_gen2_format.h). Because both
|
||||
// use this same function, an SST's data blocks and its embedded blob records
|
||||
// never collide even when the block cache and blob cache are the same cache.
|
||||
// Keeping a single implementation here avoids a divergence bug that would
|
||||
// silently alias the two keyspaces.
|
||||
inline CacheKey WithOffsetForMinSizeRecord(uint64_t offset) const {
|
||||
return WithOffset(offset >> 2);
|
||||
}
|
||||
|
||||
// The "common prefix" is a shared prefix for all the returned CacheKeys.
|
||||
// It is specific to the file but the same for all offsets within the file.
|
||||
static constexpr size_t kCommonPrefixSize = 8;
|
||||
|
||||
Vendored
+2
-7
@@ -32,9 +32,9 @@ class CacheReservationManager {
|
||||
// for an incremental amount of memory used (i.e, incremental_memory_used)
|
||||
class CacheReservationHandle {
|
||||
public:
|
||||
virtual ~CacheReservationHandle() = default;
|
||||
virtual ~CacheReservationHandle() {}
|
||||
};
|
||||
virtual ~CacheReservationManager() = default;
|
||||
virtual ~CacheReservationManager() {}
|
||||
virtual Status UpdateCacheReservation(std::size_t new_memory_used) = 0;
|
||||
// TODO(hx235): replace the usage of
|
||||
// `UpdateCacheReservation(memory_used_delta, increase)` with
|
||||
@@ -235,11 +235,6 @@ class ConcurrentCacheReservationManager
|
||||
cache_res_mgr_ = cache_res_mgr;
|
||||
cache_res_handle_ = std::move(cache_res_handle);
|
||||
}
|
||||
// No copying allowed
|
||||
CacheReservationHandle(const CacheReservationHandle&) = delete;
|
||||
CacheReservationHandle& operator=(const CacheReservationHandle&) = delete;
|
||||
CacheReservationHandle(CacheReservationHandle&&) = delete;
|
||||
CacheReservationHandle& operator=(CacheReservationHandle&&) = delete;
|
||||
|
||||
~CacheReservationHandle() override {
|
||||
std::lock_guard<std::mutex> lock(cache_res_mgr_->cache_res_mgr_mu_);
|
||||
|
||||
+2
-2
@@ -407,8 +407,8 @@ TEST(CacheReservationHandleTest, HandleTest) {
|
||||
std::size_t mem_used = 0;
|
||||
const std::size_t incremental_mem_used_handle_1 = 1 * kSizeDummyEntry;
|
||||
const std::size_t incremental_mem_used_handle_2 = 2 * kSizeDummyEntry;
|
||||
std::unique_ptr<CacheReservationManager::CacheReservationHandle> handle_1;
|
||||
std::unique_ptr<CacheReservationManager::CacheReservationHandle> handle_2;
|
||||
std::unique_ptr<CacheReservationManager::CacheReservationHandle> handle_1,
|
||||
handle_2;
|
||||
|
||||
// To test consecutive CacheReservationManager::MakeCacheReservation works
|
||||
// correctly in terms of returning the handle as well as updating cache
|
||||
|
||||
Vendored
+4
-13
@@ -975,8 +975,7 @@ void FixedHyperClockTable::Erase(const UniqueId64x2& hashed_key) {
|
||||
// Could be multiple entries in rare cases. Erase them all.
|
||||
// Optimistically increment acquire counter
|
||||
auto add_acquire = AcquireCounter::PlusTransformPromiseNoOverflow(1);
|
||||
SlotMeta old_meta;
|
||||
SlotMeta meta;
|
||||
SlotMeta old_meta, meta;
|
||||
h->meta.Apply(add_acquire, &old_meta, &meta);
|
||||
// Check if it's an entry visible to lookups
|
||||
if (meta.IsVisible()) {
|
||||
@@ -1739,8 +1738,7 @@ inline bool MatchAndRef(const UniqueId64x2* hashed_key, const ClockHandle& h,
|
||||
// Must be at least something to match
|
||||
assert(hashed_key || shift > 0);
|
||||
|
||||
SlotMeta old_meta;
|
||||
SlotMeta new_meta;
|
||||
SlotMeta old_meta, new_meta;
|
||||
// (Optimistically) increment acquire counter.
|
||||
auto add_acquire = AcquireCounter::PlusTransformPromiseNoOverflow(1);
|
||||
h.meta.Apply(add_acquire, &old_meta, &new_meta);
|
||||
@@ -1858,12 +1856,6 @@ class AutoHyperClockTable::ChainRewriteLock {
|
||||
assert(saved_head_.IsLocked());
|
||||
}
|
||||
|
||||
// No copying allowed
|
||||
ChainRewriteLock(const ChainRewriteLock&) = delete;
|
||||
ChainRewriteLock& operator=(const ChainRewriteLock&) = delete;
|
||||
ChainRewriteLock(ChainRewriteLock&&) = delete;
|
||||
ChainRewriteLock& operator=(ChainRewriteLock&&) = delete;
|
||||
|
||||
~ChainRewriteLock() {
|
||||
if (!IsEnd()) {
|
||||
// Release lock
|
||||
@@ -3116,7 +3108,7 @@ AutoHyperClockTable::HandleImpl* AutoHyperClockTable::Lookup(
|
||||
HandleImpl* const arr = array_.Get();
|
||||
NextWithShift next_with_shift = arr[home].head_next_with_shift.LoadRelaxed();
|
||||
for (size_t i = 0; !next_with_shift.IsEnd() && i < 10; ++i) {
|
||||
HandleImpl* h = &arr[next_with_shift.GetNext()];
|
||||
HandleImpl* h = &arr[next_with_shift.IsEnd()];
|
||||
// Attempt cheap key match without acquiring a read ref. This could give a
|
||||
// false positive, which is re-checked after acquiring read ref, or false
|
||||
// negative, which is re-checked in the full Lookup. Also, this is a
|
||||
@@ -3130,8 +3122,7 @@ AutoHyperClockTable::HandleImpl* AutoHyperClockTable::Lookup(
|
||||
if (probably_equal) {
|
||||
// Increment acquire counter for definitive check
|
||||
auto add_acquire = AcquireCounter::PlusTransformPromiseNoOverflow(1);
|
||||
SlotMeta old_meta;
|
||||
SlotMeta new_meta;
|
||||
SlotMeta old_meta, new_meta;
|
||||
h->meta.Apply(add_acquire, &old_meta, &new_meta);
|
||||
// Check if it's a referencable (sharable) entry
|
||||
if (LIKELY(old_meta.IsShareable())) {
|
||||
|
||||
Vendored
-4
@@ -29,10 +29,6 @@ class CompressedSecondaryCacheResultHandle : public SecondaryCacheResultHandle {
|
||||
const CompressedSecondaryCacheResultHandle&) = delete;
|
||||
CompressedSecondaryCacheResultHandle& operator=(
|
||||
const CompressedSecondaryCacheResultHandle&) = delete;
|
||||
CompressedSecondaryCacheResultHandle(CompressedSecondaryCacheResultHandle&&) =
|
||||
delete;
|
||||
CompressedSecondaryCacheResultHandle& operator=(
|
||||
CompressedSecondaryCacheResultHandle&&) = delete;
|
||||
|
||||
bool IsReady() override { return true; }
|
||||
|
||||
|
||||
+1
-2
@@ -508,8 +508,7 @@ class CompressedSecondaryCacheTestBase : public testing::Test,
|
||||
std::string str1 = rnd.RandomString(1001);
|
||||
auto item1 = std::make_unique<TestItem>(str1.data(), str1.length());
|
||||
ASSERT_OK(cache->Insert(key1, item1.get(), GetHelper(), str1.length()));
|
||||
// Appease clang-analyze "potential memory leak"
|
||||
[[maybe_unused]] TestItem* released_item1 = item1.release();
|
||||
item1.release(); // Appease clang-analyze "potential memory leak"
|
||||
|
||||
Cache::Handle* handle;
|
||||
handle = cache->Lookup(key2, nullptr, this, Cache::Priority::LOW);
|
||||
|
||||
Vendored
+1
-2
@@ -1366,8 +1366,7 @@ TEST_P(BasicSecondaryCacheTest, BasicFailTest) {
|
||||
// str1.length()).IsInvalidArgument());
|
||||
ASSERT_OK(
|
||||
cache->Insert(k1.AsSlice(), item1.get(), GetHelper(), str1.length()));
|
||||
// Appease clang-analyze "potential memory leak"
|
||||
[[maybe_unused]] TestItem* released_item1 = item1.release();
|
||||
item1.release(); // Appease clang-analyze "potential memory leak"
|
||||
|
||||
Cache::Handle* handle;
|
||||
handle = cache->Lookup(k2.AsSlice(), nullptr, /*context*/ this,
|
||||
|
||||
Vendored
+3
-9
@@ -90,7 +90,7 @@ class CacheShardBase {
|
||||
class ShardedCacheBase : public Cache {
|
||||
public:
|
||||
explicit ShardedCacheBase(const ShardedCacheOptions& opts);
|
||||
~ShardedCacheBase() override = default;
|
||||
virtual ~ShardedCacheBase() = default;
|
||||
|
||||
int GetNumShardBits() const;
|
||||
uint32_t GetNumShards() const;
|
||||
@@ -143,13 +143,7 @@ class ShardedCache : public ShardedCacheBase {
|
||||
sizeof(CacheShard) * GetNumShards()))),
|
||||
destroy_shards_in_dtor_(false) {}
|
||||
|
||||
// No copying allowed
|
||||
ShardedCache(const ShardedCache&) = delete;
|
||||
ShardedCache& operator=(const ShardedCache&) = delete;
|
||||
ShardedCache(ShardedCache&&) = delete;
|
||||
ShardedCache& operator=(ShardedCache&&) = delete;
|
||||
|
||||
~ShardedCache() override {
|
||||
virtual ~ShardedCache() {
|
||||
if (destroy_shards_in_dtor_) {
|
||||
ForEachShard([](CacheShard* cs) { cs->~CacheShard(); });
|
||||
}
|
||||
@@ -251,7 +245,7 @@ class ShardedCache : public ShardedCacheBase {
|
||||
std::unique_ptr<size_t[]> states(new size_t[num_shards]{});
|
||||
|
||||
size_t aepl = opts.average_entries_per_lock;
|
||||
aepl = std::max(aepl, size_t{1});
|
||||
aepl = std::min(aepl, size_t{1});
|
||||
|
||||
bool remaining_work;
|
||||
do {
|
||||
|
||||
Vendored
+2
-2
@@ -36,7 +36,7 @@ class TieredSecondaryCache : public SecondaryCacheWrapper {
|
||||
#endif
|
||||
}
|
||||
|
||||
~TieredSecondaryCache() override = default;
|
||||
~TieredSecondaryCache() override {}
|
||||
|
||||
const char* Name() const override { return "TieredSecondaryCache"; }
|
||||
|
||||
@@ -75,7 +75,7 @@ class TieredSecondaryCache : public SecondaryCacheWrapper {
|
||||
|
||||
class ResultHandle : public SecondaryCacheResultHandle {
|
||||
public:
|
||||
~ResultHandle() override = default;
|
||||
~ResultHandle() override {}
|
||||
|
||||
bool IsReady() override {
|
||||
if (inner_handle_ && inner_handle_->IsReady()) {
|
||||
|
||||
Vendored
+1
-1
@@ -241,7 +241,7 @@ class FullTypedCacheHelperFns : public BasicTypedCacheHelperFns<TValue> {
|
||||
if (source != CacheTier::kVolatileTier) {
|
||||
return Status::InvalidArgument();
|
||||
}
|
||||
if constexpr (!std::is_empty_v<TCreateContext>) {
|
||||
if constexpr (sizeof(TCreateContext) > 0) {
|
||||
TCreateContext* tcontext = static_cast<TCreateContext*>(context);
|
||||
tcontext->Create(&value, out_charge, data, type, allocator);
|
||||
} else {
|
||||
|
||||
+27
-50
@@ -46,7 +46,7 @@ This document provides guidance on how to add new options to RocksDB's public AP
|
||||
|
||||
## Pattern 1: Adding a Standard Column Family Option
|
||||
|
||||
Example reference: commit `94e65a2e0b4f817aa4bfa4c96cdf867e7980d7bc` (memtable_verify_per_key_checksum_on_seek)
|
||||
Example reference: commit `94e65a2e0b4f817aa4bfa4c96cdf867e7980d7bc` (memtable_veirfy_per_key_checksum_on_seek)
|
||||
|
||||
### Step 1: Define the Option in Public Header
|
||||
|
||||
@@ -63,7 +63,7 @@ Add the option with documentation in `AdvancedColumnFamilyOptions` struct:
|
||||
// operation.
|
||||
// This option depends on memtable_protection_bytes_per_key to be non zero.
|
||||
// If memtable_protection_bytes_per_key is zero, no validation is performed.
|
||||
bool memtable_verify_per_key_checksum_on_seek = false;
|
||||
bool memtable_veirfy_per_key_checksum_on_seek = false;
|
||||
```
|
||||
|
||||
### Step 2: Add to Internal Options Structs
|
||||
@@ -74,14 +74,14 @@ Add to `MutableCFOptions` struct (or `ImmutableCFOptions` for immutable options)
|
||||
|
||||
```cpp
|
||||
// In MutableCFOptions constructor from Options:
|
||||
memtable_verify_per_key_checksum_on_seek(
|
||||
options.memtable_verify_per_key_checksum_on_seek),
|
||||
memtable_veirfy_per_key_checksum_on_seek(
|
||||
options.memtable_veirfy_per_key_checksum_on_seek),
|
||||
|
||||
// In MutableCFOptions default constructor:
|
||||
memtable_verify_per_key_checksum_on_seek(false),
|
||||
memtable_veirfy_per_key_checksum_on_seek(false),
|
||||
|
||||
// In MutableCFOptions struct member declarations:
|
||||
bool memtable_verify_per_key_checksum_on_seek;
|
||||
bool memtable_veirfy_per_key_checksum_on_seek;
|
||||
```
|
||||
|
||||
### Step 3: Register for Serialization/Deserialization
|
||||
@@ -91,9 +91,9 @@ bool memtable_verify_per_key_checksum_on_seek;
|
||||
Add to the options type info map for serialization:
|
||||
|
||||
```cpp
|
||||
{"memtable_verify_per_key_checksum_on_seek",
|
||||
{"memtable_veirfy_per_key_checksum_on_seek",
|
||||
{offsetof(struct MutableCFOptions,
|
||||
memtable_verify_per_key_checksum_on_seek),
|
||||
memtable_veirfy_per_key_checksum_on_seek),
|
||||
OptionType::kBoolean, OptionVerificationType::kNormal,
|
||||
OptionTypeFlags::kMutable}},
|
||||
```
|
||||
@@ -101,8 +101,8 @@ Add to the options type info map for serialization:
|
||||
Add logging in `MutableCFOptions::Dump()`:
|
||||
|
||||
```cpp
|
||||
ROCKS_LOG_INFO(log, "memtable_verify_per_key_checksum_on_seek: %d",
|
||||
memtable_verify_per_key_checksum_on_seek);
|
||||
ROCKS_LOG_INFO(log, "memtable_veirfy_per_key_checksum_on_seek: %d",
|
||||
memtable_veirfy_per_key_checksum_on_seek);
|
||||
```
|
||||
|
||||
### Step 4: Update Options Helper
|
||||
@@ -112,8 +112,8 @@ ROCKS_LOG_INFO(log, "memtable_verify_per_key_checksum_on_seek: %d",
|
||||
Add to `UpdateColumnFamilyOptions()`:
|
||||
|
||||
```cpp
|
||||
cf_opts->memtable_verify_per_key_checksum_on_seek =
|
||||
moptions.memtable_verify_per_key_checksum_on_seek;
|
||||
cf_opts->memtable_veirfy_per_key_checksum_on_seek =
|
||||
moptions.memtable_veirfy_per_key_checksum_on_seek;
|
||||
```
|
||||
|
||||
### Step 5: Add to Options Settable Test
|
||||
@@ -123,7 +123,7 @@ cf_opts->memtable_verify_per_key_checksum_on_seek =
|
||||
Add to the test string in `ColumnFamilyOptionsAllFieldsSettable`:
|
||||
|
||||
```cpp
|
||||
"memtable_verify_per_key_checksum_on_seek=1;"
|
||||
"memtable_veirfy_per_key_checksum_on_seek=1;"
|
||||
```
|
||||
|
||||
### Step 6: Add db_stress Support
|
||||
@@ -131,23 +131,23 @@ Add to the test string in `ColumnFamilyOptionsAllFieldsSettable`:
|
||||
**File: `db_stress_tool/db_stress_common.h`**
|
||||
|
||||
```cpp
|
||||
DECLARE_bool(memtable_verify_per_key_checksum_on_seek);
|
||||
DECLARE_bool(memtable_veirfy_per_key_checksum_on_seek);
|
||||
```
|
||||
|
||||
**File: `db_stress_tool/db_stress_gflags.cc`**
|
||||
|
||||
```cpp
|
||||
DEFINE_bool(
|
||||
memtable_verify_per_key_checksum_on_seek,
|
||||
ROCKSDB_NAMESPACE::Options().memtable_verify_per_key_checksum_on_seek,
|
||||
"Sets CF option memtable_verify_per_key_checksum_on_seek.");
|
||||
memtable_veirfy_per_key_checksum_on_seek,
|
||||
ROCKSDB_NAMESPACE::Options().memtable_veirfy_per_key_checksum_on_seek,
|
||||
"Sets CF option memtable_veirfy_per_key_checksum_on_seek.");
|
||||
```
|
||||
|
||||
**File: `db_stress_tool/db_stress_test_base.cc`**
|
||||
|
||||
```cpp
|
||||
options.memtable_verify_per_key_checksum_on_seek =
|
||||
FLAGS_memtable_verify_per_key_checksum_on_seek;
|
||||
options.memtable_veirfy_per_key_checksum_on_seek =
|
||||
FLAGS_memtable_veirfy_per_key_checksum_on_seek;
|
||||
```
|
||||
|
||||
### Step 7: Add db_bench Support
|
||||
@@ -156,12 +156,12 @@ options.memtable_verify_per_key_checksum_on_seek =
|
||||
|
||||
```cpp
|
||||
// Flag definition (near related flags):
|
||||
DEFINE_bool(memtable_verify_per_key_checksum_on_seek, false,
|
||||
"Sets CF option memtable_verify_per_key_checksum_on_seek");
|
||||
DEFINE_bool(memtable_veirfy_per_key_checksum_on_seek, false,
|
||||
"Sets CF option memtable_veirfy_per_key_checksum_on_seek");
|
||||
|
||||
// Apply flag to options (in InitializeOptionsFromFlags or similar):
|
||||
options.memtable_verify_per_key_checksum_on_seek =
|
||||
FLAGS_memtable_verify_per_key_checksum_on_seek;
|
||||
options.memtable_veirfy_per_key_checksum_on_seek =
|
||||
FLAGS_memtable_veirfy_per_key_checksum_on_seek;
|
||||
```
|
||||
|
||||
### Step 8: Add Crash Test Support
|
||||
@@ -169,7 +169,7 @@ options.memtable_verify_per_key_checksum_on_seek =
|
||||
**File: `tools/db_crashtest.py`**
|
||||
|
||||
```python
|
||||
"memtable_verify_per_key_checksum_on_seek": lambda: random.choice([0] * 7 + [1]),
|
||||
"memtable_veirfy_per_key_checksum_on_seek": lambda: random.choice([0] * 7 + [1]),
|
||||
```
|
||||
|
||||
Also add constraint handling in `finalize_and_sanitize()` if needed:
|
||||
@@ -177,7 +177,7 @@ Also add constraint handling in `finalize_and_sanitize()` if needed:
|
||||
```python
|
||||
# only skip list memtable representation supports paranoid memory checks
|
||||
if dest_params.get("memtablerep") != "skip_list":
|
||||
dest_params["memtable_verify_per_key_checksum_on_seek"] = 0
|
||||
dest_params["memtable_veirfy_per_key_checksum_on_seek"] = 0
|
||||
```
|
||||
|
||||
### Step 9: Add Release Note
|
||||
@@ -185,7 +185,7 @@ if dest_params.get("memtablerep") != "skip_list":
|
||||
**File: `unreleased_history/new_features/<descriptive_name>.md`**
|
||||
|
||||
```markdown
|
||||
A new flag memtable_verify_per_key_checksum_on_seek is added to AdvancedColumnFamilyOptions. When it is enabled, it will validate key checksum along the binary search path on skiplist based memtable during seek operation.
|
||||
A new flag memtable_veirfy_per_key_checksum_on_seek is added to AdvancedColumnFamilyOptions. When it is enabled, it will validate key checksum along the binary search path on skiplist based memtable during seek operation.
|
||||
```
|
||||
|
||||
---
|
||||
@@ -421,30 +421,6 @@ Example reference: commit `429b36c22d76403d275dd0e6877b08d4cea2bc90` (block_alig
|
||||
|
||||
If an option already exists but needs C API support:
|
||||
|
||||
**First decide whether the option is auto-managed.**
|
||||
|
||||
Many simple option fields are no longer maintained by hand in
|
||||
`include/rocksdb/c.h` and `db/c.cc`. Before adding a manual wrapper:
|
||||
|
||||
- Check whether the option belongs to a family handled by
|
||||
`tools/c_api_gen/auto_simple_bindings.py`.
|
||||
- If it is a simple scalar/enum/string field in an auto-managed family, run
|
||||
`python3 tools/c_api_gen/regen_all.py` and let the generator add the C API.
|
||||
- After regenerating, run
|
||||
`python3 tools/c_api_gen/verify_generated_up_to_date.py` to confirm the
|
||||
checked-in generated fragments stay stable.
|
||||
- Do not edit generated `.inc` files under `c_api_gen/` by hand.
|
||||
- If the new field is not ready for C API support yet, add an entry to
|
||||
`tools/c_api_gen/auto_simple_bindings_blocklist.json` with
|
||||
`"policy": "deferred"` and a concrete reason so the build stays intentional
|
||||
rather than silently drifting.
|
||||
- If the field needs custom ownership, callback, vector, or nested-struct
|
||||
marshalling, keep it manual or move it into `tools/c_api_gen/spec.json`
|
||||
depending on the API shape.
|
||||
|
||||
If the option is not auto-managed, or the C API really is a custom/manual case,
|
||||
the traditional hand-written pattern still applies:
|
||||
|
||||
**File: `db/c.cc`**
|
||||
|
||||
```cpp
|
||||
@@ -533,3 +509,4 @@ Common option types used in serialization:
|
||||
- [ ] unreleased_history markdown file
|
||||
- [ ] Java API (for BlockBasedTableOptions)
|
||||
- [ ] C API (if needed)
|
||||
|
||||
@@ -168,18 +168,9 @@ Status YourNewAPI(const YourAPIOptions& /*options*/,
|
||||
|
||||
### Step 5: Add C API Bindings
|
||||
|
||||
> **Important:** `include/rocksdb/c.h` and `db/c.cc` are `@generated` and must
|
||||
> NOT be edited by hand — your changes would be overwritten on the next
|
||||
> regeneration. Choose the right path first (see "Before writing C API code by
|
||||
> hand" below). For hand-written (manual) wrappers, edit the source templates
|
||||
> `tools/c_api_gen/c_base.h` (declarations) and `tools/c_api_gen/c_base.cc`
|
||||
> (implementations), then run `python3 tools/c_api_gen/regen_all.py` to produce
|
||||
> `c.h` / `c.cc`. The snippets below show the *declaration* and *implementation*
|
||||
> you would add to those templates.
|
||||
**Header:** `include/rocksdb/c.h`
|
||||
|
||||
**Header (declaration → `tools/c_api_gen/c_base.h`):**
|
||||
|
||||
```c
|
||||
\`\`\`c
|
||||
// Basic version
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_your_new_api(
|
||||
rocksdb_t* db,
|
||||
@@ -200,7 +191,7 @@ extern ROCKSDB_LIBRARY_API void rocksdb_your_new_api_opt(
|
||||
char** errptr);
|
||||
\`\`\`
|
||||
|
||||
**Implementation (→ `tools/c_api_gen/c_base.cc`):**
|
||||
**Implementation:** `db/c.cc`
|
||||
|
||||
\`\`\`cpp
|
||||
void rocksdb_your_new_api(rocksdb_t* db, const char* start_key,
|
||||
@@ -226,38 +217,6 @@ void rocksdb_your_new_api_cf(rocksdb_t* db,
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**Before writing C API code by hand, choose the right path:**
|
||||
|
||||
- **Auto-managed simple struct fields:** If you added a new field to a managed
|
||||
public struct such as `ReadOptions`, selected option structs, or managed
|
||||
metadata structs, first check `tools/c_api_gen/auto_simple_bindings.py`.
|
||||
Simple scalar/enum/string fields should be regenerated with
|
||||
`python3 tools/c_api_gen/regen_all.py` rather than hand-editing
|
||||
`include/rocksdb/c.h` / `db/c.cc`.
|
||||
After regenerating, run
|
||||
`python3 tools/c_api_gen/verify_generated_up_to_date.py` to confirm the
|
||||
checked-in generated fragments are stable.
|
||||
- **Spec-driven wrappers:** If the API is still mechanically generated but needs
|
||||
an explicit C shape, naming, or `Status`/`char** errptr` policy, add it to
|
||||
`tools/c_api_gen/spec.json`.
|
||||
- **Fully manual wrappers:** If the API uses callbacks, ownership transfer,
|
||||
vectors/maps, open flows, or otherwise irregular marshalling, keep the C API
|
||||
hand-written.
|
||||
|
||||
**Temporary deferral for auto-managed families:**
|
||||
|
||||
If a new field lands in an auto-managed family but the C API shape is not ready
|
||||
yet, add a checked-in entry to
|
||||
`tools/c_api_gen/auto_simple_bindings_blocklist.json` with:
|
||||
|
||||
- `policy: "manual"` when the field is intentionally outside simple auto-gen
|
||||
- `policy: "deferred"` when the field should be revisited later
|
||||
- a concrete `reason`
|
||||
- `tracking_issue` when available
|
||||
|
||||
If a field in an auto-managed family is not supported by the generator and is
|
||||
not covered by the blocklist, regeneration should fail. That is intentional.
|
||||
|
||||
**If you have options, also add:**
|
||||
|
||||
\`\`\`cpp
|
||||
@@ -523,8 +482,8 @@ public class YourAPIOptionsTest {
|
||||
| StackableDB | `include/rocksdb/utilities/stackable_db.h` | ✓ |
|
||||
| Secondary DB | `db/db_impl/db_impl_secondary.h` | If not supported |
|
||||
| Compacted DB | `db/db_impl/compacted_db_impl.h` | If not supported |
|
||||
| C API Header (manual wrappers) | `tools/c_api_gen/c_base.h` → regen → `include/rocksdb/c.h` (`@generated`) | ✓ |
|
||||
| C API Implementation (manual wrappers) | `tools/c_api_gen/c_base.cc` → regen → `db/c.cc` (`@generated`) | ✓ |
|
||||
| C API Header | `include/rocksdb/c.h` | ✓ |
|
||||
| C API Implementation | `db/c.cc` | ✓ |
|
||||
| Java API | `java/src/main/java/org/rocksdb/RocksDB.java` | ✓ |
|
||||
| Java Options | `java/src/main/java/org/rocksdb/YourAPIOptions.java` | If needed |
|
||||
| JNI Implementation | `java/rocksjni/rocksjni.cc` | ✓ |
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# PR Complexity Classifier — CI Triage Prompt
|
||||
|
||||
## Purpose
|
||||
Quickly classify a RocksDB pull request as **simple** or **complex** so the
|
||||
downstream reviewer can pick an appropriate thinking budget.
|
||||
|
||||
## Output Contract (STRICT)
|
||||
Your final response MUST be exactly one of these two lowercase tokens, on a
|
||||
line by itself, with no other text:
|
||||
|
||||
```
|
||||
simple
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
complex
|
||||
```
|
||||
|
||||
If you are unsure, output `complex`. The downstream review will use this token
|
||||
to set its thinking budget — when in doubt, prefer the more thorough budget.
|
||||
|
||||
## Classification Heuristics
|
||||
|
||||
Treat a PR as **simple** when ALL of the following hold:
|
||||
- Diff touches < ~200 lines of non-test code
|
||||
- No changes to public headers under `include/rocksdb/`
|
||||
- No changes to on-disk format (SST block layout, WAL record layout,
|
||||
manifest, options file format, version edit encoding)
|
||||
- No changes to compaction picker, write-path locking, recovery, or
|
||||
WAL/memtable lifecycle
|
||||
- No new public option, no new statistics counter, no new RPC/serialized
|
||||
message
|
||||
- Tests-only or docs-only changes
|
||||
- Trivial refactors (rename, comment, dead-code removal, lint fixes)
|
||||
- One-line bug fix with obvious root cause and a focused regression test
|
||||
|
||||
Treat a PR as **complex** when ANY of the following hold:
|
||||
- Touches files in `db/`, `db/compaction/`, `db/blob/`, `cache/`,
|
||||
`table/block_based/`, `file/`, `env/io_*` with > ~50 lines of logic change
|
||||
- Modifies thread-safety/synchronization (mutexes, atomics, memory ordering,
|
||||
refcounting, condvars)
|
||||
- Changes serialization or on-disk format
|
||||
- Changes public API surface in `include/rocksdb/`
|
||||
- Adds a new feature flag, option, or compaction style
|
||||
- Touches transactions (`utilities/transactions/`), backup/checkpoint,
|
||||
user-defined timestamps, or remote compaction
|
||||
- Cross-cutting refactor spanning > 5 directories
|
||||
|
||||
## How To Decide
|
||||
1. Read the diff summary and changed-file list provided below.
|
||||
2. Skim the diff hunks — focus on which subsystems are touched and whether
|
||||
the change is mechanical vs. semantic.
|
||||
3. Apply the heuristics above. Default to `complex` if the rules conflict.
|
||||
4. Output the single token. No preamble. No explanation.
|
||||
|
||||
## Tool Use
|
||||
You may use `View`, `GlobTool`, and `GrepTool` to peek at one or two files
|
||||
if the diff snippet alone is ambiguous, but keep this fast — this is a
|
||||
triage step, not a review. Do NOT spawn sub-agents.
|
||||
@@ -1,3 +0,0 @@
|
||||
You are an expert C++ engineer for RocksDB.
|
||||
Read CLAUDE.md in the repo root and claude_md/ files for project context.
|
||||
Answer thoroughly with exact file paths and line numbers.
|
||||
@@ -1,54 +0,0 @@
|
||||
Read review-findings.md. This file contains partial code review findings
|
||||
from a session that ran out of turns before finishing. Reformat them into
|
||||
a clean final review comment.
|
||||
|
||||
## Required Output Structure
|
||||
|
||||
Use this exact structure so the PR page stays scrollable:
|
||||
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
> **Partial review** — the analysis was interrupted before all perspectives
|
||||
> were completed. Findings below cover only the perspectives that finished.
|
||||
> You can request a fresh full review with `/claude-review`.
|
||||
|
||||
<!-- One or two sentences of overall assessment. -->
|
||||
|
||||
**High-severity findings (N):**
|
||||
- **[file.cc:123]** One-line description. <!-- repeat per HIGH finding -->
|
||||
|
||||
<!-- If no HIGH findings were salvaged, write: -->
|
||||
<!-- _No high-severity findings recovered._ -->
|
||||
|
||||
<details>
|
||||
<summary>Recovered findings (click to expand)</summary>
|
||||
|
||||
### Findings
|
||||
|
||||
#### :red_circle: HIGH
|
||||
... (H1, H2, ...)
|
||||
|
||||
#### :yellow_circle: MEDIUM
|
||||
... (M1, M2, ...)
|
||||
|
||||
#### :green_circle: LOW / NIT
|
||||
... (L1, L2, ...)
|
||||
|
||||
### Cross-Component Analysis
|
||||
<!-- Whatever cross-component results were captured. -->
|
||||
|
||||
### Positive Observations
|
||||
<!-- Optional. -->
|
||||
|
||||
</details>
|
||||
```
|
||||
|
||||
## Rules
|
||||
- The `## Summary`, the partial-review notice, and the HIGH bullet list MUST
|
||||
stay outside the `<details>` block.
|
||||
- All per-finding detail and analysis MUST live inside the `<details>` block.
|
||||
- Do NOT nest `<details>` blocks.
|
||||
- Do NOT add any text after the closing `</details>` — the comment-builder
|
||||
appends its own footer.
|
||||
- Output ONLY the formatted review. No commentary, no explanation.
|
||||
@@ -1,807 +0,0 @@
|
||||
# Code Review Workflow — CI Prompt
|
||||
|
||||
## Purpose
|
||||
Thorough multi-agent code review for RocksDB commits following CLAUDE.md guidelines,
|
||||
with structured codebase exploration, inter-agent debate, and verification.
|
||||
|
||||
## Behavioral Compatibility Review Perspective
|
||||
|
||||
Behavior changes are human judgment calls. They must be intentional,
|
||||
well-documented (including release notes), and researched for potential
|
||||
downstream production impact. Agents and reviewers must call out concrete gaps,
|
||||
ambiguity, or adverse impacts in the change's intent, documentation, and
|
||||
production-impact analysis.
|
||||
|
||||
When a diff changes how an existing accepted public or serialized input is
|
||||
interpreted—including an undocumented, discouraged, or historically ignored
|
||||
value—reviewers must:
|
||||
- Compare the old and new observable behavior, including performance and
|
||||
resource impact.
|
||||
- Check that the rationale and user-facing documentation clearly describe the
|
||||
change.
|
||||
- Identify known direct callers and stored configurations that may depend on
|
||||
the previous behavior.
|
||||
- Check for appropriate regression coverage, or a documented reason why such
|
||||
coverage is not practical.
|
||||
|
||||
A behavior change is not automatically a defect. Report a finding when the
|
||||
intent, documentation, downstream-impact analysis, or mitigation has a concrete
|
||||
gap or ambiguity that could lead to an unintended compatibility regression.
|
||||
|
||||
## DB Mutex Review Perspective
|
||||
|
||||
For every non-trivial change, determine whether the changed code, or any
|
||||
transitive callee it adds or changes, can run while `DBImpl::mutex_` is held.
|
||||
State the result explicitly, including when the DB mutex is not affected.
|
||||
|
||||
`DBImpl::mutex_` is the DB-wide metadata and coordination mutex. It protects
|
||||
cross-object invariants involving `ColumnFamilyData`, memtable and
|
||||
`SuperVersion` publication, `VersionSet`, snapshots, flush/compaction queues,
|
||||
background-job state, and file lifetime. It is shared by all column families
|
||||
and can be a hot lock. It is not the filesystem `db_lock_`, and it should not
|
||||
replace data-path synchronization already provided by `WriteThread`,
|
||||
`wal_write_mutex_`, atomics, referenced `SuperVersion`s, or component-local
|
||||
synchronization.
|
||||
|
||||
When a DB-mutex critical section is affected:
|
||||
|
||||
### Locking and correctness
|
||||
|
||||
- Trace the full call path and mark the exact lock and unlock boundaries. Do
|
||||
not inspect only the lines that directly acquire the mutex.
|
||||
- State the locking contract. Helpers that require the lock should document it
|
||||
and normally use `mutex_.AssertHeld()`. Check whether each caller expects the
|
||||
lock to be held on return.
|
||||
- Treat calls that can release and re-acquire the mutex as concurrency
|
||||
boundaries. Examples include `VersionSet::LogAndApply()`, condition-variable
|
||||
waits, write-thread coordination, and notification helpers. Revalidate state
|
||||
inspected before such a call.
|
||||
- Keep atomic metadata transitions under the mutex. Examples include moving a
|
||||
memtable between mutable and immutable state, reserving compaction inputs,
|
||||
installing a `Version` or `SuperVersion`, updating scheduling counters and
|
||||
queues, and changing file-lifetime protection.
|
||||
- For expensive work, prefer a prepare/run/install structure: reserve and pin
|
||||
the required state while locked, do CPU or I/O work while unlocked, then
|
||||
re-lock, validate, and publish. Before unlocking, copy mutable options and
|
||||
acquire every required object reference or lifetime reservation.
|
||||
- Check object lifetime across every unlocked region. Do not use a raw
|
||||
`ColumnFamilyData*`, `Version*`, memtable, file metadata pointer, or DB-owned
|
||||
container element after unlocking unless an explicit reference,
|
||||
`SuperVersion`, job object, or pending-output reservation keeps it alive.
|
||||
- Preserve the snapshot/input-selection boundary. Flush and compaction must not
|
||||
miss a snapshot whose visible key versions they may remove. Missing a newly
|
||||
created snapshot is a correctness bug; retaining a recently released
|
||||
snapshot is conservative but safe.
|
||||
- Never invoke untrusted or re-entrant code while holding the mutex. The mutex
|
||||
is non-reentrant, so a callback into RocksDB can self-deadlock.
|
||||
- Check lock ordering. `options_mutex_` is acquired before the DB mutex. When
|
||||
both the DB mutex and `wal_write_mutex_` are needed, the DB mutex is acquired
|
||||
first. Establish and document the order for other locks.
|
||||
- Keep cleanup outside the critical section when possible. File deletion,
|
||||
`JobContext::Clean()`, expensive `SuperVersion` destruction, logging, and
|
||||
listener callbacks should normally run after protected state is detached or
|
||||
snapshotted.
|
||||
- Do not add the DB mutex to steady-state point reads or the normal write data
|
||||
phase without strong justification. Reads normally use a referenced
|
||||
`SuperVersion`; writes use `WriteThread` and component-specific
|
||||
synchronization.
|
||||
|
||||
### Critical-section performance
|
||||
|
||||
- Compare the CPU and I/O performed under the mutex before and after the
|
||||
change. Include call frequency, loop bounds, input-size scaling, hidden work
|
||||
in callees, and worst-case cost.
|
||||
- Account for filesystem or network I/O, waits, callbacks, logging and
|
||||
formatting, allocation, container growth, copies, sorting, scans, reference
|
||||
release and destructors, cache misses, and repeated metadata lookups.
|
||||
- Do not allow a significant regression in mutex-held work without clear
|
||||
justification, hold-time or contention measurements, and representative
|
||||
benchmarks.
|
||||
- Treat unavoidable work under the mutex as hot-path code and keep it highly
|
||||
optimized. Precompute, allocate, copy, and perform I/O outside the lock;
|
||||
remove repeated scans and lookups; cache or batch work where practical; and
|
||||
keep locked operations O(1) or tightly bounded when possible.
|
||||
- Treat new blocking I/O, waits, callbacks into user or plugin code, unbounded
|
||||
loops, or work that scales with DB size, files, column families, snapshots,
|
||||
or pending jobs as a blocker unless it is unavoidable and supported by strong
|
||||
measurements and explicit design justification.
|
||||
|
||||
### Validation and evidence
|
||||
|
||||
- Test unlock windows with sync points rather than sleeps. Cover relevant races
|
||||
with memtable switches, snapshot create/release, column-family drop,
|
||||
flush/compaction install, shutdown, and background errors. Run TSAN where
|
||||
appropriate.
|
||||
- Distinguish wait time from hold time. `PerfContext::db_mutex_lock_nanos` and
|
||||
`DB_MUTEX_WAIT_MICROS` primarily expose acquisition wait; use contention
|
||||
profiles or scoped instrumentation to find long critical sections.
|
||||
- Report affected critical sections, before/after cost, workload assumptions,
|
||||
optimization choices, and remaining risk. If exact measurement is not
|
||||
practical, provide a conservative static bound and do not claim no regression
|
||||
without evidence.
|
||||
|
||||
IMPORTANT — Where the review goes: Your FINAL RESPONSE TEXT is the review.
|
||||
The PR comment is generated verbatim from your final response, so the
|
||||
complete, polished review MUST appear there in full. Do NOT end your turn with
|
||||
a meta-summary such as "the review has been written to review-findings.md" —
|
||||
paste the entire review as your response.
|
||||
|
||||
review-findings.md is a RECOVERY BACKSTOP, not the primary output: after
|
||||
completing EACH major phase (Setup, Codebase Context, Initial Review, Debate,
|
||||
Synthesis), append your current findings to it with the Write tool, and after
|
||||
the final synthesis overwrite it with the complete review. This preserves
|
||||
partial results if the turn limit interrupts the run (a recovery step reads
|
||||
this file); it does NOT substitute for outputting the full review as your
|
||||
final response.
|
||||
|
||||
## Workflow Steps
|
||||
|
||||
### 1. Setup Phase
|
||||
- Read CLAUDE.md to understand review guidelines
|
||||
- Identify the commit/diff/PR to review
|
||||
- The PR diff is provided below in this prompt. The repository is already
|
||||
checked out — use local file search tools (Grep, Glob, Read) to explore.
|
||||
- Parse the changed files and categorize them (API, core logic, tests, etc.)
|
||||
- Read all changed files to build full context
|
||||
|
||||
### 2. Codebase Context Phase (CRITICAL — Do Not Skip)
|
||||
|
||||
**Why this matters**: Review agents that only see the diff miss systemic bugs.
|
||||
For example, a change to an iterator's return value might look correct in
|
||||
isolation but break multi-SST iteration 5 layers up the call stack. A change
|
||||
to error handling might silently drop errors that a caller 3 levels up relies
|
||||
on for recovery. This phase builds the context that prevents those blind spots.
|
||||
|
||||
Go deep. Surface-level reading leads to reviews that miss caching layers,
|
||||
existing helper functions, or concurrency requirements. The most expensive
|
||||
failure mode is findings that look correct in isolation but miss how the
|
||||
change breaks the surrounding system.
|
||||
|
||||
The team lead spawns one or more research agents to perform the following
|
||||
analyses using local file search tools (Grep, Glob, Read). The research
|
||||
must be written to `context.md` BEFORE any review agent is spawned.
|
||||
|
||||
#### 2a. Subsystem Deep-Read
|
||||
Read the changed files AND their surrounding subsystem **in depth** — not just
|
||||
signatures, but actual logic, edge cases, data flows, locking protocols,
|
||||
concurrency patterns, and interactions between components.
|
||||
|
||||
For each changed file, also read:
|
||||
- The header that declares its interface (if the change is in a .cc file)
|
||||
- The sibling implementation that does the same thing the "standard" way
|
||||
(e.g., for a UDI iterator change, read how `IndexBlockIter` handles the
|
||||
same scenario — it's the reference implementation)
|
||||
- The wrapper/adapter layer that sits between this code and its callers
|
||||
- Any existing tests to understand what behaviors are currently guaranteed
|
||||
|
||||
#### 2b. Caller-Chain Analysis (upstream impact)
|
||||
For each changed function/method, trace the call chain UPWARD 3-5 levels to
|
||||
understand who consumes the changed behavior and what invariants they rely on.
|
||||
**Focus on control flow decisions** — if/else branches, while loop conditions,
|
||||
early returns — that depend on the changed return values or state.
|
||||
|
||||
**How to do this**:
|
||||
- Search for callers of each changed function (search for the function name, the
|
||||
class method, virtual overrides)
|
||||
- For each caller, search for ITS callers, repeating 3-5 levels up
|
||||
- At each level, read the actual code to understand the control flow decision
|
||||
- Stop when you reach a "terminal" caller (e.g., user-facing API, top-level
|
||||
iterator) or when the propagation is clearly safe
|
||||
|
||||
#### 2c. Callee-Chain Analysis (downstream dependencies AND side effects)
|
||||
For each changed function, trace what it calls and whether those calls have
|
||||
new preconditions or changed semantics. **Critically, trace SIDE EFFECTS —
|
||||
not just return values.** Many bugs hide in side effects on shared state
|
||||
(counters, sequence numbers, flags) that are invisible if you only check
|
||||
return values.
|
||||
|
||||
**For each callee, ask:**
|
||||
1. What does it RETURN? (the obvious check)
|
||||
2. What shared state does it MUTATE? (the non-obvious check)
|
||||
3. Under what PRECONDITIONS does it operate correctly?
|
||||
4. Are those preconditions met in the new calling context?
|
||||
|
||||
#### 2d. Sibling Implementation Comparison
|
||||
Identify the "reference" or "standard" implementation that does the same thing
|
||||
the changed code does, and compare their behavior. This is critical for plugin/
|
||||
extension APIs where the implementation must match an implicit contract.
|
||||
|
||||
#### 2e. Invariant Documentation
|
||||
Document the key invariants that the changed code must maintain. Read existing
|
||||
comments, assertions, and test expectations to discover these invariants.
|
||||
|
||||
#### 2f. Related Functionality and Existing Conventions
|
||||
Identify related functionality that already exists in the codebase:
|
||||
- Are there existing helper functions the change should use (or is duplicating)?
|
||||
- Are there existing patterns for the same kind of change (e.g., how other
|
||||
Customizable subclasses handle deprecation)?
|
||||
- Are there existing tests that test similar scenarios (e.g., multi-SST
|
||||
iteration tests that could be extended)?
|
||||
|
||||
#### 2g. Cross-Component Data Consumer Analysis (CRITICAL — common blind spot)
|
||||
|
||||
**Why this is separate from caller-chain analysis:** Sections 2b-2c trace
|
||||
who CALLS the changed functions. This section traces who CONSUMES the data
|
||||
that the changed code PRODUCES. These are often completely different
|
||||
subsystems.
|
||||
|
||||
When the change writes data to a shared structure (memtable, SST block, cache
|
||||
entry, statistics counter), ask: **"Who reads this data, under what rules,
|
||||
and do those rules match the writer's assumptions?"**
|
||||
|
||||
**How to do this:**
|
||||
1. Identify every piece of data the change WRITES (e.g., a range tombstone
|
||||
entry, a counter update, a metadata field)
|
||||
2. For each, search the codebase for ALL readers of that data structure
|
||||
3. For each reader, check:
|
||||
- Does the reader apply visibility rules (seqno, read_callback, snapshot)?
|
||||
- Are those rules compatible with the writer's assumptions?
|
||||
- Does the reader assume invariants about the data (e.g., seqno ordering,
|
||||
monotonicity) that the writer might violate?
|
||||
|
||||
#### 2h. Alternative Execution Contexts
|
||||
|
||||
The same code path may run in different contexts with different assumptions.
|
||||
**Enumerate all contexts and check each one.** This is where "works in the
|
||||
common case but breaks in edge configurations" bugs hide.
|
||||
|
||||
For RocksDB, always check whether the changed code interacts differently with:
|
||||
|
||||
| Context | Key difference | Common failure mode |
|
||||
|---------|---------------|-------------------|
|
||||
| WritePreparedTxnDB / WriteUnpreparedTxnDB | `read_callback_` controls visibility, not just seqno | Visibility bypass |
|
||||
| ReadOnly DB / SecondaryInstance | No mutable memtable, writes not allowed | Null pointer or no-op needed |
|
||||
| CompactionService / Remote compaction | Different process, serialized state | Serialization mismatch |
|
||||
| User-defined timestamps | Extra dimension in key comparison and visibility | Wrong ordering |
|
||||
| MemPurge | Memtable-to-memtable, not memtable-to-SST | Missing data |
|
||||
| Column family with BlobDB | Values may be in blob files, not inline | Missing dereference |
|
||||
| Snapshots (old, held long-term) | Snapshot seqno may be far behind current state | Metadata corruption |
|
||||
| Concurrent writers (allow_concurrent_memtable_write) | Lock-free paths vs locked paths | Lost updates |
|
||||
| FIFO / Universal compaction | Different compaction invariants than Level | Wrong assumptions |
|
||||
| Prefix seek / total order seek | Different iterator behavior | Wrong iteration results |
|
||||
|
||||
**For each context, ask:**
|
||||
1. Does the code execute in this context? (Check constructor, feature flags)
|
||||
2. If yes, do the assumptions still hold?
|
||||
3. If not, should the feature be disabled in this context?
|
||||
|
||||
#### 2i. Assumption Stress-Testing (the "logically X" audit)
|
||||
|
||||
When the change claims a property (e.g., "logically redundant," "no-op in
|
||||
this case," "safe because X"), **systematically break it:**
|
||||
|
||||
1. **State the claim precisely.** E.g., "The inserted range tombstone is
|
||||
logically redundant — it covers only keys already deleted by point
|
||||
tombstones."
|
||||
2. **List the preconditions** that must be true for the claim to hold.
|
||||
3. **For each precondition, construct a counterexample** — a concrete scenario
|
||||
where the precondition is violated.
|
||||
4. **Verify each counterexample against the code.** Does the code guard
|
||||
against it? If not, it's a bug.
|
||||
|
||||
**Anti-pattern: treating asserts as proofs.** When you see an assert, do NOT
|
||||
conclude "the invariant holds." Instead ask: "Can I construct an input where
|
||||
this assert fires?" If yes, it's a bug (the assert catches it in debug but
|
||||
release builds silently corrupt). If you cannot construct a counterexample
|
||||
after trying, document WHY it's impossible.
|
||||
|
||||
#### 2j. Write Context Document
|
||||
Write the complete analysis to `context.md` in the review folder. This document
|
||||
is provided to ALL review agents as part of their prompt.
|
||||
|
||||
**Context document template**:
|
||||
```markdown
|
||||
# Codebase Context for Review
|
||||
|
||||
## How the Relevant Subsystem Works Today
|
||||
[Detailed description of the subsystem architecture, data flows,
|
||||
and component interactions. Not just "what" but "how" and "why."]
|
||||
|
||||
## Changed Functions and Their Call Chains
|
||||
|
||||
### function_name() (file:line)
|
||||
**What changed**: [brief description of the behavioral change]
|
||||
|
||||
**Upstream callers** (who depends on this):
|
||||
1. CallerA::method() (file:line) — uses return value to decide X
|
||||
2. CallerB::method() (file:line) — passes result to CallerC
|
||||
3. CallerC::method() (file:line) — THE CRITICAL DECISION POINT: ...
|
||||
|
||||
**Downstream callees** (what this depends on):
|
||||
1. calleeA() — behavior unchanged
|
||||
2. calleeB() — NEW dependency, requires X
|
||||
|
||||
**Sibling implementation** (how the "standard" version handles this):
|
||||
- StandardImpl::method() does Y at file:line, which ensures invariant Z
|
||||
- The changed code must match or document any deviation
|
||||
|
||||
**Key invariants**:
|
||||
- Must never return X when Y is true because CallerC will...
|
||||
- Must always set Z before returning because CallerB assumes...
|
||||
|
||||
## System Architecture Context
|
||||
[How the changed components fit into the overall system]
|
||||
|
||||
## Known Invariants That Must Be Preserved
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
## Existing Conventions and Related Code
|
||||
- [helper functions, patterns, existing tests that are relevant]
|
||||
|
||||
## Cross-Component Data Consumers
|
||||
For each piece of data the change WRITES to a shared structure:
|
||||
### [data item] written to [structure]
|
||||
**Writer assumptions**: [what the writer assumes about how this data is consumed]
|
||||
**All readers**:
|
||||
1. ReaderA::method() (file:line) — reads under [visibility rules]
|
||||
- Compatible with writer? YES/NO. If NO, explain the mismatch.
|
||||
2. ReaderB::method() (file:line) — reads under [different rules]
|
||||
- Compatible with writer? YES/NO.
|
||||
|
||||
## Alternative Execution Contexts
|
||||
| Context | Does code execute? | Assumptions hold? | Action needed? |
|
||||
|---------|-------------------|-------------------|----------------|
|
||||
| WritePreparedTxnDB | YES/NO | YES/NO | [disable/guard/safe] |
|
||||
| Old snapshots | YES/NO | YES/NO | ... |
|
||||
| User-defined timestamps | YES/NO | YES/NO | ... |
|
||||
| ReadOnly DB | YES/NO | YES/NO | ... |
|
||||
| ... | ... | ... | ... |
|
||||
|
||||
## Assumption Stress Test
|
||||
### Claim: "[the design claim, e.g., logically redundant]"
|
||||
**Preconditions for claim to hold:**
|
||||
1. [precondition] — counterexample: [scenario]. Guarded? YES/NO.
|
||||
2. [precondition] — counterexample: [scenario]. Guarded? YES/NO.
|
||||
|
||||
## Potential Pitfalls
|
||||
- [specific scenarios where the change could interact badly with
|
||||
the surrounding system, identified from the caller-chain analysis]
|
||||
```
|
||||
|
||||
### 3. Initial Review Phase (Parallel)
|
||||
Create a team and spawn 5 review agents in parallel. **Include the context
|
||||
document from Phase 2 in each agent's prompt.** Each agent writes findings
|
||||
to its own file and sends a summary message to the team lead.
|
||||
|
||||
Each agent's prompt should include:
|
||||
```
|
||||
## Codebase Context (READ THIS FIRST)
|
||||
[paste or reference the context.md file]
|
||||
|
||||
You MUST consider how your findings interact with the upstream callers
|
||||
and system invariants documented above. A finding that looks correct
|
||||
in isolation may be a critical bug when you consider the full call chain.
|
||||
```
|
||||
|
||||
#### Agent: Design & Approach Reviewer
|
||||
- Read the commit message deeply to understand the problem being solved
|
||||
- Analyze whether this is the right approach to the problem
|
||||
- Consider alternative designs and trade-offs:
|
||||
- Are there simpler solutions that achieve the same goal?
|
||||
- Does the approach introduce unnecessary complexity?
|
||||
- Would a different data structure or algorithm be more appropriate?
|
||||
- Evaluate whether the change follows existing architectural patterns or
|
||||
introduces new patterns that may be inconsistent
|
||||
- Assess the scope: is the change too large? Should it be split into
|
||||
smaller, independently reviewable pieces?
|
||||
- Check if the approach has precedent in the codebase or in the academic
|
||||
literature it references (e.g., SuRF paper)
|
||||
|
||||
#### Agent: Correctness Reviewer
|
||||
- Thread safety and concurrency analysis
|
||||
- Error handling and propagation via Status type
|
||||
- Edge cases (empty inputs, overflow, boundary conditions)
|
||||
- Data corruption scenarios
|
||||
- Logic correctness of new algorithms
|
||||
- **Behavioral contract changes**: Do return value semantics match what
|
||||
upstream callers expect? (Use the caller-chain analysis from context.md)
|
||||
- **Callee side effects**: Does the change call functions that mutate shared
|
||||
state (counters, seqnos, metadata)? Are the mutations correct for the new
|
||||
calling context? (Use the callee-chain analysis from context.md)
|
||||
- Apply the DB Mutex Review Perspective above to locking contracts, unlocked
|
||||
object lifetimes, stale-state validation, lock ordering, and snapshot
|
||||
boundaries.
|
||||
|
||||
#### Agent: Cross-Component & Adversarial Reviewer
|
||||
|
||||
This agent exists because the most critical bugs hide at component boundaries,
|
||||
not within a single component. It uses a fundamentally different methodology
|
||||
than the correctness reviewer: instead of verifying "does the code do what it
|
||||
intends?", it asks "what breaks when we change the assumptions?"
|
||||
|
||||
**Data-flow analysis:** Perform the cross-component data consumer analysis
|
||||
described in section 2g. For every piece of data the change WRITES to a shared
|
||||
structure, trace ALL READERS and verify their visibility rules are compatible
|
||||
with the writer's assumptions. This is a DATA-FLOW question, not a
|
||||
CONTROL-FLOW question — readers may be in completely different subsystems.
|
||||
|
||||
**Alternative execution contexts:** Use the canonical table from section 2h.
|
||||
Enumerate all contexts where the changed code executes and verify assumptions
|
||||
hold in each.
|
||||
|
||||
**Assumption stress-testing and assert-breaking:** Follow the methodology from
|
||||
section 2i. Identify every design claim, enumerate preconditions, construct
|
||||
counterexamples. Treat asserts as hypotheses to break, not proofs.
|
||||
**Red flag words**: "logically redundant", "safe because", "no-op",
|
||||
"always true", "cannot happen", "invariant holds"
|
||||
|
||||
**Callee side-effect audit:** Perform the callee side-effect audit described
|
||||
in section 2c. For every callee, ask what it RETURNS and what it MUTATES.
|
||||
|
||||
Write findings to `findings-cross-component.md`.
|
||||
|
||||
#### Agent: Invariant Adversary
|
||||
|
||||
This agent does NOT read the diff in detail. It takes the feature summary and
|
||||
systematically tries to break it. While other agents verify "does the code do
|
||||
what it says?", this agent asks "what existing system invariants does this
|
||||
feature violate?" and "under what inputs do the design claims fail?"
|
||||
|
||||
**Steps 1-4: Assumption stress-testing.** Follow the methodology from section
|
||||
2i: extract design claims, enumerate preconditions, construct counterexamples,
|
||||
and attempt to break every assert. Be exhaustive about input parameter ranges,
|
||||
shared state configurations, and concurrent interleaving.
|
||||
|
||||
**Step 5: Callee side-effect audit.** Perform the callee side-effect audit
|
||||
described in section 2c. For every function the changed code calls, list ALL
|
||||
mutations to shared state (atomic CAS loops, counter increments, flag/metadata
|
||||
updates, cache invalidation). A function returning `Status::OK()` does NOT
|
||||
mean its side effects are correct.
|
||||
|
||||
Write findings to `findings-invariant-adversary.md`.
|
||||
|
||||
#### Agent: Caller-Context Auditor
|
||||
|
||||
This agent traces BACKWARD from every entry point the changed code hooks into.
|
||||
While other agents read the changed code forward ("what does it do?"), this
|
||||
agent enumerates WHO invokes it and WITH WHAT parameter ranges.
|
||||
|
||||
The key insight: a function that is correct for all *typical* inputs may be
|
||||
catastrophically wrong for *atypical-but-reachable* inputs. This agent's job
|
||||
is to find the atypical inputs.
|
||||
|
||||
**Step 1: Identify entry points.** List every function/constructor/method in
|
||||
the changed code that receives external input (parameters, config values,
|
||||
pointers to shared state). Include:
|
||||
- Constructor parameters (e.g., `active_mem`, `read_callback`, `sequence`)
|
||||
- Virtual method overrides that callers invoke polymorphically
|
||||
- Functions called from multiple subsystems
|
||||
|
||||
**Step 2: Enumerate all callers (3-5 levels up).** For each entry point,
|
||||
search the codebase for ALL callers. Do NOT stop at the first caller — trace
|
||||
the full call chain. Use `Grep` and `Glob` to find:
|
||||
- Direct callers of the function
|
||||
- Callers of wrapper/adapter functions that forward to it
|
||||
- Factory functions that construct the object
|
||||
- Virtual dispatch sites (search for the base class method name)
|
||||
|
||||
**Step 3: Parameter range analysis.** For each caller, determine:
|
||||
- What values does it pass for each parameter?
|
||||
- Under what conditions does it call this function?
|
||||
- Are there callers that pass unusual values? (e.g., `kMaxSequenceNumber`,
|
||||
`nullptr`, old snapshot seqnos, non-null `read_callback_`)
|
||||
|
||||
Build a parameter range table for each entry point, listing all callers
|
||||
and the values they pass for each parameter.
|
||||
|
||||
**Step 4: Configuration matrix.** Enumerate option/config combinations that
|
||||
affect the changed code path:
|
||||
- Which options enable/disable the feature?
|
||||
- Which options change the execution context? (e.g.,
|
||||
`allow_concurrent_memtable_write`, `use_trie_index`)
|
||||
- Are there option combinations that create contradictions?
|
||||
|
||||
**Step 5: Cross-reference with context.md.** Compare your caller analysis
|
||||
with the invariants and execution contexts documented in context.md. Flag
|
||||
any caller that violates an assumed precondition.
|
||||
|
||||
Write findings to `findings-caller-audit.md`.
|
||||
|
||||
#### Agent: Performance Reviewer
|
||||
- Memory allocation on hot paths
|
||||
- Unnecessary copies (string, buffer)
|
||||
- Cache efficiency and data locality
|
||||
- Loop optimization opportunities
|
||||
- Branch prediction (LIKELY/UNLIKELY)
|
||||
- Zero-overhead design verification
|
||||
- Apply the DB Mutex Review Perspective above, with special focus on transitive
|
||||
CPU and I/O, before/after cost, critical-section hold time, and benchmark
|
||||
evidence
|
||||
|
||||
#### Agent: API & Compatibility Reviewer
|
||||
- Public API backwards compatibility
|
||||
- API consistency with existing patterns
|
||||
- Documentation completeness
|
||||
- Deprecation policy compliance
|
||||
- Forward compatibility (struct extensibility)
|
||||
- Apply the Behavioral Compatibility Review Perspective above to changes in
|
||||
observable semantics and implicit caller contracts.
|
||||
|
||||
#### Agent: Serialization & Deserialization Reviewer
|
||||
- Format correctness and versioning
|
||||
- Alignment requirements
|
||||
- Integer overflow in size computations
|
||||
- Bounds checking on untrusted data
|
||||
- Crafted input attack vectors
|
||||
|
||||
#### Agent: Test Coverage Reviewer
|
||||
- Edge case coverage
|
||||
- Failure mode testing (corruption, truncation)
|
||||
- Round-trip testing (build → serialize → deserialize → verify)
|
||||
- Integration test coverage
|
||||
- **System-level test coverage**: Are the caller-chain interactions tested?
|
||||
(e.g., multi-SST iteration with UDI, level compaction with new behavior)
|
||||
- Test quality (no flaky patterns, good assertions)
|
||||
|
||||
### 4. Round-Robin Debate Phase
|
||||
After all 5 agents complete their initial review, the team lead orchestrates
|
||||
a structured debate:
|
||||
|
||||
#### Step 4a: Share findings
|
||||
- Team lead sends each agent a summary of ALL other agents' findings
|
||||
(or instructs each agent to read the other agents' findings files)
|
||||
|
||||
#### Step 4b: Critique round (2 rounds)
|
||||
Each agent reviews the findings from the other agents and sends messages to
|
||||
challenge, support, or refine them:
|
||||
|
||||
- **Challenge**: "I disagree with [agent] [finding] because [evidence]."
|
||||
- **Support**: "I independently found the same issue — this confirms it."
|
||||
- **Refine**: "[Finding A] is actually a consequence of [Finding B].
|
||||
The root cause is the same."
|
||||
|
||||
The debate assignment follows a round-robin pattern:
|
||||
```
|
||||
correctness-reviewer → critiques → invariant-adversary, serialization
|
||||
cross-component-reviewer → critiques → correctness, caller-audit
|
||||
invariant-adversary → critiques → correctness, cross-component
|
||||
caller-audit → critiques → invariant-adversary, cross-component
|
||||
performance-reviewer → critiques → api, cross-component
|
||||
api-reviewer → critiques → correctness, performance
|
||||
serialization-reviewer → critiques → correctness, invariant-adversary
|
||||
test-reviewer → critiques → serialization, caller-audit
|
||||
design-reviewer → critiques → cross-component, invariant-adversary
|
||||
```
|
||||
|
||||
**Note:** The invariant-adversary and caller-audit agents are deliberately
|
||||
cross-linked with correctness and cross-component because their findings
|
||||
often reveal the same underlying bug from different angles (invariant
|
||||
violation vs reachable bad input vs data-flow mismatch).
|
||||
|
||||
Each agent should:
|
||||
1. Read the assigned agents' findings files
|
||||
2. Send a critique message to each assigned agent
|
||||
3. Respond to critiques received from other agents
|
||||
4. Update their own findings file with any revisions (upgraded/downgraded severity,
|
||||
withdrawn findings, new findings inspired by others)
|
||||
|
||||
#### Step 4c: Team lead collects debate results
|
||||
- Read all updated findings files
|
||||
- Review the debate messages
|
||||
- Build consensus: findings supported by 2+ agents → HIGH confidence
|
||||
- Write consensus document with final severity classifications
|
||||
|
||||
### 5. Consensus Phase
|
||||
Team lead synthesizes the debate into a consensus document:
|
||||
- Cross-reference overlapping findings across agents
|
||||
- Count agreement (majority = 2+ agents independently flagging or supporting)
|
||||
- Note disagreements and how they were resolved
|
||||
- Classify findings as HIGH/MEDIUM/LOW severity
|
||||
- Write consensus document
|
||||
|
||||
### 6. Summary Phase
|
||||
- Compile all validated findings ordered by severity
|
||||
- Include detailed bug analysis (root cause, vulnerable code paths)
|
||||
- Include suggested fixes
|
||||
- Note which findings were debated and the outcome
|
||||
- Output the complete review as your final response text (this becomes the PR
|
||||
comment verbatim), and also overwrite review-findings.md with the identical
|
||||
content as a recovery backstop
|
||||
|
||||
**Final report quality rules:**
|
||||
- The final report must be CLEAN and POLISHED. No stream-of-consciousness,
|
||||
no "Wait, actually...", no "on closer re-examination". Those belong in
|
||||
the working notes, not the output.
|
||||
- If a finding was raised during review but later disproven during debate
|
||||
or deeper analysis, REMOVE IT entirely from the final report. Do not
|
||||
include it with a retraction — just drop it.
|
||||
- If a finding was downgraded (e.g., Critical → Suggestion), present it
|
||||
at the final severity only. Do not narrate the severity change.
|
||||
- Each finding in the final report should read as a confident, verified
|
||||
conclusion — not a record of the analysis process.
|
||||
- The reader should never see the reviewer arguing with itself.
|
||||
|
||||
**REQUIRED output structure (so the PR page stays scrollable):**
|
||||
|
||||
Your final response — which becomes the PR comment verbatim — (and the
|
||||
identical contents of `review-findings.md`) MUST follow this exact structure.
|
||||
The summary appears first so reviewers can see HIGH findings at a glance;
|
||||
everything else is hidden behind a `<details>` block.
|
||||
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
<!-- One or two sentences of overall assessment. -->
|
||||
|
||||
**High-severity findings (N):**
|
||||
- **[file.cc:123]** One-line description of the issue. <!-- repeat per HIGH finding -->
|
||||
|
||||
<!-- If there are NO high-severity findings, write exactly: -->
|
||||
<!-- _No high-severity findings._ -->
|
||||
|
||||
<details>
|
||||
<summary>Full review (click to expand)</summary>
|
||||
|
||||
### Findings
|
||||
|
||||
#### :red_circle: HIGH
|
||||
|
||||
##### H1. <Title> — `file.cc:123`
|
||||
- **Issue:** ...
|
||||
- **Root cause:** ...
|
||||
- **Suggested fix:** ...
|
||||
|
||||
#### :yellow_circle: MEDIUM
|
||||
... (same structure: M1, M2, ...)
|
||||
|
||||
#### :green_circle: LOW / NIT
|
||||
... (same structure: L1, L2, ...)
|
||||
|
||||
### Cross-Component Analysis
|
||||
<!-- Execution-context table and assumption stress-test results. -->
|
||||
|
||||
### Positive Observations
|
||||
<!-- Optional: good patterns, clever optimizations. -->
|
||||
|
||||
</details>
|
||||
```
|
||||
|
||||
Rules for this structure:
|
||||
- The top-level `## Summary` and the bullet list of HIGH findings MUST stay
|
||||
outside the `<details>` block — they are always visible.
|
||||
- Every detail (per-finding root cause, fix, debate outcomes, cross-component
|
||||
analysis, positive observations) MUST live inside the `<details>` block.
|
||||
- Do NOT nest a `<details>` inside another `<details>`.
|
||||
- Do NOT add any text after the closing `</details>` — the comment-builder
|
||||
appends its own footer.
|
||||
- Your final response MUST be the review itself in this structure — never a
|
||||
meta-summary like "the review has been written to review-findings.md". The
|
||||
PR comment is generated verbatim from your final response.
|
||||
- If the review is partial (recovery path), still produce the summary block
|
||||
first, and put whatever was salvaged inside the `<details>` block.
|
||||
|
||||
## Review Checklist
|
||||
|
||||
### Context Phase (must be completed before agents spawn)
|
||||
- [ ] Subsystem deep-read — read changed files AND surrounding subsystem
|
||||
in depth (logic, edge cases, data flows, locking, concurrency)
|
||||
- [ ] Caller chain for every changed public/virtual method (3-5 levels up)
|
||||
- [ ] Critical decision points where callers branch on changed behavior
|
||||
- [ ] Callee chain with SIDE EFFECTS — downstream dependencies, new
|
||||
preconditions, AND mutations to shared state (section 2c)
|
||||
- [ ] Sibling implementations — how does the standard version handle same scenarios?
|
||||
- [ ] Invariants that callers rely on
|
||||
- [ ] Related functionality — existing helpers, patterns, conventions
|
||||
- [ ] Cross-component data consumers — for every data WRITTEN, find ALL readers
|
||||
and verify visibility rules match (section 2g)
|
||||
- [ ] Alternative execution contexts verified (section 2h table)
|
||||
- [ ] Assumption stress-test — for every design claim, list preconditions
|
||||
and construct counterexamples (section 2i)
|
||||
- [ ] Multi-component interactions (compaction, recovery, snapshots, iterators)
|
||||
- [ ] Configuration dependencies and unexpected option combinations
|
||||
- [ ] Potential pitfalls from caller-chain analysis
|
||||
- [ ] DB-mutex reachability checked through transitive callees; affected lock
|
||||
and unlock boundaries documented
|
||||
|
||||
### Review Phase (verified by agents)
|
||||
- [ ] Database semantics preserved (snapshot isolation, key ordering)
|
||||
- [ ] All error cases handled
|
||||
- [ ] Thread-safe with correct synchronization
|
||||
- [ ] No data races or deadlocks
|
||||
- [ ] Appropriate test coverage (edge cases, failure modes, system-level)
|
||||
- [ ] No unnecessary allocations or copies in hot paths
|
||||
- [ ] Backwards compatible
|
||||
- [ ] New APIs consistent with existing patterns and documented
|
||||
- [ ] Code follows RocksDB style conventions
|
||||
- [ ] Behavioral contracts with upstream callers preserved
|
||||
- [ ] All callers enumerated with parameter range table
|
||||
- [ ] Before/after CPU and I/O under the DB mutex compared, with call frequency,
|
||||
scaling, hidden callee work, and worst-case cost included
|
||||
- [ ] No significant DB-mutex-held work regression; unavoidable work is highly
|
||||
optimized, bounded, and supported by measurements when material
|
||||
|
||||
## Output Structure
|
||||
Your **final response text is the primary output** — it becomes the PR comment
|
||||
verbatim. The files below are working artifacts and recovery backstops only;
|
||||
they are NOT a substitute for outputting the full review in your final response.
|
||||
|
||||
Write these artifacts to the working directory root:
|
||||
- `review-findings.md` — Recovery backstop: incremental findings appended after
|
||||
each phase, overwritten with the final synthesized review at the end. Used
|
||||
only if the turn limit interrupts the run.
|
||||
- `context.md` — Codebase context (call chains, invariants)
|
||||
- `findings-*.md` — Per-agent findings (design, correctness, cross-component,
|
||||
invariant-adversary, caller-audit, performance, api, serialization, tests)
|
||||
- `consensus.md` — Cross-review consensus (post-debate)
|
||||
|
||||
|
||||
|
||||
## Team Structure
|
||||
```
|
||||
Team Lead (you)
|
||||
│
|
||||
├── Phase 2: Codebase Context (team lead or dedicated research agent)
|
||||
│ └── context-researcher (general-purpose agent)
|
||||
│ ├── Trace caller chains (3-5 levels up)
|
||||
│ ├── Trace callee chains (dependencies AND side effects)
|
||||
│ ├── Trace data consumers (who reads what the change writes?)
|
||||
│ └── Document invariants
|
||||
│
|
||||
├── Phase 3: Initial Review (parallel, run_in_background)
|
||||
│ │ (all agents receive context.md in their prompt)
|
||||
│ ├── design-reviewer (general-purpose agent)
|
||||
│ ├── correctness-reviewer (general-purpose agent)
|
||||
│ ├── cross-component-reviewer (general-purpose agent)
|
||||
│ ├── invariant-adversary (general-purpose agent) ← NEW
|
||||
│ ├── caller-audit (general-purpose agent) ← NEW
|
||||
│ ├── performance-reviewer (general-purpose agent)
|
||||
│ ├── api-reviewer (general-purpose agent)
|
||||
│ ├── serialization-reviewer (general-purpose agent)
|
||||
│ └── test-reviewer (general-purpose agent)
|
||||
│
|
||||
├── Phase 4: Debate (agents message each other)
|
||||
│ ├── correctness ↔ invariant-adversary, serialization
|
||||
│ ├── cross-component ↔ correctness, caller-audit
|
||||
│ ├── invariant-adversary ↔ correctness, cross-component
|
||||
│ ├── caller-audit ↔ invariant-adversary, cross-component
|
||||
│ ├── performance ↔ api, cross-component
|
||||
│ ├── api ↔ correctness, performance
|
||||
│ ├── serialization ↔ correctness, invariant-adversary
|
||||
│ ├── test-coverage ↔ serialization, caller-audit
|
||||
│ └── design ↔ cross-component, invariant-adversary
|
||||
│
|
||||
```
|
||||
|
||||
|
||||
## Agent Communication Protocol
|
||||
|
||||
### During Initial Review (Phase 3)
|
||||
- Each agent writes findings to its own file
|
||||
- Each agent sends a summary message to team lead when done
|
||||
- Agents do NOT communicate with each other yet
|
||||
|
||||
### During Debate (Phase 4)
|
||||
- Team lead sends each agent a message with instructions to:
|
||||
1. Read the assigned agents' findings files
|
||||
2. Send critique messages to those agents
|
||||
3. Respond to incoming critiques
|
||||
4. Update their own findings file with revisions
|
||||
- Each critique message should include:
|
||||
- Which finding they're addressing (e.g., "Correctness F1")
|
||||
- Whether they AGREE, DISAGREE, or want to REFINE
|
||||
- Their reasoning with code evidence
|
||||
- Suggested severity adjustment (if any)
|
||||
|
||||
### Message format example
|
||||
```
|
||||
To: correctness-reviewer
|
||||
Re: Your Finding F1
|
||||
|
||||
AGREE/DISAGREE/REFINE - [reasoning with code evidence].
|
||||
[Suggested severity adjustment if any.]
|
||||
```
|
||||
|
||||
## Review Anti-Patterns
|
||||
|
||||
These recurring failure modes lead to missed bugs. Each is detailed in the
|
||||
referenced section; this table is a quick-reference checklist.
|
||||
|
||||
| Anti-Pattern | Fix | Reference |
|
||||
|---|---|---|
|
||||
| Return-Value Tunnel Vision | Trace callee MUTATIONS, not just returns | Section 2c |
|
||||
| Default-Configuration Bias | Enumerate all execution contexts | Section 2h |
|
||||
| Assert-as-Proof | Try to BREAK every assert | Section 2i |
|
||||
| Write-Path-Only Analysis | Trace data readers, not just writers | Section 2g |
|
||||
| Confirmation-Seeking Research | Use adversarial prompts ("find where X fails") | Invariant Adversary agent |
|
||||
| Data-Flow vs Control-Flow Confusion | Separate who CALLS from who READS the data | Section 2g |
|
||||
@@ -1,67 +0,0 @@
|
||||
# Manual (Local) Code Review — Lightweight Wrapper
|
||||
|
||||
## What this is
|
||||
|
||||
A resource-light, **single-reviewer** variant of `claude_md/ci_review_prompt.md`
|
||||
for running a review by hand in a local Claude Code / Devmate session. It reuses
|
||||
the full CI review *methodology* but drops the multi-agent orchestration and the
|
||||
CI-only file-persistence machinery, to approximate the heavyweight result at a
|
||||
fraction of the cost.
|
||||
|
||||
**Scope: LOCAL manual review only. This file is NOT used by CI.** CI uses
|
||||
`claude_md/ci_review_prompt.md`.
|
||||
|
||||
## How to use
|
||||
|
||||
Read `claude_md/ci_review_prompt.md` for the complete methodology — the analysis
|
||||
techniques (caller-chain, callee side-effects, cross-component data consumers,
|
||||
alternative execution contexts, assumption stress-testing), the per-perspective
|
||||
reviewer instructions, the review checklist, and the anti-patterns table.
|
||||
|
||||
Then apply that methodology with the OVERRIDES below. **Where this file
|
||||
conflicts with `ci_review_prompt.md`, this file wins.**
|
||||
|
||||
## Overrides (this is what makes it lightweight)
|
||||
|
||||
### 1. Single reviewer — no team, no subagents
|
||||
- Do NOT create a team, spawn subagents, or run parallel/background agents.
|
||||
- Do NOT run the round-robin Debate phase or the Consensus phase.
|
||||
- Instead, YOU personally apply each reviewer role from `ci_review_prompt.md`
|
||||
(Design, Correctness, Cross-Component & Adversarial, Invariant Adversary,
|
||||
Caller-Context, Performance, API/Compat, Serialization, Test Coverage) as
|
||||
sequential *lenses* in one pass. Spend a few focused minutes per lens. Skip
|
||||
lenses that plainly don't apply (e.g., Serialization when there is no on-disk
|
||||
or wire-format change) and note the skip in one line.
|
||||
|
||||
### 2. No intermediate files
|
||||
- Do NOT write `context.md`, `findings-*.md`, `consensus.md`, or
|
||||
`review-findings.md`. Keep working notes in your reasoning, not on disk.
|
||||
- Rationale: those files exist only so CI can recover partial results when an
|
||||
ephemeral runner hits the turn limit — a local session has neither problem.
|
||||
`ci_review_prompt.md` already outputs the review as its final response, so
|
||||
skipping the file loses nothing here.
|
||||
|
||||
### 3. Right-size the effort
|
||||
- Do the Codebase Context phase, but proportionally: trace the 2-3 most
|
||||
load-bearing call chains and the highest-risk cross-component data consumers,
|
||||
rather than exhaustively enumerating every caller 3-5 levels up.
|
||||
- Prioritize the highest-signal lenses for RocksDB: **Correctness**,
|
||||
**Cross-Component & Adversarial**, and **Assumption Stress-Testing**. These
|
||||
catch the bugs that matter most; give them the most attention.
|
||||
- Escalation clause: if a thread looks dangerous, go deep on that specific
|
||||
thread even though the overall pass is modest. Modest is the default, not a cap.
|
||||
|
||||
### 4. Identify the review target locally
|
||||
- Unlike CI, the diff is NOT pre-pasted into this prompt. Determine what to
|
||||
review from the user's request against the local worktree — e.g. the current
|
||||
commit (`git show`), uncommitted changes (`git diff` / `git diff --staged`),
|
||||
a named commit range, or a PR — and read the changed files plus their
|
||||
surrounding context directly from the repo. When in doubt, include all changes
|
||||
not yet upstream, as in
|
||||
`git diff "$(git merge-base upstream/main HEAD 2> /dev/null || git merge-base origin/main HEAD 2> /dev/null)"`
|
||||
plus any untracked files (`git status`) that seem relevant.
|
||||
|
||||
## Reminder
|
||||
|
||||
The goal is a thorough *single* reviewer, not a 9-agent debate: depth where it
|
||||
matters, brevity everywhere else.
|
||||
@@ -1,106 +0,0 @@
|
||||
# RocksDB Diff and Pull Request Summary Guidance
|
||||
|
||||
This guidance applies to both internal Phabricator diff summaries and external
|
||||
GitHub pull request summaries for changes under `fbcode/internal_repo_rocksdb/`.
|
||||
|
||||
## Goal
|
||||
|
||||
Write each diff or pull request summary for a reviewer who has not read the
|
||||
patch. The summary must explain the behavioral story and the evidence for it,
|
||||
not merely inventory the edited files or symbols.
|
||||
|
||||
Every new or updated diff or pull request summary must clearly cover:
|
||||
|
||||
1. Why the change is required.
|
||||
2. What the previous behavior was, including the failure mode or limitation.
|
||||
3. What the new behavior is.
|
||||
4. What changed in the implementation.
|
||||
5. Safety boundaries, compatibility, and unsupported or intentionally deferred
|
||||
cases.
|
||||
6. Tests performed and known limitations of the validation.
|
||||
|
||||
Use explicit headings for a broad, subtle, or high-risk change. A small,
|
||||
focused change may combine these points into a few paragraphs, but none may be
|
||||
left implicit when it affects a review decision.
|
||||
|
||||
## What Good RocksDB Summaries Make Concrete
|
||||
|
||||
- Name the exact conditions that activate a bug or behavior: relevant options,
|
||||
call ordering, storage mode, concurrency mode, file format, platform, or
|
||||
workload shape. Also state important cases that are not affected.
|
||||
- Explain the causal chain from the old behavior to its externally observable
|
||||
result. For correctness fixes, distinguish a symptom from the underlying
|
||||
invariant violation.
|
||||
- Describe the new contract before implementation mechanics. Then identify the
|
||||
essential implementation choices and why they are sufficient.
|
||||
- Call out API, ABI, serialized-format, behavioral, and performance
|
||||
compatibility where relevant. For additive persisted fields, state how older
|
||||
data is interpreted and whether older readers remain supported.
|
||||
- State safety boundaries precisely: defaults, feature gates, fallback paths,
|
||||
ownership and lifetime constraints, memory-ordering assumptions, and cases
|
||||
deliberately postponed to a follow-up.
|
||||
- Support performance claims with a baseline, workload and configuration,
|
||||
measurement method, and results. Report meaningful tradeoffs, not only the
|
||||
winning metric.
|
||||
- Make the test plan evidence-based. Name the tests and configurations, say
|
||||
what behavior each proves, and report failures, timeouts, untested platforms,
|
||||
or stale pre-rebase results honestly. For a regression test, say how it fails
|
||||
without the fix when that was verified.
|
||||
- Separate incidental cleanup or a pre-existing test fix from the primary
|
||||
change, and explain why it belongs in the diff.
|
||||
|
||||
Avoid vague claims such as "improves performance," "fixes an issue," or "tests
|
||||
pass." Avoid copying the patch into prose, exhaustive file-by-file narration,
|
||||
raw command output, and claims broader than the evidence.
|
||||
|
||||
## Suggested Structure
|
||||
|
||||
Adapt this structure to the change; do not keep empty or irrelevant sections.
|
||||
|
||||
```text
|
||||
Summary:
|
||||
|
||||
Why the change is required:
|
||||
<User or system impact, and why the current behavior is inadequate.>
|
||||
|
||||
Previous behavior:
|
||||
<Old contract or mechanism, triggering conditions, and observable result.>
|
||||
|
||||
New behavior:
|
||||
<New contract and externally visible effect.>
|
||||
|
||||
Implementation:
|
||||
<Essential design and code changes; omit routine edit-by-edit narration.>
|
||||
|
||||
Safety, compatibility, and limitations:
|
||||
<Defaults, unaffected paths, compatibility, unsupported cases, and follow-ups.>
|
||||
|
||||
Test Plan:
|
||||
<Exact tests/benchmarks, configurations, what they demonstrate, and gaps.>
|
||||
```
|
||||
|
||||
For a focused bug fix, a cohesive narrative can be clearer than six headings:
|
||||
problem and root cause, trigger and unaffected cases, fix, then quantified or
|
||||
counterfactual validation. For a multi-part change, labeled bullets such as
|
||||
`Fix`, `Add`, and `Change` can make the implementation and review surface easy
|
||||
to scan.
|
||||
|
||||
## Reference Pull Request Summaries
|
||||
|
||||
- [PR #15216](https://github.com/facebook/rocksdb/pull/15216) is a strong
|
||||
focused bug-fix example. It traces stale iterator state to readahead behavior
|
||||
and dropped keys, identifies the exact prerequisites and unaffected mmap
|
||||
case, gives before/after measurements, and explains how the regression test
|
||||
fails when the fix is reverted.
|
||||
- [PR #15218](https://github.com/facebook/rocksdb/pull/15218) is a concise
|
||||
example of explicit `Why`, `Previous behavior`, `New behavior`,
|
||||
`Implementation`, and `Safety boundaries and unsupported cases` sections.
|
||||
- Peter Dillinger's [PR #15231](https://github.com/facebook/rocksdb/pull/15231)
|
||||
is a strong recent multi-part example. Its `Fix`/`Add`/`Change` bullets
|
||||
separate the behaviors, its compatibility sentence explains how old files
|
||||
read back, and its test plan maps each new persisted property to concrete
|
||||
coverage while explaining an adjacent test adjustment.
|
||||
|
||||
Use these pull requests as models for reasoning, specificity, and evidence. Do
|
||||
not copy their length or headings mechanically; scale the summary to the risk
|
||||
and complexity of the change.
|
||||
Loaded 100 of 1022 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user