mirror of
https://github.com/facebook/rocksdb.git
synced 2026-11-07 03:22:34 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fcd07e0f78 | ||
|
|
0efb576ca3 | ||
|
|
53649ce36b | ||
|
|
6b389b43ff | ||
|
|
49ce8a1064 | ||
|
|
b8d41c55e7 | ||
|
|
3b1ce121c2 | ||
|
|
17e3628cb5 | ||
|
|
8bcbed2e93 |
No files matched your search
+74
-13
@@ -146,12 +146,9 @@ commands:
|
||||
install-maven:
|
||||
steps:
|
||||
- run:
|
||||
name: Install Maven
|
||||
name: Install maven
|
||||
command: |
|
||||
wget --no-check-certificate https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz
|
||||
tar zxf apache-maven-3.9.6-bin.tar.gz
|
||||
echo "export M2_HOME=$(pwd)/apache-maven-3.9.6" >> $BASH_ENV
|
||||
echo 'export PATH=$M2_HOME/bin:$PATH' >> $BASH_ENV
|
||||
sudo apt-get update -y && sudo apt-get install -y maven
|
||||
|
||||
setup-folly:
|
||||
steps:
|
||||
@@ -234,7 +231,6 @@ executors:
|
||||
- image: zjay437/rocksdb:0.6
|
||||
linux-java-docker:
|
||||
docker:
|
||||
# This is the Docker Image used for building RocksJava releases, see: https://github.com/evolvedbinary/docker-rocksjava
|
||||
- image: evolvedbinary/rocksjava:centos6_x64-be
|
||||
|
||||
jobs:
|
||||
@@ -248,7 +244,7 @@ jobs:
|
||||
- increase-max-open-files-on-macos
|
||||
- install-gflags-on-macos
|
||||
- pre-steps-macos
|
||||
- run: ulimit -S -n `ulimit -H -n` && make V=1 J=16 -j16 all
|
||||
- run: ulimit -S -n `ulimit -H -n` && OPT=-DCIRCLECI make V=1 J=16 -j16 all
|
||||
- post-steps
|
||||
|
||||
build-macos-cmake:
|
||||
@@ -627,7 +623,7 @@ jobs:
|
||||
- windows-build-steps
|
||||
|
||||
build-linux-java:
|
||||
executor: linux-java-docker
|
||||
executor: linux-docker
|
||||
resource_class: large
|
||||
steps:
|
||||
- pre-steps
|
||||
@@ -640,13 +636,17 @@ jobs:
|
||||
which javac && javac -version
|
||||
- run:
|
||||
name: "Test RocksDBJava"
|
||||
command: scl enable devtoolset-7 'make V=1 J=8 -j8 jtest'
|
||||
command: make V=1 J=8 -j8 jtest
|
||||
- post-steps
|
||||
|
||||
build-linux-java-pmd:
|
||||
executor: linux-java-docker
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
resource_class: large
|
||||
environment:
|
||||
JAVA_HOME: /usr/lib/jvm/java-8-openjdk-amd64
|
||||
steps:
|
||||
- install-maven
|
||||
- pre-steps
|
||||
- run:
|
||||
name: "Set Java Environment"
|
||||
@@ -655,10 +655,9 @@ jobs:
|
||||
echo 'export PATH=$JAVA_HOME/bin:$PATH' >> $BASH_ENV
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- install-maven
|
||||
- run:
|
||||
name: "PMD RocksDBJava"
|
||||
command: scl enable devtoolset-7 'make V=1 J=8 -j8 jpmd'
|
||||
command: make V=1 J=8 -j8 jpmd
|
||||
- post-pmd-steps
|
||||
|
||||
build-linux-java-static:
|
||||
@@ -878,11 +877,68 @@ jobs:
|
||||
- perform-benchmarks
|
||||
- post-benchmarks
|
||||
|
||||
workflows: # Only jobs that haven't been successfully migrated to GitHub Actions
|
||||
workflows:
|
||||
version: 2
|
||||
jobs-linux-run-tests:
|
||||
jobs:
|
||||
- build-linux
|
||||
- build-linux-cmake-with-folly
|
||||
- build-linux-cmake-with-folly-lite-no-test
|
||||
- build-linux-gcc-7-with-folly
|
||||
- build-linux-gcc-7-with-folly-lite-no-test
|
||||
- build-linux-cmake-with-folly-coroutines
|
||||
- build-linux-cmake-with-benchmark
|
||||
- build-linux-encrypted_env-no_compression
|
||||
jobs-linux-run-tests-san:
|
||||
jobs:
|
||||
- build-linux-clang10-asan
|
||||
- build-linux-clang10-ubsan
|
||||
- build-linux-clang10-mini-tsan
|
||||
- build-linux-static_lib-alt_namespace-status_checked
|
||||
jobs-linux-no-test-run:
|
||||
jobs:
|
||||
- build-linux-release
|
||||
- build-linux-release-rtti
|
||||
- build-examples
|
||||
- build-fuzzers
|
||||
- build-linux-clang-no_test_run
|
||||
- build-linux-clang-13-no_test_run
|
||||
- build-linux-gcc-8-no_test_run
|
||||
- build-linux-gcc-10-cxx20-no_test_run
|
||||
- build-linux-gcc-11-no_test_run
|
||||
- build-linux-arm-cmake-no_test_run
|
||||
jobs-linux-other-checks:
|
||||
jobs:
|
||||
- build-linux-clang10-clang-analyze
|
||||
- build-linux-unity-and-headers
|
||||
- build-linux-mini-crashtest
|
||||
jobs-windows:
|
||||
jobs:
|
||||
- build-windows-vs2022-avx2
|
||||
- build-windows-vs2022
|
||||
- build-windows-vs2019
|
||||
- build-cmake-mingw
|
||||
jobs-java:
|
||||
jobs:
|
||||
- build-linux-java
|
||||
- build-linux-java-static
|
||||
- build-macos-java
|
||||
- build-macos-java-static
|
||||
- build-macos-java-static-universal
|
||||
- build-linux-java-pmd
|
||||
jobs-macos:
|
||||
jobs:
|
||||
- build-macos
|
||||
- build-macos-cmake:
|
||||
run_even_tests: true
|
||||
- build-macos-cmake:
|
||||
run_even_tests: false
|
||||
jobs-linux-arm:
|
||||
jobs:
|
||||
- build-linux-arm
|
||||
build-fuzzers:
|
||||
jobs:
|
||||
- build-fuzzers
|
||||
benchmark-linux:
|
||||
triggers:
|
||||
- schedule:
|
||||
@@ -902,4 +958,9 @@ workflows: # Only jobs that haven't been successfully migrated to GitHub Actions
|
||||
only:
|
||||
- main
|
||||
jobs:
|
||||
- build-format-compatible
|
||||
- build-linux-arm-test-full
|
||||
- build-linux-run-microbench
|
||||
- build-linux-non-shm
|
||||
- build-linux-clang-13-asan-ubsan-with-folly
|
||||
- build-linux-valgrind
|
||||
@@ -1,7 +0,0 @@
|
||||
name: build-folly
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Build folly and dependencies
|
||||
run: make build_folly
|
||||
shell: bash
|
||||
@@ -1,8 +0,0 @@
|
||||
name: build-for-benchmarks
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- name: Linux build for benchmarks
|
||||
run: make V=1 J=8 -j8 release
|
||||
shell: bash
|
||||
@@ -1,10 +0,0 @@
|
||||
name: increase-max-open-files-on-macos
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Increase max open files
|
||||
run: |-
|
||||
sudo sysctl -w kern.maxfiles=1048576
|
||||
sudo sysctl -w kern.maxfilesperproc=1048576
|
||||
sudo launchctl limit maxfiles 1048576
|
||||
shell: bash
|
||||
@@ -1,7 +0,0 @@
|
||||
name: install-gflags-on-macos
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install gflags on macos
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install gflags
|
||||
shell: bash
|
||||
@@ -1,7 +0,0 @@
|
||||
name: install-gflags
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install gflags
|
||||
run: sudo apt-get update -y && sudo apt-get install -y libgflags-dev
|
||||
shell: bash
|
||||
@@ -1,9 +0,0 @@
|
||||
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
|
||||
@@ -1,11 +0,0 @@
|
||||
name: install-maven
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install Maven
|
||||
run: |
|
||||
wget --no-check-certificate https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz
|
||||
tar zxf apache-maven-3.9.6-bin.tar.gz
|
||||
echo "export M2_HOME=$(pwd)/apache-maven-3.9.6" >> $GITHUB_ENV
|
||||
echo "$(pwd)/apache-maven-3.9.6/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
@@ -1,22 +0,0 @@
|
||||
name: perform-benchmarks
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Test low-variance benchmarks
|
||||
run: "./tools/benchmark_ci.py --db_dir ${{ runner.temp }}/rocksdb-benchmark-datadir --output_dir ${{ runner.temp }}/benchmark-results --num_keys 20000000"
|
||||
env:
|
||||
LD_LIBRARY_PATH: "/usr/local/lib"
|
||||
DURATION_RO: 300
|
||||
DURATION_RW: 500
|
||||
NUM_THREADS: 1
|
||||
MAX_BACKGROUND_JOBS: 4
|
||||
CI_TESTS_ONLY: 'true'
|
||||
WRITE_BUFFER_SIZE_MB: 16
|
||||
TARGET_FILE_SIZE_BASE_MB: 16
|
||||
MAX_BYTES_FOR_LEVEL_BASE_MB: 64
|
||||
COMPRESSION_TYPE: none
|
||||
CACHE_INDEX_AND_FILTER_BLOCKS: 1
|
||||
MIN_LEVEL_TO_COMPRESS: 3
|
||||
CACHE_SIZE_MB: 10240
|
||||
MB_WRITE_PER_SEC: 2
|
||||
shell: bash
|
||||
@@ -1,17 +0,0 @@
|
||||
name: post-benchmarks
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Upload Benchmark Results artifact
|
||||
uses: actions/upload-artifact@v4.0.0
|
||||
with:
|
||||
name: benchmark-results
|
||||
path: "${{ runner.temp }}/benchmark-results/**"
|
||||
if-no-files-found: error
|
||||
- name: Send benchmark report to visualisation
|
||||
run: |-
|
||||
set +e
|
||||
set +o pipefail
|
||||
./build_tools/benchmark_log_tool.py --tsvfile ${{ runner.temp }}/benchmark-results/report.tsv --esdocument https://search-rocksdb-bench-k2izhptfeap2hjfxteolsgsynm.us-west-2.es.amazonaws.com/bench_test3_rix/_doc
|
||||
true
|
||||
shell: bash
|
||||
@@ -1,38 +0,0 @@
|
||||
name: post-steps
|
||||
description: Steps that are taken after a RocksDB job
|
||||
inputs:
|
||||
artifact-prefix:
|
||||
description: Prefix to append to the name of artifacts that are uploaded
|
||||
required: true
|
||||
default: "${{ github.job }}"
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Upload Test Results artifact
|
||||
uses: actions/upload-artifact@v4.0.0
|
||||
with:
|
||||
name: "${{ inputs.artifact-prefix }}-test-results"
|
||||
path: "${{ runner.temp }}/test-results/**"
|
||||
- name: Upload DB LOG file artifact
|
||||
uses: actions/upload-artifact@v4.0.0
|
||||
with:
|
||||
name: "${{ inputs.artifact-prefix }}-db-log-file"
|
||||
path: LOG
|
||||
- name: Copy Test Logs (on Failure)
|
||||
if: ${{ failure() }}
|
||||
run: |
|
||||
mkdir -p ${{ runner.temp }}/failure-test-logs
|
||||
cp -r t/* ${{ runner.temp }}/failure-test-logs
|
||||
shell: bash
|
||||
- name: Upload Test Logs (on Failure) artifact
|
||||
uses: actions/upload-artifact@v4.0.0
|
||||
with:
|
||||
name: "${{ inputs.artifact-prefix }}-failure-test-logs"
|
||||
path: ${{ runner.temp }}/failure-test-logs/**
|
||||
if-no-files-found: ignore
|
||||
- name: Upload Core Dumps artifact
|
||||
uses: actions/upload-artifact@v4.0.0
|
||||
with:
|
||||
name: "${{ inputs.artifact-prefix }}-core-dumps"
|
||||
path: "core.*"
|
||||
if-no-files-found: ignore
|
||||
@@ -1,5 +0,0 @@
|
||||
name: pre-steps-macos
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
@@ -1,18 +0,0 @@
|
||||
name: pre-steps
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Setup Environment Variables
|
||||
run: |-
|
||||
echo "GTEST_THROW_ON_FAILURE=0" >> "$GITHUB_ENV"
|
||||
echo "GTEST_OUTPUT=\"xml:${{ runner.temp }}/test-results/\"" >> "$GITHUB_ENV"
|
||||
echo "SKIP_FORMAT_BUCK_CHECKS=1" >> "$GITHUB_ENV"
|
||||
echo "GTEST_COLOR=1" >> "$GITHUB_ENV"
|
||||
echo "CTEST_OUTPUT_ON_FAILURE=1" >> "$GITHUB_ENV"
|
||||
echo "CTEST_TEST_TIMEOUT=300" >> "$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,7 +0,0 @@
|
||||
name: setup-folly
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Checkout folly sources
|
||||
run: make checkout_folly
|
||||
shell: bash
|
||||
@@ -1,20 +0,0 @@
|
||||
name: build-folly
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Fix repo ownership
|
||||
# Needed in some cases, as safe.directory setting doesn't take effect
|
||||
# under env -i
|
||||
run: chown `whoami` . || true
|
||||
shell: bash
|
||||
- name: Set upstream
|
||||
run: git remote add upstream https://github.com/facebook/rocksdb.git
|
||||
shell: bash
|
||||
- name: Fetch upstream
|
||||
run: git fetch upstream
|
||||
shell: bash
|
||||
- name: Git status
|
||||
# NOTE: some old branch builds under check_format_compatible.sh invoke
|
||||
# git under env -i
|
||||
run: git status && git remote -v && env -i git branch
|
||||
shell: bash
|
||||
@@ -1,54 +0,0 @@
|
||||
name: windows-build-steps
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.3.1
|
||||
- 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.1.8
|
||||
SNAPPY_INCLUDE: ${{ github.workspace }}/thirdparty/snappy-1.1.8;${{ github.workspace }}/thirdparty/snappy-1.1.8/build
|
||||
SNAPPY_LIB_DEBUG: ${{ github.workspace }}/thirdparty/snappy-1.1.8/build/Debug/snappy.lib
|
||||
run: |-
|
||||
# NOTE: if ... Exit $LASTEXITCODE lines needed to exit and report failure
|
||||
echo ===================== Install Dependencies =====================
|
||||
choco install liberica8jdk -y
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
mkdir $Env:THIRDPARTY_HOME
|
||||
cd $Env:THIRDPARTY_HOME
|
||||
echo "Building Snappy dependency..."
|
||||
curl -Lo snappy-1.1.8.zip https://github.com/google/snappy/archive/refs/tags/1.1.8.zip
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
unzip -q snappy-1.1.8.zip
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
cd snappy-1.1.8
|
||||
mkdir build
|
||||
cd build
|
||||
& cmake -G "$Env:CMAKE_GENERATOR" ..
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
msbuild Snappy.sln -maxCpuCount -property:Configuration=Debug -property:Platform=x64
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
echo ======================== Build RocksDB =========================
|
||||
cd ${{ github.workspace }}
|
||||
$env:Path = $env:JAVA_HOME + ";" + $env:Path
|
||||
mkdir build
|
||||
cd build
|
||||
& cmake -G "$Env:CMAKE_GENERATOR" -DCMAKE_BUILD_TYPE=Debug -DOPTDBG=1 -DPORTABLE="$Env:CMAKE_PORTABLE" -DSNAPPY=1 -DJNI=1 ..
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
cd ..
|
||||
echo "Building with VS version: $Env:CMAKE_GENERATOR"
|
||||
msbuild build/rocksdb.sln -maxCpuCount -property:Configuration=Debug -property:Platform=x64
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
echo ========================= Test RocksDB =========================
|
||||
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
|
||||
@@ -1,15 +0,0 @@
|
||||
name: facebook/rocksdb/benchmark-linux
|
||||
on: workflow_dispatch
|
||||
jobs:
|
||||
# FIXME: when this job is fixed, it should be given a cron schedule like
|
||||
# schedule:
|
||||
# - cron: 0 * * * *
|
||||
# workflow_dispatch:
|
||||
benchmark-linux:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/build-for-benchmarks"
|
||||
- uses: "./.github/actions/perform-benchmarks"
|
||||
- uses: "./.github/actions/post-benchmarks"
|
||||
@@ -1,18 +0,0 @@
|
||||
name: facebook/rocksdb/nightly
|
||||
on: workflow_dispatch
|
||||
jobs:
|
||||
# These jobs would be in nightly but are failing or otherwise broken for
|
||||
# some reason.
|
||||
build-linux-arm-test-full:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: arm64large
|
||||
container:
|
||||
image: ubuntu-2004:202111-02
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/install-gflags"
|
||||
- run: make V=1 J=4 -j4 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
@@ -1,98 +0,0 @@
|
||||
name: facebook/rocksdb/nightly
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 9 * * *
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build-format-compatible:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
with:
|
||||
fetch-depth: 0 # Need full repo history
|
||||
fetch-tags: true
|
||||
- uses: "./.github/actions/setup-upstream"
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- name: test
|
||||
run: |-
|
||||
export TEST_TMPDIR=/dev/shm/rocksdb
|
||||
rm -rf /dev/shm/rocksdb
|
||||
mkdir /dev/shm/rocksdb
|
||||
git config --global --add safe.directory /__w/rocksdb/rocksdb
|
||||
tools/check_format_compatible.sh
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-run-microbench:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: DEBUG_LEVEL=0 make -j32 run_microbench
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-non-shm:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
env:
|
||||
TEST_TMPDIR: "/tmp/rocksdb_test_tmp"
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: make V=1 -j32 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-clang-13-asan-ubsan-with-folly:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- uses: "./.github/actions/build-folly"
|
||||
- run: CC=clang-13 CXX=clang++-13 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-valgrind:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: PORTABLE=1 make V=1 -j32 valgrind_test
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-windows-vs2022-avx2:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: windows-2022
|
||||
env:
|
||||
CMAKE_GENERATOR: Visual Studio 17 2022
|
||||
CMAKE_PORTABLE: AVX2
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/windows-build-steps"
|
||||
build-windows-vs2022:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: windows-2022
|
||||
env:
|
||||
CMAKE_GENERATOR: Visual Studio 17 2022
|
||||
CMAKE_PORTABLE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/windows-build-steps"
|
||||
@@ -1,46 +0,0 @@
|
||||
name: facebook/rocksdb/pr-jobs-candidate
|
||||
on: workflow_dispatch
|
||||
jobs:
|
||||
# These jobs would be in pr-jobs but are failing or otherwise broken for
|
||||
# some reason.
|
||||
# =========================== ARM Jobs ============================ #
|
||||
build-linux-arm:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: arm64large # GitHub hosted ARM runners do not yet exist
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/install-gflags"
|
||||
- run: ROCKSDBTESTS_PLATFORM_DEPENDENT=only make V=1 J=4 -j4 all_but_some_tests check_some
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-arm-cmake-no_test_run:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: arm64large # GitHub hosted ARM runners do not yet exist
|
||||
env:
|
||||
JAVA_HOME: "/usr/lib/jvm/java-8-openjdk-arm64"
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/install-gflags"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
echo 'export PATH=$JAVA_HOME/bin:$PATH' >> $BASH_ENV
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- name: Build with cmake
|
||||
run: |-
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=0 -DWITH_GFLAGS=1 -DWITH_BENCHMARK_TOOLS=0 -DWITH_TOOLS=0 -DWITH_CORE_TOOLS=1 ..
|
||||
make -j4
|
||||
- name: Build Java with cmake
|
||||
run: |-
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DJNI=1 -DCMAKE_BUILD_TYPE=Release -DWITH_GFLAGS=1 ..
|
||||
make -j4 rocksdb rocksdbjni
|
||||
- uses: "./.github/actions/post-steps"
|
||||
@@ -1,608 +0,0 @@
|
||||
name: facebook/rocksdb/pr-jobs
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
# NOTE: multiple workflows would be recommended, but the current GHA UI in
|
||||
# PRs doesn't make it clear when there's an overall error with a workflow,
|
||||
# making it easy to overlook something broken. Grouping everything into one
|
||||
# workflow minimizes the problem because it will be suspicious if there are
|
||||
# no GHA results.
|
||||
#
|
||||
# The if: ${{ github.repository_owner == 'facebook' }} lines prevent the
|
||||
# jobs from attempting to run on repo forks, because of a few problems:
|
||||
# * runs-on labels are repository (owner) specific, so the job might wait
|
||||
# for days waiting for a runner that simply isn't available.
|
||||
# * Pushes to branches on forks for pull requests (the normal process) would
|
||||
# run the workflow jobs twice: once in the pull-from fork and once for the PR
|
||||
# destination repo. This is wasteful and dumb.
|
||||
# * It is not known how to avoid copy-pasting the line to each job,
|
||||
# increasing the risk of misconfiguration, especially on forks that might
|
||||
# want to run with this GHA setup.
|
||||
#
|
||||
# DEBUGGING WITH SSH: Temporarily add this as a job step, either before the
|
||||
# step of interest without the "if:" line or after the failing step with the
|
||||
# "if:" line. Then use ssh command printed in CI output.
|
||||
# - name: Setup tmate session # TEMPORARY!
|
||||
# if: ${{ failure() }}
|
||||
# uses: mxschmitt/action-tmate@v3
|
||||
# with:
|
||||
# limit-access-to-actor: true
|
||||
|
||||
# ======================== Fast Initial Checks ====================== #
|
||||
check-format-and-targets:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
with:
|
||||
fetch-depth: 0 # Need full checkout to determine merge base
|
||||
fetch-tags: true
|
||||
- uses: "./.github/actions/setup-upstream"
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
- name: Install Dependencies
|
||||
run: python -m pip install --upgrade pip
|
||||
- name: Install argparse
|
||||
run: pip install argparse
|
||||
- name: Download clang-format-diff.py
|
||||
run: wget https://raw.githubusercontent.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
|
||||
# ========================= Linux With Tests ======================== #
|
||||
build-linux:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: make V=1 J=32 -j32 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-cmake-mingw:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
|
||||
- name: Build cmake-mingw
|
||||
run: |-
|
||||
export PATH=$JAVA_HOME/bin:$PATH
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
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/post-steps"
|
||||
build-linux-cmake-with-folly:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- uses: "./.github/actions/build-folly"
|
||||
- run: "(mkdir build && cd build && cmake -DUSE_FOLLY=1 -DWITH_GFLAGS=1 -DROCKSDB_BUILD_SHARED=0 .. && make V=1 -j20 && ctest -j20)"
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-cmake-with-folly-lite-no-test:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- run: "(mkdir build && cd build && cmake -DUSE_FOLLY_LITE=1 -DWITH_GFLAGS=1 .. && make V=1 -j20)"
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-gcc-7-with-folly:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- uses: "./.github/actions/build-folly"
|
||||
- run: USE_FOLLY=1 LIB_MODE=static CC=gcc-7 CXX=g++-7 V=1 make -j32 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-gcc-7-with-folly-lite-no-test:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- run: USE_FOLLY_LITE=1 CC=gcc-7 CXX=g++-7 V=1 make -j32 all
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-cmake-with-folly-coroutines:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
env:
|
||||
CC: gcc-10
|
||||
CXX: g++-10
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- uses: "./.github/actions/setup-folly"
|
||||
- uses: "./.github/actions/build-folly"
|
||||
- run: "(mkdir build && cd build && cmake -DUSE_COROUTINES=1 -DWITH_GFLAGS=1 -DROCKSDB_BUILD_SHARED=0 .. && make V=1 -j20 && ctest -j20)"
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-cmake-with-benchmark:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: mkdir build && cd build && cmake -DWITH_GFLAGS=1 -DWITH_BENCHMARK=1 .. && make V=1 -j20 && ctest -j20
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-encrypted_env-no_compression:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- 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 compression types: kNoCompression$' # Verify no compiled in compression\n"
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ======================== Linux No Test Runs ======================= #
|
||||
build-linux-release:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- run: make V=1 -j32 LIB_MODE=shared release
|
||||
- run: ls librocksdb.so
|
||||
- run: "./db_stress --version"
|
||||
- run: make clean
|
||||
- run: make V=1 -j32 release
|
||||
- run: ls librocksdb.a
|
||||
- run: "./db_stress --version"
|
||||
- run: make clean
|
||||
- run: apt-get remove -y libgflags-dev
|
||||
- run: make V=1 -j32 LIB_MODE=shared release
|
||||
- run: ls librocksdb.so
|
||||
- run: if ./db_stress --version; then false; else true; fi
|
||||
- run: make clean
|
||||
- run: make V=1 -j32 release
|
||||
- run: ls librocksdb.a
|
||||
- run: if ./db_stress --version; then false; else true; fi
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-release-rtti:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 8-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- run: USE_RTTI=1 DEBUG_LEVEL=0 make V=1 -j16 static_lib tools db_bench
|
||||
- run: "./db_stress --version"
|
||||
- run: make clean
|
||||
- run: apt-get remove -y libgflags-dev
|
||||
- run: USE_RTTI=1 DEBUG_LEVEL=0 make V=1 -j16 static_lib tools db_bench
|
||||
- run: if ./db_stress --version; then false; else true; fi
|
||||
build-examples:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- name: Build examples
|
||||
run: make V=1 -j4 static_lib && cd examples && make V=1 -j4
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-fuzzers:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- name: Build rocksdb lib
|
||||
run: CC=clang-13 CXX=clang++-13 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"
|
||||
build-linux-clang-no_test_run:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 8-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- run: CC=clang CXX=clang++ USE_CLANG=1 PORTABLE=1 make V=1 -j16 all
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-clang-13-no_test_run:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: CC=clang-13 CXX=clang++-13 USE_CLANG=1 make -j32 all microbench
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-gcc-8-no_test_run:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: CC=gcc-8 CXX=g++-8 V=1 make -j32 all
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-gcc-10-cxx20-no_test_run:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: CC=gcc-10 CXX=g++-10 V=1 ROCKSDB_CXX_STANDARD=c++20 make -j32 all
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-gcc-11-no_test_run:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: LIB_MODE=static CC=gcc-11 CXX=g++-11 V=1 make -j32 all microbench
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ======================== Linux Other Checks ======================= #
|
||||
build-linux-clang10-clang-analyze:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: CC=clang-10 CXX=clang++-10 ROCKSDB_DISABLE_ALIGNED_NEW=1 CLANG_ANALYZER="/usr/bin/clang++-10" CLANG_SCAN_BUILD=scan-build-10 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: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: gcc:latest
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- run: apt-get update -y && apt-get install -y libgflags-dev
|
||||
- name: Unity build
|
||||
run: make V=1 -j8 unity_test
|
||||
- run: make V=1 -j8 -k check-headers
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-mini-crashtest:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: ulimit -S -n `ulimit -H -n` && make V=1 -j8 CRASH_TEST_EXT_ARGS='--duration=960 --max_key=2500000 --use_io_uring=0' blackbox_crash_test_with_atomic_flush
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ======================= Linux with Sanitizers ===================== #
|
||||
build-linux-clang10-asan:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 32-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: COMPILE_WITH_ASAN=1 CC=clang-10 CXX=clang++-10 ROCKSDB_DISABLE_ALIGNED_NEW=1 USE_CLANG=1 make V=1 -j32 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-clang10-ubsan:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: COMPILE_WITH_UBSAN=1 OPT="-fsanitize-blacklist=.circleci/ubsan_suppression_list.txt" CC=clang-10 CXX=clang++-10 ROCKSDB_DISABLE_ALIGNED_NEW=1 USE_CLANG=1 make V=1 -j32 ubsan_check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-clang10-mini-tsan:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 32-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: COMPILE_WITH_TSAN=1 CC=clang-13 CXX=clang++-13 ROCKSDB_DISABLE_ALIGNED_NEW=1 USE_CLANG=1 make V=1 -j32 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-static_lib-alt_namespace-status_checked:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 16-core-ubuntu
|
||||
container:
|
||||
image: zjay437/rocksdb:0.6
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- run: ASSERT_STATUS_CHECKED=1 TEST_UINT128_COMPAT=1 ROCKSDB_MODIFY_NPHASH=1 LIB_MODE=static OPT="-DROCKSDB_NAMESPACE=alternative_rocksdb_ns" make V=1 -j24 check
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ========================= MacOS with Tests ======================== #
|
||||
build-macos:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: macos-13
|
||||
env:
|
||||
ROCKSDB_DISABLE_JEMALLOC: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: 14.3.1
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
- name: Run all tests
|
||||
run: ulimit -S -n `ulimit -H -n` && make V=1 J=16 -j16 all
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-macos-cmake:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: macos-13
|
||||
strategy:
|
||||
matrix:
|
||||
run_even_tests: [true, false]
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: 14.3.1
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
- name: cmake generate project file
|
||||
run: ulimit -S -n `ulimit -H -n` && mkdir build && cd build && cmake -DWITH_GFLAGS=1 ..
|
||||
- name: Build tests
|
||||
run: cd build && make V=1 -j16
|
||||
- name: Run even tests
|
||||
run: ulimit -S -n `ulimit -H -n` && cd build && ctest -j16 -I 0,,2
|
||||
if: ${{ matrix.run_even_tests }}
|
||||
- name: Run odd tests
|
||||
run: ulimit -S -n `ulimit -H -n` && cd build && ctest -j16 -I 1,,2
|
||||
if: ${{ ! matrix.run_even_tests }}
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ======================== Windows with Tests ======================= #
|
||||
# NOTE: some windows jobs are in "nightly" to save resources
|
||||
build-windows-vs2019:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: windows-2019
|
||||
env:
|
||||
CMAKE_GENERATOR: Visual Studio 16 2019
|
||||
CMAKE_PORTABLE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/windows-build-steps"
|
||||
# ============================ Java Jobs ============================ #
|
||||
build-linux-java:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: evolvedbinary/rocksjava:centos6_x64-be
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
# 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.
|
||||
- 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"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- name: Test RocksDBJava
|
||||
run: scl enable devtoolset-7 'make V=1 J=8 -j8 jtest'
|
||||
# NOTE: post-steps skipped because of compatibility issues with docker image
|
||||
build-linux-java-static:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: evolvedbinary/rocksjava:centos6_x64-be
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
# 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.
|
||||
- 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"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- name: Build RocksDBJava Static Library
|
||||
run: scl enable devtoolset-7 'make V=1 J=8 -j8 rocksdbjavastatic'
|
||||
# NOTE: post-steps skipped because of compatibility issues with docker image
|
||||
build-macos-java:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: macos-13
|
||||
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: 14.3.1
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/install-jdk8-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- name: Test RocksDBJava
|
||||
run: make V=1 J=16 -j16 jtest
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-macos-java-static:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: macos-13
|
||||
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: 14.3.1
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/install-jdk8-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- name: Build RocksDBJava x86 and ARM Static Libraries
|
||||
run: make V=1 J=16 -j16 rocksdbjavastaticosx
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-macos-java-static-universal:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on: macos-13
|
||||
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: 14.3.1
|
||||
- uses: "./.github/actions/increase-max-open-files-on-macos"
|
||||
- uses: "./.github/actions/install-gflags-on-macos"
|
||||
- uses: "./.github/actions/install-jdk8-on-macos"
|
||||
- uses: "./.github/actions/pre-steps-macos"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- name: Build RocksDBJava Universal Binary Static Library
|
||||
run: make V=1 J=16 -j16 rocksdbjavastaticosx_ub
|
||||
- uses: "./.github/actions/post-steps"
|
||||
build-linux-java-pmd:
|
||||
if: ${{ github.repository_owner == 'facebook' }}
|
||||
runs-on:
|
||||
labels: 4-core-ubuntu
|
||||
container:
|
||||
image: evolvedbinary/rocksjava:rockylinux8_x64-be
|
||||
options: --shm-size=16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/install-maven"
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- name: Set Java Environment
|
||||
run: |-
|
||||
echo "JAVA_HOME=${JAVA_HOME}"
|
||||
which java && java -version
|
||||
which javac && javac -version
|
||||
- name: PMD RocksDBJava
|
||||
run: make V=1 J=8 -j8 jpmd
|
||||
- uses: actions/upload-artifact@v4.0.0
|
||||
with:
|
||||
name: pmd-report
|
||||
path: "${{ github.workspace }}/java/target/pmd.xml"
|
||||
- uses: actions/upload-artifact@v4.0.0
|
||||
with:
|
||||
name: maven-site
|
||||
path: "${{ github.workspace }}/java/target/site"
|
||||
@@ -0,0 +1,45 @@
|
||||
name: Check buck targets and code format
|
||||
on: [push, pull_request]
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check TARGETS file and code format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout feature branch
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetch from upstream
|
||||
run: |
|
||||
git remote add upstream https://github.com/facebook/rocksdb.git && git fetch upstream
|
||||
|
||||
- name: Where am I
|
||||
run: |
|
||||
echo git status && git status
|
||||
echo "git remote -v" && git remote -v
|
||||
echo git branch && git branch
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v1
|
||||
|
||||
- name: Install Dependencies
|
||||
run: python -m pip install --upgrade pip
|
||||
|
||||
- name: Install argparse
|
||||
run: pip install argparse
|
||||
|
||||
- name: Download clang-format-diff.py
|
||||
run: wget https://raw.githubusercontent.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
|
||||
+8
-4
@@ -76,6 +76,11 @@ if (WITH_WINDOWS_UTF8_FILENAMES)
|
||||
endif()
|
||||
option(ROCKSDB_BUILD_SHARED "Build shared versions of the RocksDB libraries" ON)
|
||||
|
||||
if ($ENV{CIRCLECI})
|
||||
message(STATUS "Build for CircieCI env, a few tests may be disabled")
|
||||
add_definitions(-DCIRCLECI)
|
||||
endif()
|
||||
|
||||
if( NOT DEFINED CMAKE_CXX_STANDARD )
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
endif()
|
||||
@@ -1423,7 +1428,6 @@ if(WITH_TESTS)
|
||||
util/ribbon_test.cc
|
||||
util/slice_test.cc
|
||||
util/slice_transform_test.cc
|
||||
util/string_util_test.cc
|
||||
util/timer_queue_test.cc
|
||||
util/timer_test.cc
|
||||
util/thread_list_test.cc
|
||||
@@ -1473,7 +1477,7 @@ if(WITH_TESTS)
|
||||
utilities/cassandra/test_utils.cc
|
||||
)
|
||||
enable_testing()
|
||||
add_custom_target(rocksdb_check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
set(TESTUTILLIB testutillib${ARTIFACT_SUFFIX})
|
||||
add_library(${TESTUTILLIB} STATIC ${TESTUTIL_SOURCE})
|
||||
target_link_libraries(${TESTUTILLIB} ${ROCKSDB_LIB} ${FOLLY_LIBS})
|
||||
@@ -1498,7 +1502,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")
|
||||
gtest_discover_tests(${exename} DISCOVERY_TIMEOUT 120)
|
||||
add_dependencies(rocksdb_check ${exename}${ARTIFACT_SUFFIX})
|
||||
add_dependencies(check ${exename}${ARTIFACT_SUFFIX})
|
||||
endif()
|
||||
endforeach(sourcefile ${TESTS})
|
||||
|
||||
@@ -1518,7 +1522,7 @@ if(WITH_TESTS)
|
||||
add_executable(c_test db/c_test.c)
|
||||
target_link_libraries(c_test ${ROCKSDB_LIB_FOR_C} testharness)
|
||||
add_test(NAME c_test COMMAND c_test${ARTIFACT_SUFFIX})
|
||||
add_dependencies(rocksdb_check c_test)
|
||||
add_dependencies(check c_test)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
+5
-79
@@ -1,88 +1,14 @@
|
||||
# Rocksdb Change Log
|
||||
> NOTE: Entries for next release do not go here. Follow instructions in `unreleased_history/README.txt`
|
||||
|
||||
## 8.11.5 (11/26/2025)
|
||||
### Behavior Changes
|
||||
* Backport new value types `kTypeValuePreferredSeqno` and `kTypeColumnFamilyValuePreferredSeqno` introduced in RocksDB 9.1. This fixes a forward compatibility issue to allow reading MANIFEST with entries containing kTypeMaxValid written by RocksDB 9.1+.
|
||||
|
||||
## 8.11.4 (04/09/2024)
|
||||
## 8.9.2 (12/12/2023)
|
||||
### Bug Fixes
|
||||
* Fixed CMake Javadoc build
|
||||
* Fixed Java `SstFileMetaData` to prevent throwing `java.lang.NoSuchMethodError`
|
||||
|
||||
## 8.11.3 (02/27/2024)
|
||||
* Correct CMake Javadoc and source jar builds
|
||||
|
||||
## 8.11.2 (02/16/2024)
|
||||
* Update zlib to 1.3.1 for Java builds
|
||||
|
||||
## 8.11.1 (01/25/2024)
|
||||
### Bug Fixes
|
||||
* Fix a bug where older data of an ingested key can be returned for read when universal compaction is used
|
||||
* Apply appropriate rate limiting and priorities in more places.
|
||||
|
||||
## 8.11.0 (01/19/2024)
|
||||
### New Features
|
||||
* Add new statistics: `rocksdb.sst.write.micros` measures time of each write to SST file; `rocksdb.file.write.{flush|compaction|db.open}.micros` measure time of each write to SST table (currently only block-based table format) and blob file for flush, compaction and db open.
|
||||
|
||||
### Public API Changes
|
||||
* Added another enumerator `kVerify` to enum class `FileOperationType` in listener.h. Update your `switch` statements as needed.
|
||||
* Add CompressionOptions to the CompressedSecondaryCacheOptions structure to allow users to specify library specific options when creating the compressed secondary cache.
|
||||
* Deprecated several options: `level_compaction_dynamic_file_size`, `ignore_max_compaction_bytes_for_input`, `check_flush_compaction_key_order`, `flush_verify_memtable_count`, `compaction_verify_record_count`, `fail_if_options_file_error`, and `enforce_single_del_contracts`
|
||||
* Exposed options ttl via c api.
|
||||
|
||||
### Behavior Changes
|
||||
* `rocksdb.blobdb.blob.file.write.micros` expands to also measure time writing the header and footer. Therefore the COUNT may be higher and values may be smaller than before. For stacked BlobDB, it no longer measures the time of explictly flushing blob file.
|
||||
* Files will be compacted to the next level if the data age exceeds periodic_compaction_seconds except for the last level.
|
||||
* Reduced the compaction debt ratio trigger for scheduling parallel compactions
|
||||
* For leveled compaction with default compaction pri (kMinOverlappingRatio), files marked for compaction will be prioritized over files not marked when picking a file from a level for compaction.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix bug in auto_readahead_size that combined with IndexType::kBinarySearchWithFirstKey + fails or iterator lands at a wrong key
|
||||
* Fixed some cases in which DB file corruption was detected but ignored on creating a backup with BackupEngine.
|
||||
* Fix bugs where `rocksdb.blobdb.blob.file.synced` includes blob files failed to get synced and `rocksdb.blobdb.blob.file.bytes.written` includes blob bytes failed to get written.
|
||||
* Fixed a possible memory leak or crash on a failure (such as I/O error) in automatic atomic flush of multiple column families.
|
||||
* Fixed some cases of in-memory data corruption using mmap reads with `BackupEngine`, `sst_dump`, or `ldb`.
|
||||
* Fixed issues with experimental `preclude_last_level_data_seconds` option that could interfere with expected data tiering.
|
||||
* Fixed the handling of the edge case when all existing blob files become unreferenced. Such files are now correctly deleted.
|
||||
|
||||
## 8.10.0 (12/15/2023)
|
||||
### New Features
|
||||
* Provide support for async_io to trim readahead_size by doing block cache lookup
|
||||
* Added initial wide-column support in `WriteBatchWithIndex`. This includes the `PutEntity` API and support for wide columns in the existing read APIs (`GetFromBatch`, `GetFromBatchAndDB`, `MultiGetFromBatchAndDB`, and `BaseDeltaIterator`).
|
||||
|
||||
### Public API Changes
|
||||
* Custom implementations of `TablePropertiesCollectorFactory` may now return a `nullptr` collector to decline processing a file, reducing callback overheads in such cases.
|
||||
|
||||
### Behavior Changes
|
||||
* Make ReadOptions.auto_readahead_size default true which does prefetching optimizations for forward scans if iterate_upper_bound and block_cache is also specified.
|
||||
* Compactions can be scheduled in parallel in an additional scenario: high compaction debt relative to the data size
|
||||
* HyperClockCache now has built-in protection against excessive CPU consumption under the extreme stress condition of no (or very few) evictable cache entries, which can slightly increase memory usage such conditions. New option `HyperClockCacheOptions::eviction_effort_cap` controls the space-time trade-off of the response. The default should be generally well-balanced, with no measurable affect on normal operation.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix a corner case with auto_readahead_size where Prev Operation returns NOT SUPPORTED error when scans direction is changed from forward to backward.
|
||||
* Avoid destroying the periodic task scheduler's default timer in order to prevent static destruction order issues.
|
||||
* Fix double counting of BYTES_WRITTEN ticker when doing writes with transactions.
|
||||
* Fix a WRITE_STALL counter that was reporting wrong value in few cases.
|
||||
* A lookup by MultiGet in a TieredCache that goes to the local flash cache and finishes with very low latency, i.e before the subsequent call to WaitAll, is ignored, resulting in a false negative and a memory leak.
|
||||
* Sanitize the cache_opts->secondary_cache field in TieredCacheOptions. It can be mistakenly set by the user, which would conflict with nvm_sec_cache in TieredCacheOptions if not sanitized to nullptr.
|
||||
|
||||
### Performance Improvements
|
||||
* Java API extensions to improve consistency and completeness of APIs
|
||||
1 Extended `RocksDB.get([ColumnFamilyHandle columnFamilyHandle,] ReadOptions opt, ByteBuffer key, ByteBuffer value)` which now accepts indirect buffer parameters as well as direct buffer parameters
|
||||
2 Extended `RocksDB.put( [ColumnFamilyHandle columnFamilyHandle,] WriteOptions writeOpts, final ByteBuffer key, final ByteBuffer value)` which now accepts indirect buffer parameters as well as direct buffer parameters
|
||||
3 Added `RocksDB.merge([ColumnFamilyHandle columnFamilyHandle,] WriteOptions writeOptions, ByteBuffer key, ByteBuffer value)` methods with the same parameter options as `put(...)` - direct and indirect buffers are supported
|
||||
4 Added `RocksIterator.key( byte[] key [, int offset, int len])` methods which retrieve the iterator key into the supplied buffer
|
||||
5 Added `RocksIterator.value( byte[] value [, int offset, int len])` methods which retrieve the iterator value into the supplied buffer
|
||||
6 Deprecated `get(final ColumnFamilyHandle columnFamilyHandle, final ReadOptions readOptions, byte[])` in favour of `get(final ReadOptions readOptions, final ColumnFamilyHandle columnFamilyHandle, byte[])` which has consistent parameter ordering with other methods in the same class
|
||||
7 Added `Transaction.get( ReadOptions opt, [ColumnFamilyHandle columnFamilyHandle, ] byte[] key, byte[] value)` methods which retrieve the requested value into the supplied buffer
|
||||
8 Added `Transaction.get( ReadOptions opt, [ColumnFamilyHandle columnFamilyHandle, ] ByteBuffer key, ByteBuffer value)` methods which retrieve the requested value into the supplied buffer
|
||||
9 Added `Transaction.getForUpdate( ReadOptions readOptions, [ColumnFamilyHandle columnFamilyHandle, ] byte[] key, byte[] value, boolean exclusive [, boolean doValidate])` methods which retrieve the requested value into the supplied buffer
|
||||
10 Added `Transaction.getForUpdate( ReadOptions readOptions, [ColumnFamilyHandle columnFamilyHandle, ] ByteBuffer key, ByteBuffer value, boolean exclusive [, boolean doValidate])` methods which retrieve the requested value into the supplied buffer
|
||||
11 Added `Transaction.getIterator()` method as a convenience which defaults the `ReadOptions` value supplied to existing `Transaction.iterator()` methods. This mirrors the existing `RocksDB.iterator()` method.
|
||||
12 Added `Transaction.put([ColumnFamilyHandle columnFamilyHandle, ] ByteBuffer key, ByteBuffer value [, boolean assumeTracked])` methods which supply the key, and the value to be written in a `ByteBuffer` parameter
|
||||
13 Added `Transaction.merge([ColumnFamilyHandle columnFamilyHandle, ] ByteBuffer key, ByteBuffer value [, boolean assumeTracked])` methods which supply the key, and the value to be written/merged in a `ByteBuffer` parameter
|
||||
14 Added `Transaction.mergeUntracked([ColumnFamilyHandle columnFamilyHandle, ] ByteBuffer key, ByteBuffer value)` methods which supply the key, and the value to be written/merged in a `ByteBuffer` parameter
|
||||
|
||||
## 8.9.1 (12/8/2023)
|
||||
### Bug Fixes
|
||||
* Avoid destroying the periodic task scheduler's default timer in order to prevent static destruction order issues.
|
||||
|
||||
## 8.9.0 (11/17/2023)
|
||||
### New Features
|
||||
|
||||
@@ -1768,9 +1768,6 @@ cuckoo_table_db_test: $(OBJ_DIR)/db/cuckoo_table_db_test.o $(TEST_LIBRARY) $(LIB
|
||||
listener_test: $(OBJ_DIR)/db/listener_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
string_util_test: $(OBJ_DIR)/util/string_util_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
thread_list_test: $(OBJ_DIR)/util/thread_list_test.o $(TEST_LIBRARY) $(LIBRARY)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -2063,7 +2060,7 @@ JAVA_INCLUDE = -I$(JAVA_HOME)/include/ -I$(JAVA_HOME)/include/linux
|
||||
ifeq ($(PLATFORM), OS_SOLARIS)
|
||||
ARCH := $(shell isainfo -b)
|
||||
else ifeq ($(PLATFORM), OS_OPENBSD)
|
||||
ifneq (,$(filter amd64 ppc64 ppc64le s390x arm64 aarch64 riscv64 sparc64 loongarch64, $(MACHINE)))
|
||||
ifneq (,$(filter amd64 ppc64 ppc64le s390x arm64 aarch64 sparc64 loongarch64, $(MACHINE)))
|
||||
ARCH := 64
|
||||
else
|
||||
ARCH := 32
|
||||
@@ -2084,7 +2081,7 @@ ifneq ($(origin JNI_LIBC), undefined)
|
||||
endif
|
||||
|
||||
ifeq (,$(ROCKSDBJNILIB))
|
||||
ifneq (,$(filter ppc% s390x arm64 aarch64 riscv64 sparc64 loongarch64, $(MACHINE)))
|
||||
ifneq (,$(filter ppc% s390x arm64 aarch64 sparc64 loongarch64, $(MACHINE)))
|
||||
ROCKSDBJNILIB = librocksdbjni-linux-$(MACHINE)$(JNI_LIBC_POSTFIX).so
|
||||
else
|
||||
ROCKSDBJNILIB = librocksdbjni-linux$(ARCH)$(JNI_LIBC_POSTFIX).so
|
||||
@@ -2097,8 +2094,8 @@ ROCKSDB_JAVADOCS_JAR = rocksdbjni-$(ROCKSDB_JAVA_VERSION)-javadoc.jar
|
||||
ROCKSDB_SOURCES_JAR = rocksdbjni-$(ROCKSDB_JAVA_VERSION)-sources.jar
|
||||
SHA256_CMD = sha256sum
|
||||
|
||||
ZLIB_VER ?= 1.3.1
|
||||
ZLIB_SHA256 ?= 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23
|
||||
ZLIB_VER ?= 1.3
|
||||
ZLIB_SHA256 ?= ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e
|
||||
ZLIB_DOWNLOAD_BASE ?= http://zlib.net
|
||||
BZIP2_VER ?= 1.0.8
|
||||
BZIP2_SHA256 ?= ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269
|
||||
@@ -2349,10 +2346,6 @@ rocksdbjavastaticdockers390x:
|
||||
mkdir -p java/target
|
||||
docker run --rm --name rocksdb_linux_s390x-be --attach stdin --attach stdout --attach stderr --volume $(HOME)/.m2:/root/.m2:ro --volume `pwd`:/rocksdb-host:ro --volume /rocksdb-local-build --volume `pwd`/java/target:/rocksdb-java-target --env DEBUG_LEVEL=$(DEBUG_LEVEL) evolvedbinary/rocksjava:ubuntu18_s390x-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh
|
||||
|
||||
rocksdbjavastaticdockerriscv64:
|
||||
mkdir -p java/target
|
||||
docker run --rm --name rocksdb_linux_riscv64-be --attach stdin --attach stdout --attach stderr --volume $(HOME)/.m2:/root/.m2:ro --volume `pwd`:/rocksdb-host:ro --volume /rocksdb-local-build --volume `pwd`/java/target:/rocksdb-java-target --env DEBUG_LEVEL=$(DEBUG_LEVEL) evolvedbinary/rocksjava:ubuntu20_riscv64-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh
|
||||
|
||||
rocksdbjavastaticdockerx86musl:
|
||||
mkdir -p java/target
|
||||
docker run --rm --name rocksdb_linux_x86-musl-be --platform linux/386 --attach stdin --attach stdout --attach stderr --volume $(HOME)/.m2:/root/.m2:ro --volume `pwd`:/rocksdb-host:ro --volume /rocksdb-local-build --volume `pwd`/java/target:/rocksdb-java-target --env DEBUG_LEVEL=$(DEBUG_LEVEL) evolvedbinary/rocksjava:alpine3_x86-be /rocksdb-host/java/crossbuild/docker-build-linux-alpine.sh
|
||||
|
||||
@@ -647,10 +647,8 @@ if [ "$PORTABLE" == "" ] || [ "$PORTABLE" == 0 ]; then
|
||||
fi
|
||||
COMMON_FLAGS="$COMMON_FLAGS"
|
||||
elif test -n "`echo $TARGET_ARCHITECTURE | grep ^riscv64`"; then
|
||||
RISC_ISA=$(cat /proc/cpuinfo | grep -E '^isa\s*:' | head -1 | cut --delimiter=: -f 2 | cut -b 2-)
|
||||
if [ -n "${RISCV_ISA}" ]; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -march=${RISC_ISA}"
|
||||
fi
|
||||
RISC_ISA=$(cat /proc/cpuinfo | grep isa | head -1 | cut --delimiter=: -f 2 | cut -b 2-)
|
||||
COMMON_FLAGS="$COMMON_FLAGS -march=${RISC_ISA}"
|
||||
elif [ "$TARGET_OS" == "IOS" ]; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS"
|
||||
else
|
||||
@@ -662,7 +660,8 @@ else
|
||||
if test -n "`echo $TARGET_ARCHITECTURE | grep ^s390x`"; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -march=z196 "
|
||||
elif test -n "`echo $TARGET_ARCHITECTURE | grep ^riscv64`"; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -march=rv64gc"
|
||||
RISC_ISA=$(cat /proc/cpuinfo | grep isa | head -1 | cut --delimiter=: -f 2 | cut -b 2-)
|
||||
COMMON_FLAGS="$COMMON_FLAGS -march=${RISC_ISA}"
|
||||
elif test "$USE_SSE"; then
|
||||
# USE_SSE is DEPRECATED
|
||||
# This is a rough approximation of the old USE_SSE behavior
|
||||
|
||||
@@ -1561,7 +1561,7 @@ sub save_stdin_stdout_stderr {
|
||||
::die_bug("Can't dup STDERR: $!");
|
||||
open $Global::original_stdin, "<&", "STDIN" or
|
||||
::die_bug("Can't dup STDIN: $!");
|
||||
$Global::is_terminal = (-t $Global::original_stderr) && !$ENV{'CIRCLECI'}&& !$ENV{'GITHUB_ACTIONS'} && !$ENV{'TRAVIS'};
|
||||
$Global::is_terminal = (-t $Global::original_stderr) && !$ENV{'CIRCLECI'} && !$ENV{'TRAVIS'};
|
||||
}
|
||||
|
||||
sub enough_file_handles {
|
||||
|
||||
Vendored
-5
@@ -48,10 +48,6 @@ DEFINE_uint64(cache_size, 1 * GiB,
|
||||
"Number of bytes to use as a cache of uncompressed data.");
|
||||
DEFINE_int32(num_shard_bits, -1,
|
||||
"ShardedCacheOptions::shard_bits. Default = auto");
|
||||
DEFINE_int32(
|
||||
eviction_effort_cap,
|
||||
ROCKSDB_NAMESPACE::HyperClockCacheOptions(1, 1).eviction_effort_cap,
|
||||
"HyperClockCacheOptions::eviction_effort_cap");
|
||||
|
||||
DEFINE_double(resident_ratio, 0.25,
|
||||
"Ratio of keys fitting in cache to keyspace.");
|
||||
@@ -395,7 +391,6 @@ class CacheBench {
|
||||
FLAGS_cache_size, /*estimated_entry_charge=*/0, FLAGS_num_shard_bits);
|
||||
opts.hash_seed = BitwiseAnd(FLAGS_seed, INT32_MAX);
|
||||
opts.memory_allocator = allocator;
|
||||
opts.eviction_effort_cap = FLAGS_eviction_effort_cap;
|
||||
if (FLAGS_cache_type == "fixed_hyper_clock_cache" ||
|
||||
FLAGS_cache_type == "hyper_clock_cache") {
|
||||
opts.estimated_entry_charge = FLAGS_value_bytes_estimate > 0
|
||||
|
||||
Vendored
+41
-94
@@ -15,7 +15,6 @@
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
@@ -95,8 +94,7 @@ inline void Unref(const ClockHandle& h, uint64_t count = 1) {
|
||||
(void)old_meta;
|
||||
}
|
||||
|
||||
inline bool ClockUpdate(ClockHandle& h, BaseClockTable::EvictionData* data,
|
||||
bool* purgeable = nullptr) {
|
||||
inline bool ClockUpdate(ClockHandle& h, bool* purgeable = nullptr) {
|
||||
uint64_t meta;
|
||||
if (purgeable) {
|
||||
assert(*purgeable == false);
|
||||
@@ -128,7 +126,6 @@ inline bool ClockUpdate(ClockHandle& h, BaseClockTable::EvictionData* data,
|
||||
(meta >> ClockHandle::kReleaseCounterShift) & ClockHandle::kCounterMask;
|
||||
if (acquire_count != release_count) {
|
||||
// Only clock update entries with no outstanding refs
|
||||
data->seen_pinned_count++;
|
||||
return false;
|
||||
}
|
||||
if ((meta >> ClockHandle::kStateShift == ClockHandle::kStateVisible) &&
|
||||
@@ -152,8 +149,6 @@ inline bool ClockUpdate(ClockHandle& h, BaseClockTable::EvictionData* data,
|
||||
<< ClockHandle::kStateShift) |
|
||||
(meta & ClockHandle::kHitBitMask))) {
|
||||
// Took ownership.
|
||||
data->freed_charge += h.GetTotalCharge();
|
||||
data->freed_count += 1;
|
||||
return true;
|
||||
} else {
|
||||
// Compare-exchange failing probably
|
||||
@@ -361,18 +356,6 @@ void ConstApplyToEntriesRange(const Func& func, const HandleImpl* begin,
|
||||
}
|
||||
}
|
||||
|
||||
constexpr uint32_t kStrictCapacityLimitBit = 1u << 31;
|
||||
|
||||
uint32_t SanitizeEncodeEecAndScl(int eviction_effort_cap,
|
||||
bool strict_capacit_limit) {
|
||||
eviction_effort_cap = std::max(int{1}, eviction_effort_cap);
|
||||
eviction_effort_cap =
|
||||
std::min(static_cast<int>(~kStrictCapacityLimitBit), eviction_effort_cap);
|
||||
uint32_t eec_and_scl = static_cast<uint32_t>(eviction_effort_cap);
|
||||
eec_and_scl |= strict_capacit_limit ? kStrictCapacityLimitBit : 0;
|
||||
return eec_and_scl;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ClockHandleBasicData::FreeData(MemoryAllocator* allocator) const {
|
||||
@@ -402,20 +385,17 @@ HandleImpl* BaseClockTable::StandaloneInsert(
|
||||
|
||||
template <class Table>
|
||||
typename Table::HandleImpl* BaseClockTable::CreateStandalone(
|
||||
ClockHandleBasicData& proto, size_t capacity, uint32_t eec_and_scl,
|
||||
ClockHandleBasicData& proto, size_t capacity, bool strict_capacity_limit,
|
||||
bool allow_uncharged) {
|
||||
Table& derived = static_cast<Table&>(*this);
|
||||
typename Table::InsertState state;
|
||||
derived.StartInsert(state);
|
||||
|
||||
const size_t total_charge = proto.GetTotalCharge();
|
||||
// NOTE: we can use eec_and_scl as eviction_effort_cap below because
|
||||
// strict_capacity_limit=true is supposed to disable the limit on eviction
|
||||
// effort, and a large value effectively does that.
|
||||
if (eec_and_scl & kStrictCapacityLimitBit) {
|
||||
if (strict_capacity_limit) {
|
||||
Status s = ChargeUsageMaybeEvictStrict<Table>(
|
||||
total_charge, capacity,
|
||||
/*need_evict_for_occupancy=*/false, eec_and_scl, state);
|
||||
/*need_evict_for_occupancy=*/false, state);
|
||||
if (!s.ok()) {
|
||||
if (allow_uncharged) {
|
||||
proto.total_charge = 0;
|
||||
@@ -427,7 +407,7 @@ typename Table::HandleImpl* BaseClockTable::CreateStandalone(
|
||||
// Case strict_capacity_limit == false
|
||||
bool success = ChargeUsageMaybeEvictNonStrict<Table>(
|
||||
total_charge, capacity,
|
||||
/*need_evict_for_occupancy=*/false, eec_and_scl, state);
|
||||
/*need_evict_for_occupancy=*/false, state);
|
||||
if (!success) {
|
||||
// Force the issue
|
||||
usage_.FetchAddRelaxed(total_charge);
|
||||
@@ -440,7 +420,7 @@ typename Table::HandleImpl* BaseClockTable::CreateStandalone(
|
||||
template <class Table>
|
||||
Status BaseClockTable::ChargeUsageMaybeEvictStrict(
|
||||
size_t total_charge, size_t capacity, bool need_evict_for_occupancy,
|
||||
uint32_t eviction_effort_cap, typename Table::InsertState& state) {
|
||||
typename Table::InsertState& state) {
|
||||
if (total_charge > capacity) {
|
||||
return Status::MemoryLimit(
|
||||
"Cache entry too large for a single cache shard: " +
|
||||
@@ -465,8 +445,7 @@ Status BaseClockTable::ChargeUsageMaybeEvictStrict(
|
||||
}
|
||||
if (request_evict_charge > 0) {
|
||||
EvictionData data;
|
||||
static_cast<Table*>(this)->Evict(request_evict_charge, state, &data,
|
||||
eviction_effort_cap);
|
||||
static_cast<Table*>(this)->Evict(request_evict_charge, state, &data);
|
||||
occupancy_.FetchSub(data.freed_count);
|
||||
if (LIKELY(data.freed_charge > need_evict_charge)) {
|
||||
assert(data.freed_count > 0);
|
||||
@@ -496,7 +475,7 @@ Status BaseClockTable::ChargeUsageMaybeEvictStrict(
|
||||
template <class Table>
|
||||
inline bool BaseClockTable::ChargeUsageMaybeEvictNonStrict(
|
||||
size_t total_charge, size_t capacity, bool need_evict_for_occupancy,
|
||||
uint32_t eviction_effort_cap, typename Table::InsertState& state) {
|
||||
typename Table::InsertState& state) {
|
||||
// For simplicity, we consider that either the cache can accept the insert
|
||||
// with no evictions, or we must evict enough to make (at least) enough
|
||||
// space. It could lead to unnecessary failures or excessive evictions in
|
||||
@@ -532,8 +511,7 @@ inline bool BaseClockTable::ChargeUsageMaybeEvictNonStrict(
|
||||
}
|
||||
EvictionData data;
|
||||
if (need_evict_charge > 0) {
|
||||
static_cast<Table*>(this)->Evict(need_evict_charge, state, &data,
|
||||
eviction_effort_cap);
|
||||
static_cast<Table*>(this)->Evict(need_evict_charge, state, &data);
|
||||
// Deal with potential occupancy deficit
|
||||
if (UNLIKELY(need_evict_for_occupancy) && data.freed_count == 0) {
|
||||
assert(data.freed_charge == 0);
|
||||
@@ -552,7 +530,11 @@ inline bool BaseClockTable::ChargeUsageMaybeEvictNonStrict(
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseClockTable::TrackAndReleaseEvictedEntry(ClockHandle* h) {
|
||||
void BaseClockTable::TrackAndReleaseEvictedEntry(
|
||||
ClockHandle* h, BaseClockTable::EvictionData* data) {
|
||||
data->freed_charge += h->GetTotalCharge();
|
||||
data->freed_count += 1;
|
||||
|
||||
bool took_value_ownership = false;
|
||||
if (eviction_callback_) {
|
||||
// For key reconstructed from hash
|
||||
@@ -569,20 +551,11 @@ void BaseClockTable::TrackAndReleaseEvictedEntry(ClockHandle* h) {
|
||||
MarkEmpty(*h);
|
||||
}
|
||||
|
||||
bool IsEvictionEffortExceeded(const BaseClockTable::EvictionData& data,
|
||||
uint32_t eviction_effort_cap) {
|
||||
// Basically checks whether the ratio of useful effort to wasted effort is
|
||||
// too low, with a start-up allowance for wasted effort before any useful
|
||||
// effort.
|
||||
return (data.freed_count + 1U) * uint64_t{eviction_effort_cap} <=
|
||||
data.seen_pinned_count;
|
||||
}
|
||||
|
||||
template <class Table>
|
||||
Status BaseClockTable::Insert(const ClockHandleBasicData& proto,
|
||||
typename Table::HandleImpl** handle,
|
||||
Cache::Priority priority, size_t capacity,
|
||||
uint32_t eec_and_scl) {
|
||||
bool strict_capacity_limit) {
|
||||
using HandleImpl = typename Table::HandleImpl;
|
||||
Table& derived = static_cast<Table&>(*this);
|
||||
|
||||
@@ -600,12 +573,9 @@ Status BaseClockTable::Insert(const ClockHandleBasicData& proto,
|
||||
// strict_capacity_limit, but mostly pessimistic.
|
||||
bool use_standalone_insert = false;
|
||||
const size_t total_charge = proto.GetTotalCharge();
|
||||
// NOTE: we can use eec_and_scl as eviction_effort_cap below because
|
||||
// strict_capacity_limit=true is supposed to disable the limit on eviction
|
||||
// effort, and a large value effectively does that.
|
||||
if (eec_and_scl & kStrictCapacityLimitBit) {
|
||||
if (strict_capacity_limit) {
|
||||
Status s = ChargeUsageMaybeEvictStrict<Table>(
|
||||
total_charge, capacity, need_evict_for_occupancy, eec_and_scl, state);
|
||||
total_charge, capacity, need_evict_for_occupancy, state);
|
||||
if (!s.ok()) {
|
||||
// Revert occupancy
|
||||
occupancy_.FetchSubRelaxed(1);
|
||||
@@ -614,7 +584,7 @@ Status BaseClockTable::Insert(const ClockHandleBasicData& proto,
|
||||
} else {
|
||||
// Case strict_capacity_limit == false
|
||||
bool success = ChargeUsageMaybeEvictNonStrict<Table>(
|
||||
total_charge, capacity, need_evict_for_occupancy, eec_and_scl, state);
|
||||
total_charge, capacity, need_evict_for_occupancy, state);
|
||||
if (!success) {
|
||||
// Revert occupancy
|
||||
occupancy_.FetchSubRelaxed(1);
|
||||
@@ -718,7 +688,8 @@ void BaseClockTable::TEST_ReleaseNMinus1(ClockHandle* h, size_t n) {
|
||||
#endif
|
||||
|
||||
FixedHyperClockTable::FixedHyperClockTable(
|
||||
size_t capacity, CacheMetadataChargePolicy metadata_charge_policy,
|
||||
size_t capacity, bool /*strict_capacity_limit*/,
|
||||
CacheMetadataChargePolicy metadata_charge_policy,
|
||||
MemoryAllocator* allocator,
|
||||
const Cache::EvictionCallback* eviction_callback, const uint32_t* hash_seed,
|
||||
const Opts& opts)
|
||||
@@ -1113,8 +1084,7 @@ inline void FixedHyperClockTable::ReclaimEntryUsage(size_t total_charge) {
|
||||
}
|
||||
|
||||
inline void FixedHyperClockTable::Evict(size_t requested_charge, InsertState&,
|
||||
EvictionData* data,
|
||||
uint32_t eviction_effort_cap) {
|
||||
EvictionData* data) {
|
||||
// precondition
|
||||
assert(requested_charge > 0);
|
||||
|
||||
@@ -1135,10 +1105,10 @@ inline void FixedHyperClockTable::Evict(size_t requested_charge, InsertState&,
|
||||
for (;;) {
|
||||
for (size_t i = 0; i < step_size; i++) {
|
||||
HandleImpl& h = array_[ModTableSize(Lower32of64(old_clock_pointer + i))];
|
||||
bool evicting = ClockUpdate(h, data);
|
||||
bool evicting = ClockUpdate(h);
|
||||
if (evicting) {
|
||||
Rollback(h.hashed_key, &h);
|
||||
TrackAndReleaseEvictedEntry(&h);
|
||||
TrackAndReleaseEvictedEntry(&h, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1149,10 +1119,6 @@ inline void FixedHyperClockTable::Evict(size_t requested_charge, InsertState&,
|
||||
if (old_clock_pointer >= max_clock_pointer) {
|
||||
return;
|
||||
}
|
||||
if (IsEvictionEffortExceeded(*data, eviction_effort_cap)) {
|
||||
eviction_effort_exceeded_count_.FetchAddRelaxed(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Advance clock pointer (concurrently)
|
||||
old_clock_pointer = clock_pointer_.FetchAddRelaxed(step_size);
|
||||
@@ -1167,11 +1133,10 @@ ClockCacheShard<Table>::ClockCacheShard(
|
||||
const Cache::EvictionCallback* eviction_callback, const uint32_t* hash_seed,
|
||||
const typename Table::Opts& opts)
|
||||
: CacheShardBase(metadata_charge_policy),
|
||||
table_(capacity, metadata_charge_policy, allocator, eviction_callback,
|
||||
hash_seed, opts),
|
||||
table_(capacity, strict_capacity_limit, metadata_charge_policy, allocator,
|
||||
eviction_callback, hash_seed, opts),
|
||||
capacity_(capacity),
|
||||
eec_and_scl_(SanitizeEncodeEecAndScl(opts.eviction_effort_cap,
|
||||
strict_capacity_limit)) {
|
||||
strict_capacity_limit_(strict_capacity_limit) {
|
||||
// Initial charge metadata should not exceed capacity
|
||||
assert(table_.GetUsage() <= capacity_.LoadRelaxed() ||
|
||||
capacity_.LoadRelaxed() < sizeof(HandleImpl));
|
||||
@@ -1247,11 +1212,7 @@ void ClockCacheShard<Table>::SetCapacity(size_t capacity) {
|
||||
template <class Table>
|
||||
void ClockCacheShard<Table>::SetStrictCapacityLimit(
|
||||
bool strict_capacity_limit) {
|
||||
if (strict_capacity_limit) {
|
||||
eec_and_scl_.FetchOrRelaxed(kStrictCapacityLimitBit);
|
||||
} else {
|
||||
eec_and_scl_.FetchAndRelaxed(~kStrictCapacityLimitBit);
|
||||
}
|
||||
strict_capacity_limit_.StoreRelaxed(strict_capacity_limit);
|
||||
// next Insert will take care of any necessary evictions
|
||||
}
|
||||
|
||||
@@ -1273,7 +1234,7 @@ Status ClockCacheShard<Table>::Insert(const Slice& key,
|
||||
proto.total_charge = charge;
|
||||
return table_.template Insert<Table>(proto, handle, priority,
|
||||
capacity_.LoadRelaxed(),
|
||||
eec_and_scl_.LoadRelaxed());
|
||||
strict_capacity_limit_.LoadRelaxed());
|
||||
}
|
||||
|
||||
template <class Table>
|
||||
@@ -1288,9 +1249,9 @@ typename Table::HandleImpl* ClockCacheShard<Table>::CreateStandalone(
|
||||
proto.value = obj;
|
||||
proto.helper = helper;
|
||||
proto.total_charge = charge;
|
||||
return table_.template CreateStandalone<Table>(proto, capacity_.LoadRelaxed(),
|
||||
eec_and_scl_.LoadRelaxed(),
|
||||
allow_uncharged);
|
||||
return table_.template CreateStandalone<Table>(
|
||||
proto, capacity_.LoadRelaxed(), strict_capacity_limit_.LoadRelaxed(),
|
||||
allow_uncharged);
|
||||
}
|
||||
|
||||
template <class Table>
|
||||
@@ -1542,20 +1503,14 @@ void BaseHyperClockCache<Table>::ReportProblems(
|
||||
const std::shared_ptr<Logger>& info_log) const {
|
||||
if (info_log->GetInfoLogLevel() <= InfoLogLevel::DEBUG_LEVEL) {
|
||||
LoadVarianceStats slot_stats;
|
||||
uint64_t eviction_effort_exceeded_count = 0;
|
||||
this->ForEachShard([&](const BaseHyperClockCache<Table>::Shard* shard) {
|
||||
size_t count = shard->GetTableAddressCount();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
slot_stats.Add(IsSlotOccupied(*shard->GetTable().HandlePtr(i)));
|
||||
}
|
||||
eviction_effort_exceeded_count +=
|
||||
shard->GetTable().GetEvictionEffortExceededCount();
|
||||
});
|
||||
ROCKS_LOG_AT_LEVEL(info_log, InfoLogLevel::DEBUG_LEVEL,
|
||||
"Slot occupancy stats: %s", slot_stats.Report().c_str());
|
||||
ROCKS_LOG_AT_LEVEL(info_log, InfoLogLevel::DEBUG_LEVEL,
|
||||
"Eviction effort exceeded: %" PRIu64,
|
||||
eviction_effort_exceeded_count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1953,7 +1908,8 @@ class AutoHyperClockTable::ChainRewriteLock {
|
||||
};
|
||||
|
||||
AutoHyperClockTable::AutoHyperClockTable(
|
||||
size_t capacity, CacheMetadataChargePolicy metadata_charge_policy,
|
||||
size_t capacity, bool /*strict_capacity_limit*/,
|
||||
CacheMetadataChargePolicy metadata_charge_policy,
|
||||
MemoryAllocator* allocator,
|
||||
const Cache::EvictionCallback* eviction_callback, const uint32_t* hash_seed,
|
||||
const Opts& opts)
|
||||
@@ -2634,8 +2590,7 @@ using ClockUpdateChainLockedOpData =
|
||||
template <class OpData>
|
||||
void AutoHyperClockTable::PurgeImplLocked(OpData* op_data,
|
||||
ChainRewriteLock& rewrite_lock,
|
||||
size_t home,
|
||||
BaseClockTable::EvictionData* data) {
|
||||
size_t home) {
|
||||
constexpr bool kIsPurge = std::is_same_v<OpData, PurgeLockedOpData>;
|
||||
constexpr bool kIsClockUpdateChain =
|
||||
std::is_same_v<OpData, ClockUpdateChainLockedOpData>;
|
||||
@@ -2677,7 +2632,7 @@ void AutoHyperClockTable::PurgeImplLocked(OpData* op_data,
|
||||
assert(home == BottomNBits(h->hashed_key[1], home_shift));
|
||||
if constexpr (kIsClockUpdateChain) {
|
||||
// Clock update and/or check for purgeable (under (de)construction)
|
||||
if (ClockUpdate(*h, data, &purgeable)) {
|
||||
if (ClockUpdate(*h, &purgeable)) {
|
||||
// Remember for finishing eviction
|
||||
op_data->push_back(h);
|
||||
// Entries for eviction become purgeable
|
||||
@@ -2687,7 +2642,6 @@ void AutoHyperClockTable::PurgeImplLocked(OpData* op_data,
|
||||
}
|
||||
} else {
|
||||
(void)op_data;
|
||||
(void)data;
|
||||
purgeable = ((h->meta.Load() >> ClockHandle::kStateShift) &
|
||||
ClockHandle::kStateShareableBit) == 0;
|
||||
}
|
||||
@@ -2765,8 +2719,7 @@ using PurgeOpData = const UniqueId64x2;
|
||||
using ClockUpdateChainOpData = ClockUpdateChainLockedOpData;
|
||||
|
||||
template <class OpData>
|
||||
void AutoHyperClockTable::PurgeImpl(OpData* op_data, size_t home,
|
||||
BaseClockTable::EvictionData* data) {
|
||||
void AutoHyperClockTable::PurgeImpl(OpData* op_data, size_t home) {
|
||||
// Early efforts to make AutoHCC fully wait-free ran into too many problems
|
||||
// that needed obscure and potentially inefficient work-arounds to have a
|
||||
// chance at working.
|
||||
@@ -2847,9 +2800,9 @@ void AutoHyperClockTable::PurgeImpl(OpData* op_data, size_t home,
|
||||
if (!rewrite_lock.IsEnd()) {
|
||||
if constexpr (kIsPurge) {
|
||||
PurgeLockedOpData* locked_op_data{};
|
||||
PurgeImplLocked(locked_op_data, rewrite_lock, home, data);
|
||||
PurgeImplLocked(locked_op_data, rewrite_lock, home);
|
||||
} else {
|
||||
PurgeImplLocked(op_data, rewrite_lock, home, data);
|
||||
PurgeImplLocked(op_data, rewrite_lock, home);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3452,8 +3405,7 @@ void AutoHyperClockTable::EraseUnRefEntries() {
|
||||
}
|
||||
|
||||
void AutoHyperClockTable::Evict(size_t requested_charge, InsertState& state,
|
||||
EvictionData* data,
|
||||
uint32_t eviction_effort_cap) {
|
||||
EvictionData* data) {
|
||||
// precondition
|
||||
assert(requested_charge > 0);
|
||||
|
||||
@@ -3511,12 +3463,12 @@ void AutoHyperClockTable::Evict(size_t requested_charge, InsertState& state,
|
||||
if (home >= used_length) {
|
||||
break;
|
||||
}
|
||||
PurgeImpl(&to_finish_eviction, home, data);
|
||||
PurgeImpl(&to_finish_eviction, home);
|
||||
}
|
||||
}
|
||||
|
||||
for (HandleImpl* h : to_finish_eviction) {
|
||||
TrackAndReleaseEvictedEntry(h);
|
||||
TrackAndReleaseEvictedEntry(h, data);
|
||||
// NOTE: setting likely_empty_slot here can cause us to reduce the
|
||||
// portion of "at home" entries, probably because an evicted entry
|
||||
// is more likely to come back than a random new entry and would be
|
||||
@@ -3544,11 +3496,6 @@ void AutoHyperClockTable::Evict(size_t requested_charge, InsertState& state,
|
||||
if (old_clock_pointer + step_size >= max_clock_pointer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsEvictionEffortExceeded(*data, eviction_effort_cap)) {
|
||||
eviction_effort_exceeded_count_.FetchAddRelaxed(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+19
-49
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -375,14 +374,6 @@ struct ClockHandle : public ClockHandleBasicData {
|
||||
|
||||
class BaseClockTable {
|
||||
public:
|
||||
struct BaseOpts {
|
||||
explicit BaseOpts(int _eviction_effort_cap)
|
||||
: eviction_effort_cap(_eviction_effort_cap) {}
|
||||
explicit BaseOpts(const HyperClockCacheOptions& opts)
|
||||
: BaseOpts(opts.eviction_effort_cap) {}
|
||||
int eviction_effort_cap;
|
||||
};
|
||||
|
||||
BaseClockTable(CacheMetadataChargePolicy metadata_charge_policy,
|
||||
MemoryAllocator* allocator,
|
||||
const Cache::EvictionCallback* eviction_callback,
|
||||
@@ -395,13 +386,13 @@ class BaseClockTable {
|
||||
template <class Table>
|
||||
typename Table::HandleImpl* CreateStandalone(ClockHandleBasicData& proto,
|
||||
size_t capacity,
|
||||
uint32_t eec_and_scl,
|
||||
bool strict_capacity_limit,
|
||||
bool allow_uncharged);
|
||||
|
||||
template <class Table>
|
||||
Status Insert(const ClockHandleBasicData& proto,
|
||||
typename Table::HandleImpl** handle, Cache::Priority priority,
|
||||
size_t capacity, uint32_t eec_and_scl);
|
||||
size_t capacity, bool strict_capacity_limit);
|
||||
|
||||
void Ref(ClockHandle& handle);
|
||||
|
||||
@@ -415,17 +406,12 @@ class BaseClockTable {
|
||||
|
||||
uint64_t GetYieldCount() const { return yield_count_.LoadRelaxed(); }
|
||||
|
||||
uint64_t GetEvictionEffortExceededCount() const {
|
||||
return eviction_effort_exceeded_count_.LoadRelaxed();
|
||||
}
|
||||
|
||||
struct EvictionData {
|
||||
size_t freed_charge = 0;
|
||||
size_t freed_count = 0;
|
||||
size_t seen_pinned_count = 0;
|
||||
};
|
||||
|
||||
void TrackAndReleaseEvictedEntry(ClockHandle* h);
|
||||
void TrackAndReleaseEvictedEntry(ClockHandle* h, EvictionData* data);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Acquire N references
|
||||
@@ -450,7 +436,6 @@ class BaseClockTable {
|
||||
template <class Table>
|
||||
Status ChargeUsageMaybeEvictStrict(size_t total_charge, size_t capacity,
|
||||
bool need_evict_for_occupancy,
|
||||
uint32_t eviction_effort_cap,
|
||||
typename Table::InsertState& state);
|
||||
|
||||
// Helper for updating `usage_` for new entry with given `total_charge`
|
||||
@@ -464,7 +449,6 @@ class BaseClockTable {
|
||||
template <class Table>
|
||||
bool ChargeUsageMaybeEvictNonStrict(size_t total_charge, size_t capacity,
|
||||
bool need_evict_for_occupancy,
|
||||
uint32_t eviction_effort_cap,
|
||||
typename Table::InsertState& state);
|
||||
|
||||
protected: // data
|
||||
@@ -477,15 +461,9 @@ class BaseClockTable {
|
||||
RelaxedAtomic<uint64_t> clock_pointer_{};
|
||||
|
||||
// Counter for number of times we yield to wait on another thread.
|
||||
// It is normal for this to occur rarely in normal operation.
|
||||
// (Relaxed: a simple stat counter.)
|
||||
RelaxedAtomic<uint64_t> yield_count_{};
|
||||
|
||||
// Counter for number of times eviction effort cap is exceeded.
|
||||
// It is normal for this to occur rarely in normal operation.
|
||||
// (Relaxed: a simple stat counter.)
|
||||
RelaxedAtomic<uint64_t> eviction_effort_exceeded_count_{};
|
||||
|
||||
// TODO: is this separation needed if we don't do background evictions?
|
||||
ALIGN_AS(CACHE_LINE_SIZE)
|
||||
// Number of elements in the table.
|
||||
@@ -539,19 +517,17 @@ class FixedHyperClockTable : public BaseClockTable {
|
||||
inline void SetStandalone() { standalone = true; }
|
||||
}; // struct HandleImpl
|
||||
|
||||
struct Opts : public BaseOpts {
|
||||
explicit Opts(size_t _estimated_value_size, int _eviction_effort_cap)
|
||||
: BaseOpts(_eviction_effort_cap),
|
||||
estimated_value_size(_estimated_value_size) {}
|
||||
explicit Opts(const HyperClockCacheOptions& opts)
|
||||
: BaseOpts(opts.eviction_effort_cap) {
|
||||
struct Opts {
|
||||
explicit Opts(size_t _estimated_value_size)
|
||||
: estimated_value_size(_estimated_value_size) {}
|
||||
explicit Opts(const HyperClockCacheOptions& opts) {
|
||||
assert(opts.estimated_entry_charge > 0);
|
||||
estimated_value_size = opts.estimated_entry_charge;
|
||||
}
|
||||
size_t estimated_value_size;
|
||||
};
|
||||
|
||||
FixedHyperClockTable(size_t capacity,
|
||||
FixedHyperClockTable(size_t capacity, bool strict_capacity_limit,
|
||||
CacheMetadataChargePolicy metadata_charge_policy,
|
||||
MemoryAllocator* allocator,
|
||||
const Cache::EvictionCallback* eviction_callback,
|
||||
@@ -573,8 +549,7 @@ class FixedHyperClockTable : public BaseClockTable {
|
||||
// Runs the clock eviction algorithm trying to reclaim at least
|
||||
// requested_charge. Returns how much is evicted, which could be less
|
||||
// if it appears impossible to evict the requested amount without blocking.
|
||||
void Evict(size_t requested_charge, InsertState& state, EvictionData* data,
|
||||
uint32_t eviction_effort_cap);
|
||||
void Evict(size_t requested_charge, InsertState& state, EvictionData* data);
|
||||
|
||||
HandleImpl* Lookup(const UniqueId64x2& hashed_key);
|
||||
|
||||
@@ -828,20 +803,18 @@ class AutoHyperClockTable : public BaseClockTable {
|
||||
}
|
||||
}; // struct HandleImpl
|
||||
|
||||
struct Opts : public BaseOpts {
|
||||
explicit Opts(size_t _min_avg_value_size, int _eviction_effort_cap)
|
||||
: BaseOpts(_eviction_effort_cap),
|
||||
min_avg_value_size(_min_avg_value_size) {}
|
||||
struct Opts {
|
||||
explicit Opts(size_t _min_avg_value_size)
|
||||
: min_avg_value_size(_min_avg_value_size) {}
|
||||
|
||||
explicit Opts(const HyperClockCacheOptions& opts)
|
||||
: BaseOpts(opts.eviction_effort_cap) {
|
||||
explicit Opts(const HyperClockCacheOptions& opts) {
|
||||
assert(opts.estimated_entry_charge == 0);
|
||||
min_avg_value_size = opts.min_avg_entry_charge;
|
||||
}
|
||||
size_t min_avg_value_size;
|
||||
};
|
||||
|
||||
AutoHyperClockTable(size_t capacity,
|
||||
AutoHyperClockTable(size_t capacity, bool strict_capacity_limit,
|
||||
CacheMetadataChargePolicy metadata_charge_policy,
|
||||
MemoryAllocator* allocator,
|
||||
const Cache::EvictionCallback* eviction_callback,
|
||||
@@ -868,8 +841,7 @@ class AutoHyperClockTable : public BaseClockTable {
|
||||
// Runs the clock eviction algorithm trying to reclaim at least
|
||||
// requested_charge. Returns how much is evicted, which could be less
|
||||
// if it appears impossible to evict the requested amount without blocking.
|
||||
void Evict(size_t requested_charge, InsertState& state, EvictionData* data,
|
||||
uint32_t eviction_effort_cap);
|
||||
void Evict(size_t requested_charge, InsertState& state, EvictionData* data);
|
||||
|
||||
HandleImpl* Lookup(const UniqueId64x2& hashed_key);
|
||||
|
||||
@@ -934,8 +906,7 @@ class AutoHyperClockTable : public BaseClockTable {
|
||||
// with proper handling to ensure all existing data is seen even in the
|
||||
// presence of concurrent insertions, etc. (See implementation.)
|
||||
template <class OpData>
|
||||
void PurgeImpl(OpData* op_data, size_t home = SIZE_MAX,
|
||||
EvictionData* data = nullptr);
|
||||
void PurgeImpl(OpData* op_data, size_t home = SIZE_MAX);
|
||||
|
||||
// An RAII wrapper for locking a chain of entries for removals. See
|
||||
// implementation.
|
||||
@@ -945,7 +916,7 @@ class AutoHyperClockTable : public BaseClockTable {
|
||||
// implementation.
|
||||
template <class OpData>
|
||||
void PurgeImplLocked(OpData* op_data, ChainRewriteLock& rewrite_lock,
|
||||
size_t home, EvictionData* data);
|
||||
size_t home);
|
||||
|
||||
// Update length_info_ as much as possible without waiting, given a known
|
||||
// usable (ready for inserts and lookups) grow_home. (Previous grow_homes
|
||||
@@ -1107,10 +1078,9 @@ class ALIGN_AS(CACHE_LINE_SIZE) ClockCacheShard final : public CacheShardBase {
|
||||
// (Relaxed: eventual consistency/update is OK)
|
||||
RelaxedAtomic<size_t> capacity_;
|
||||
|
||||
// Encodes eviction_effort_cap (bottom 31 bits) and strict_capacity_limit
|
||||
// (top bit). See HyperClockCacheOptions::eviction_effort_cap etc.
|
||||
// Whether to reject insertion if cache reaches its full capacity.
|
||||
// (Relaxed: eventual consistency/update is OK)
|
||||
RelaxedAtomic<uint32_t> eec_and_scl_;
|
||||
RelaxedAtomic<bool> strict_capacity_limit_;
|
||||
}; // class ClockCacheShard
|
||||
|
||||
template <class Table>
|
||||
|
||||
Vendored
+5
-12
@@ -31,7 +31,7 @@ CompressedSecondaryCache::~CompressedSecondaryCache() {}
|
||||
std::unique_ptr<SecondaryCacheResultHandle> CompressedSecondaryCache::Lookup(
|
||||
const Slice& key, const Cache::CacheItemHelper* helper,
|
||||
Cache::CreateContext* create_context, bool /*wait*/, bool advise_erase,
|
||||
Statistics* stats, bool& kept_in_sec_cache) {
|
||||
bool& kept_in_sec_cache) {
|
||||
assert(helper);
|
||||
// This is a minor optimization. Its ok to skip it in TSAN in order to
|
||||
// avoid a false positive.
|
||||
@@ -51,7 +51,6 @@ std::unique_ptr<SecondaryCacheResultHandle> CompressedSecondaryCache::Lookup(
|
||||
void* handle_value = cache_->Value(lru_handle);
|
||||
if (handle_value == nullptr) {
|
||||
cache_->Release(lru_handle, /*erase_if_last_ref=*/false);
|
||||
RecordTick(stats, COMPRESSED_SECONDARY_CACHE_DUMMY_HITS);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -138,7 +137,6 @@ std::unique_ptr<SecondaryCacheResultHandle> CompressedSecondaryCache::Lookup(
|
||||
cache_->Release(lru_handle, /*erase_if_last_ref=*/false);
|
||||
}
|
||||
handle.reset(new CompressedSecondaryCacheResultHandle(value, charge));
|
||||
RecordTick(stats, COMPRESSED_SECONDARY_CACHE_HITS);
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -192,13 +190,13 @@ Status CompressedSecondaryCache::InsertInternal(
|
||||
type == kNoCompression &&
|
||||
!cache_options_.do_not_compress_roles.Contains(helper->role)) {
|
||||
PERF_COUNTER_ADD(compressed_sec_cache_uncompressed_bytes, data_size);
|
||||
CompressionOptions compression_opts;
|
||||
CompressionContext compression_context(cache_options_.compression_type,
|
||||
cache_options_.compression_opts);
|
||||
compression_opts);
|
||||
uint64_t sample_for_compression{0};
|
||||
CompressionInfo compression_info(
|
||||
cache_options_.compression_opts, compression_context,
|
||||
CompressionDict::GetEmptyDict(), cache_options_.compression_type,
|
||||
sample_for_compression);
|
||||
compression_opts, compression_context, CompressionDict::GetEmptyDict(),
|
||||
cache_options_.compression_type, sample_for_compression);
|
||||
|
||||
bool success =
|
||||
CompressData(val, compression_info,
|
||||
@@ -291,11 +289,6 @@ std::string CompressedSecondaryCache::GetPrintableOptions() const {
|
||||
snprintf(buffer, kBufferSize, " compression_type : %s\n",
|
||||
CompressionTypeToString(cache_options_.compression_type).c_str());
|
||||
ret.append(buffer);
|
||||
snprintf(buffer, kBufferSize, " compression_opts : %s\n",
|
||||
CompressionOptionsToString(
|
||||
const_cast<CompressionOptions&>(cache_options_.compression_opts))
|
||||
.c_str());
|
||||
ret.append(buffer);
|
||||
snprintf(buffer, kBufferSize, " compress_format_version : %d\n",
|
||||
cache_options_.compress_format_version);
|
||||
ret.append(buffer);
|
||||
|
||||
Vendored
+1
-1
@@ -86,7 +86,7 @@ class CompressedSecondaryCache : public SecondaryCache {
|
||||
std::unique_ptr<SecondaryCacheResultHandle> Lookup(
|
||||
const Slice& key, const Cache::CacheItemHelper* helper,
|
||||
Cache::CreateContext* create_context, bool /*wait*/, bool advise_erase,
|
||||
Statistics* stats, bool& kept_in_sec_cache) override;
|
||||
bool& kept_in_sec_cache) override;
|
||||
|
||||
bool SupportForceErase() const override { return true; }
|
||||
|
||||
|
||||
+13
-15
@@ -44,7 +44,7 @@ class CompressedSecondaryCacheTestBase : public testing::Test,
|
||||
// Lookup an non-existent key.
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle0 =
|
||||
sec_cache->Lookup(key0, GetHelper(), this, true, /*advise_erase=*/true,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_EQ(handle0, nullptr);
|
||||
|
||||
Random rnd(301);
|
||||
@@ -59,7 +59,7 @@ class CompressedSecondaryCacheTestBase : public testing::Test,
|
||||
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle1_1 =
|
||||
sec_cache->Lookup(key1, GetHelper(), this, true, /*advise_erase=*/false,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_EQ(handle1_1, nullptr);
|
||||
|
||||
// Insert and Lookup the item k1 for the second time and advise erasing it.
|
||||
@@ -68,7 +68,7 @@ class CompressedSecondaryCacheTestBase : public testing::Test,
|
||||
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle1_2 =
|
||||
sec_cache->Lookup(key1, GetHelper(), this, true, /*advise_erase=*/true,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_NE(handle1_2, nullptr);
|
||||
ASSERT_FALSE(kept_in_sec_cache);
|
||||
if (sec_cache_is_compressed) {
|
||||
@@ -89,7 +89,7 @@ class CompressedSecondaryCacheTestBase : public testing::Test,
|
||||
// Lookup the item k1 again.
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle1_3 =
|
||||
sec_cache->Lookup(key1, GetHelper(), this, true, /*advise_erase=*/true,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_EQ(handle1_3, nullptr);
|
||||
|
||||
// Insert and Lookup the item k2.
|
||||
@@ -99,7 +99,7 @@ class CompressedSecondaryCacheTestBase : public testing::Test,
|
||||
ASSERT_EQ(get_perf_context()->compressed_sec_cache_insert_dummy_count, 2);
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle2_1 =
|
||||
sec_cache->Lookup(key2, GetHelper(), this, true, /*advise_erase=*/false,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_EQ(handle2_1, nullptr);
|
||||
|
||||
ASSERT_OK(sec_cache->Insert(key2, &item2, GetHelper(), false));
|
||||
@@ -115,7 +115,7 @@ class CompressedSecondaryCacheTestBase : public testing::Test,
|
||||
}
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle2_2 =
|
||||
sec_cache->Lookup(key2, GetHelper(), this, true, /*advise_erase=*/false,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_NE(handle2_2, nullptr);
|
||||
std::unique_ptr<TestItem> val2 =
|
||||
std::unique_ptr<TestItem>(static_cast<TestItem*>(handle2_2->Value()));
|
||||
@@ -196,14 +196,14 @@ class CompressedSecondaryCacheTestBase : public testing::Test,
|
||||
bool kept_in_sec_cache{false};
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle1 =
|
||||
sec_cache->Lookup(key1, GetHelper(), this, true, /*advise_erase=*/false,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_EQ(handle1, nullptr);
|
||||
|
||||
// Insert k2 and k1 is evicted.
|
||||
ASSERT_OK(sec_cache->Insert(key2, &item2, GetHelper(), false));
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle2 =
|
||||
sec_cache->Lookup(key2, GetHelper(), this, true, /*advise_erase=*/false,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_NE(handle2, nullptr);
|
||||
std::unique_ptr<TestItem> val2 =
|
||||
std::unique_ptr<TestItem>(static_cast<TestItem*>(handle2->Value()));
|
||||
@@ -215,14 +215,14 @@ class CompressedSecondaryCacheTestBase : public testing::Test,
|
||||
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle1_1 =
|
||||
sec_cache->Lookup(key1, GetHelper(), this, true, /*advise_erase=*/false,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_EQ(handle1_1, nullptr);
|
||||
|
||||
// Create Fails.
|
||||
SetFailCreate(true);
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle2_1 =
|
||||
sec_cache->Lookup(key2, GetHelper(), this, true, /*advise_erase=*/true,
|
||||
/*stats=*/nullptr, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
ASSERT_EQ(handle2_1, nullptr);
|
||||
|
||||
// Save Fails.
|
||||
@@ -912,9 +912,9 @@ TEST_P(CompressedSecondaryCacheTestWithCompressionParam, EntryRoles) {
|
||||
ASSERT_EQ(get_perf_context()->compressed_sec_cache_insert_real_count, 1U);
|
||||
|
||||
bool kept_in_sec_cache{true};
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle = sec_cache->Lookup(
|
||||
ith_key, GetHelper(role), this, true,
|
||||
/*advise_erase=*/true, /*stats=*/nullptr, kept_in_sec_cache);
|
||||
std::unique_ptr<SecondaryCacheResultHandle> handle =
|
||||
sec_cache->Lookup(ith_key, GetHelper(role), this, true,
|
||||
/*advise_erase=*/true, kept_in_sec_cache);
|
||||
ASSERT_NE(handle, nullptr);
|
||||
|
||||
// Lookup returns the right data
|
||||
@@ -992,8 +992,6 @@ class CompressedSecCacheTestWithTiered
|
||||
/*_capacity=*/0,
|
||||
/*_estimated_entry_charge=*/256 << 10,
|
||||
/*_num_shard_bits=*/0);
|
||||
// eviction_effort_cap setting simply to avoid churn in existing test
|
||||
hcc_opts.eviction_effort_cap = 100;
|
||||
TieredCacheOptions opts;
|
||||
lru_opts.capacity = 0;
|
||||
lru_opts.num_shard_bits = 0;
|
||||
|
||||
Vendored
+3
-60
@@ -389,13 +389,12 @@ class ClockCacheTest : public testing::Test {
|
||||
}
|
||||
}
|
||||
|
||||
void NewShard(size_t capacity, bool strict_capacity_limit = true,
|
||||
int eviction_effort_cap = 30) {
|
||||
void NewShard(size_t capacity, bool strict_capacity_limit = true) {
|
||||
DeleteShard();
|
||||
shard_ =
|
||||
reinterpret_cast<Shard*>(port::cacheline_aligned_alloc(sizeof(Shard)));
|
||||
|
||||
TableOpts opts{1 /*value_size*/, eviction_effort_cap};
|
||||
TableOpts opts{1 /*value_size*/};
|
||||
new (shard_)
|
||||
Shard(capacity, strict_capacity_limit, kDontChargeCacheMetadata,
|
||||
/*allocator*/ nullptr, &eviction_callback_, &hash_seed_, opts);
|
||||
@@ -446,20 +445,12 @@ class ClockCacheTest : public testing::Test {
|
||||
return Slice(reinterpret_cast<const char*>(&hashed_key), 16U);
|
||||
}
|
||||
|
||||
// A bad hash function for testing / stressing collision handling
|
||||
static inline UniqueId64x2 TestHashedKey(char key) {
|
||||
// For testing hash near-collision behavior, put the variance in
|
||||
// hashed_key in bits that are unlikely to be used as hash bits.
|
||||
return {(static_cast<uint64_t>(key) << 56) + 1234U, 5678U};
|
||||
}
|
||||
|
||||
// A reasonable hash function, for testing "typical behavior" etc.
|
||||
template <typename T>
|
||||
static inline UniqueId64x2 CheapHash(T i) {
|
||||
return {static_cast<uint64_t>(i) * uint64_t{0x85EBCA77C2B2AE63},
|
||||
static_cast<uint64_t>(i) * uint64_t{0xC2B2AE3D27D4EB4F}};
|
||||
}
|
||||
|
||||
Shard* shard_ = nullptr;
|
||||
|
||||
private:
|
||||
@@ -692,53 +683,6 @@ TYPED_TEST(ClockCacheTest, ClockEvictionTest) {
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST(ClockCacheTest, ClockEvictionEffortCapTest) {
|
||||
using HandleImpl = typename ClockCacheTest<TypeParam>::Shard::HandleImpl;
|
||||
for (bool strict_capacity_limit : {true, false}) {
|
||||
SCOPED_TRACE("strict_capacity_limit = " +
|
||||
std::to_string(strict_capacity_limit));
|
||||
for (int eec : {-42, 0, 1, 10, 100, 1000}) {
|
||||
SCOPED_TRACE("eviction_effort_cap = " + std::to_string(eec));
|
||||
constexpr size_t kCapacity = 1000;
|
||||
// Start with much larger capacity to ensure that we can go way over
|
||||
// capacity without reaching table occupancy limit.
|
||||
this->NewShard(3 * kCapacity, strict_capacity_limit, eec);
|
||||
auto& shard = *this->shard_;
|
||||
shard.SetCapacity(kCapacity);
|
||||
|
||||
// Nearly fill the cache with pinned entries, then add a bunch of
|
||||
// non-pinned entries. eviction_effort_cap should affect how many
|
||||
// evictable entries are present beyond the cache capacity, despite
|
||||
// being evictable.
|
||||
constexpr size_t kCount = kCapacity - 1;
|
||||
std::unique_ptr<HandleImpl* []> ha { new HandleImpl* [kCount] {} };
|
||||
for (size_t i = 0; i < 2 * kCount; ++i) {
|
||||
UniqueId64x2 hkey = this->CheapHash(i);
|
||||
ASSERT_OK(shard.Insert(
|
||||
this->TestKey(hkey), hkey, nullptr /*value*/, &kNoopCacheItemHelper,
|
||||
1 /*charge*/, i < kCount ? &ha[i] : nullptr, Cache::Priority::LOW));
|
||||
}
|
||||
|
||||
if (strict_capacity_limit) {
|
||||
// If strict_capacity_limit is enabled, the cache will never exceed its
|
||||
// capacity
|
||||
EXPECT_EQ(shard.GetOccupancyCount(), kCapacity);
|
||||
} else {
|
||||
// Rough inverse relationship between cap and possible memory
|
||||
// explosion, which shows up as increased table occupancy count.
|
||||
int effective_eec = std::max(int{1}, eec) + 1;
|
||||
EXPECT_NEAR(shard.GetOccupancyCount() * 1.0,
|
||||
kCount * (1 + 1.4 / effective_eec),
|
||||
kCount * (0.6 / effective_eec) + 1.0);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < kCount; ++i) {
|
||||
shard.Release(ha[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct DeleteCounter {
|
||||
int deleted = 0;
|
||||
@@ -1091,8 +1035,7 @@ class TestSecondaryCache : public SecondaryCache {
|
||||
std::unique_ptr<SecondaryCacheResultHandle> Lookup(
|
||||
const Slice& key, const Cache::CacheItemHelper* helper,
|
||||
Cache::CreateContext* create_context, bool /*wait*/,
|
||||
bool /*advise_erase*/, Statistics* /*stats*/,
|
||||
bool& kept_in_sec_cache) override {
|
||||
bool /*advise_erase*/, bool& kept_in_sec_cache) override {
|
||||
std::string key_str = key.ToString();
|
||||
TEST_SYNC_POINT_CALLBACK("TestSecondaryCache::Lookup", &key_str);
|
||||
|
||||
|
||||
Vendored
+5
-6
@@ -294,8 +294,7 @@ Cache::Handle* CacheWithSecondaryAdapter::Lookup(const Slice& key,
|
||||
bool kept_in_sec_cache = false;
|
||||
std::unique_ptr<SecondaryCacheResultHandle> secondary_handle =
|
||||
secondary_cache_->Lookup(key, helper, create_context, /*wait*/ true,
|
||||
found_dummy_entry, stats,
|
||||
/*out*/ kept_in_sec_cache);
|
||||
found_dummy_entry, /*out*/ kept_in_sec_cache);
|
||||
if (secondary_handle) {
|
||||
result = Promote(std::move(secondary_handle), key, helper, priority,
|
||||
stats, found_dummy_entry, kept_in_sec_cache);
|
||||
@@ -349,10 +348,10 @@ void CacheWithSecondaryAdapter::StartAsyncLookupOnMySecondary(
|
||||
assert(async_handle.result_handle == nullptr);
|
||||
|
||||
std::unique_ptr<SecondaryCacheResultHandle> secondary_handle =
|
||||
secondary_cache_->Lookup(
|
||||
async_handle.key, async_handle.helper, async_handle.create_context,
|
||||
/*wait*/ false, async_handle.found_dummy_entry, async_handle.stats,
|
||||
/*out*/ async_handle.kept_in_sec_cache);
|
||||
secondary_cache_->Lookup(async_handle.key, async_handle.helper,
|
||||
async_handle.create_context, /*wait*/ false,
|
||||
async_handle.found_dummy_entry,
|
||||
/*out*/ async_handle.kept_in_sec_cache);
|
||||
if (secondary_handle) {
|
||||
// TODO with stacked secondaries: Check & process if already ready?
|
||||
async_handle.pending_handle = secondary_handle.release();
|
||||
|
||||
Vendored
+5
-13
@@ -5,8 +5,6 @@
|
||||
|
||||
#include "cache/tiered_secondary_cache.h"
|
||||
|
||||
#include "monitoring/statistics_impl.h"
|
||||
|
||||
namespace ROCKSDB_NAMESPACE {
|
||||
|
||||
// Creation callback for use in the lookup path. It calls the upper layer
|
||||
@@ -31,9 +29,6 @@ Status TieredSecondaryCache::MaybeInsertAndCreate(
|
||||
// TODO: Don't hardcode the source
|
||||
context->comp_sec_cache->InsertSaved(*context->key, data, type, source)
|
||||
.PermitUncheckedError();
|
||||
RecordTick(context->stats, COMPRESSED_SECONDARY_CACHE_PROMOTIONS);
|
||||
} else {
|
||||
RecordTick(context->stats, COMPRESSED_SECONDARY_CACHE_PROMOTION_SKIPS);
|
||||
}
|
||||
// Primary cache will accept the object, so call its helper to create
|
||||
// the object
|
||||
@@ -48,10 +43,10 @@ Status TieredSecondaryCache::MaybeInsertAndCreate(
|
||||
std::unique_ptr<SecondaryCacheResultHandle> TieredSecondaryCache::Lookup(
|
||||
const Slice& key, const Cache::CacheItemHelper* helper,
|
||||
Cache::CreateContext* create_context, bool wait, bool advise_erase,
|
||||
Statistics* stats, bool& kept_in_sec_cache) {
|
||||
bool& kept_in_sec_cache) {
|
||||
bool dummy = false;
|
||||
std::unique_ptr<SecondaryCacheResultHandle> result =
|
||||
target()->Lookup(key, helper, create_context, wait, advise_erase, stats,
|
||||
target()->Lookup(key, helper, create_context, wait, advise_erase,
|
||||
/*kept_in_sec_cache=*/dummy);
|
||||
// We never want the item to spill back into the secondary cache
|
||||
kept_in_sec_cache = true;
|
||||
@@ -71,10 +66,9 @@ std::unique_ptr<SecondaryCacheResultHandle> TieredSecondaryCache::Lookup(
|
||||
ctx.helper = helper;
|
||||
ctx.inner_ctx = create_context;
|
||||
ctx.comp_sec_cache = target();
|
||||
ctx.stats = stats;
|
||||
|
||||
return nvm_sec_cache_->Lookup(key, outer_helper, &ctx, wait, advise_erase,
|
||||
stats, kept_in_sec_cache);
|
||||
kept_in_sec_cache);
|
||||
}
|
||||
|
||||
// If wait is false, i.e its an async lookup, we have to allocate a result
|
||||
@@ -86,10 +80,8 @@ std::unique_ptr<SecondaryCacheResultHandle> TieredSecondaryCache::Lookup(
|
||||
handle->ctx()->helper = helper;
|
||||
handle->ctx()->inner_ctx = create_context;
|
||||
handle->ctx()->comp_sec_cache = target();
|
||||
handle->ctx()->stats = stats;
|
||||
handle->SetInnerHandle(
|
||||
nvm_sec_cache_->Lookup(key, outer_helper, handle->ctx(), wait,
|
||||
advise_erase, stats, kept_in_sec_cache));
|
||||
handle->SetInnerHandle(nvm_sec_cache_->Lookup(
|
||||
key, outer_helper, handle->ctx(), wait, advise_erase, kept_in_sec_cache));
|
||||
if (!handle->inner_handle()) {
|
||||
handle.reset();
|
||||
} else {
|
||||
|
||||
Vendored
+1
-2
@@ -59,7 +59,7 @@ class TieredSecondaryCache : public SecondaryCacheWrapper {
|
||||
virtual std::unique_ptr<SecondaryCacheResultHandle> Lookup(
|
||||
const Slice& key, const Cache::CacheItemHelper* helper,
|
||||
Cache::CreateContext* create_context, bool wait, bool advise_erase,
|
||||
Statistics* stats, bool& kept_in_sec_cache) override;
|
||||
bool& kept_in_sec_cache) override;
|
||||
|
||||
virtual void WaitAll(
|
||||
std::vector<SecondaryCacheResultHandle*> handles) override;
|
||||
@@ -72,7 +72,6 @@ class TieredSecondaryCache : public SecondaryCacheWrapper {
|
||||
Cache::CreateContext* inner_ctx;
|
||||
std::shared_ptr<SecondaryCacheResultHandle> inner_handle;
|
||||
SecondaryCache* comp_sec_cache;
|
||||
Statistics* stats;
|
||||
};
|
||||
|
||||
class ResultHandle : public SecondaryCacheResultHandle {
|
||||
|
||||
Vendored
+1
-1
@@ -62,7 +62,7 @@ class TestSecondaryCache : public SecondaryCache {
|
||||
std::unique_ptr<SecondaryCacheResultHandle> Lookup(
|
||||
const Slice& key, const Cache::CacheItemHelper* helper,
|
||||
Cache::CreateContext* create_context, bool wait, bool /*advise_erase*/,
|
||||
Statistics* /*stats*/, bool& kept_in_sec_cache) override {
|
||||
bool& kept_in_sec_cache) override {
|
||||
std::string key_str = key.ToString();
|
||||
TEST_SYNC_POINT_CALLBACK("TestSecondaryCache::Lookup", &key_str);
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ BlobFileBuilder::BlobFileBuilder(
|
||||
VersionSet* versions, FileSystem* fs,
|
||||
const ImmutableOptions* immutable_options,
|
||||
const MutableCFOptions* mutable_cf_options, const FileOptions* file_options,
|
||||
const WriteOptions* write_options, std::string db_id,
|
||||
std::string db_session_id, int job_id, uint32_t column_family_id,
|
||||
const std::string& column_family_name, Env::WriteLifeTimeHint write_hint,
|
||||
std::string db_id, std::string db_session_id, int job_id,
|
||||
uint32_t column_family_id, const std::string& column_family_name,
|
||||
Env::IOPriority io_priority, Env::WriteLifeTimeHint write_hint,
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
BlobFileCompletionCallback* blob_callback,
|
||||
BlobFileCreationReason creation_reason,
|
||||
@@ -44,18 +44,18 @@ BlobFileBuilder::BlobFileBuilder(
|
||||
std::vector<BlobFileAddition>* blob_file_additions)
|
||||
: BlobFileBuilder([versions]() { return versions->NewFileNumber(); }, fs,
|
||||
immutable_options, mutable_cf_options, file_options,
|
||||
write_options, db_id, db_session_id, job_id,
|
||||
column_family_id, column_family_name, write_hint,
|
||||
io_tracer, blob_callback, creation_reason,
|
||||
blob_file_paths, blob_file_additions) {}
|
||||
db_id, db_session_id, job_id, column_family_id,
|
||||
column_family_name, io_priority, write_hint, io_tracer,
|
||||
blob_callback, creation_reason, blob_file_paths,
|
||||
blob_file_additions) {}
|
||||
|
||||
BlobFileBuilder::BlobFileBuilder(
|
||||
std::function<uint64_t()> file_number_generator, FileSystem* fs,
|
||||
const ImmutableOptions* immutable_options,
|
||||
const MutableCFOptions* mutable_cf_options, const FileOptions* file_options,
|
||||
const WriteOptions* write_options, std::string db_id,
|
||||
std::string db_session_id, int job_id, uint32_t column_family_id,
|
||||
const std::string& column_family_name, Env::WriteLifeTimeHint write_hint,
|
||||
std::string db_id, std::string db_session_id, int job_id,
|
||||
uint32_t column_family_id, const std::string& column_family_name,
|
||||
Env::IOPriority io_priority, Env::WriteLifeTimeHint write_hint,
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
BlobFileCompletionCallback* blob_callback,
|
||||
BlobFileCreationReason creation_reason,
|
||||
@@ -69,12 +69,12 @@ BlobFileBuilder::BlobFileBuilder(
|
||||
blob_compression_type_(mutable_cf_options->blob_compression_type),
|
||||
prepopulate_blob_cache_(mutable_cf_options->prepopulate_blob_cache),
|
||||
file_options_(file_options),
|
||||
write_options_(write_options),
|
||||
db_id_(std::move(db_id)),
|
||||
db_session_id_(std::move(db_session_id)),
|
||||
job_id_(job_id),
|
||||
column_family_id_(column_family_id),
|
||||
column_family_name_(column_family_name),
|
||||
io_priority_(io_priority),
|
||||
write_hint_(write_hint),
|
||||
io_tracer_(io_tracer),
|
||||
blob_callback_(blob_callback),
|
||||
@@ -87,7 +87,6 @@ BlobFileBuilder::BlobFileBuilder(
|
||||
assert(fs_);
|
||||
assert(immutable_options_);
|
||||
assert(file_options_);
|
||||
assert(write_options_);
|
||||
assert(blob_file_paths_);
|
||||
assert(blob_file_paths_->empty());
|
||||
assert(blob_file_additions_);
|
||||
@@ -208,14 +207,14 @@ Status BlobFileBuilder::OpenBlobFileIfNeeded() {
|
||||
blob_file_paths_->emplace_back(std::move(blob_file_path));
|
||||
|
||||
assert(file);
|
||||
file->SetIOPriority(write_options_->rate_limiter_priority);
|
||||
file->SetIOPriority(io_priority_);
|
||||
file->SetWriteLifeTimeHint(write_hint_);
|
||||
FileTypeSet tmp_set = immutable_options_->checksum_handoff_file_types;
|
||||
Statistics* const statistics = immutable_options_->stats;
|
||||
std::unique_ptr<WritableFileWriter> file_writer(new WritableFileWriter(
|
||||
std::move(file), blob_file_paths_->back(), *file_options_,
|
||||
immutable_options_->clock, io_tracer_, statistics,
|
||||
Histograms::BLOB_DB_BLOB_FILE_WRITE_MICROS, immutable_options_->listeners,
|
||||
immutable_options_->listeners,
|
||||
immutable_options_->file_checksum_gen_factory.get(),
|
||||
tmp_set.Contains(FileType::kBlobFile), false));
|
||||
|
||||
@@ -232,7 +231,7 @@ Status BlobFileBuilder::OpenBlobFileIfNeeded() {
|
||||
expiration_range);
|
||||
|
||||
{
|
||||
Status s = blob_log_writer->WriteHeader(*write_options_, header);
|
||||
Status s = blob_log_writer->WriteHeader(header);
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"BlobFileBuilder::OpenBlobFileIfNeeded:WriteHeader", &s);
|
||||
@@ -297,8 +296,7 @@ Status BlobFileBuilder::WriteBlobToFile(const Slice& key, const Slice& blob,
|
||||
|
||||
uint64_t key_offset = 0;
|
||||
|
||||
Status s =
|
||||
writer_->AddRecord(*write_options_, key, blob, &key_offset, blob_offset);
|
||||
Status s = writer_->AddRecord(key, blob, &key_offset, blob_offset);
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("BlobFileBuilder::WriteBlobToFile:AddRecord", &s);
|
||||
|
||||
@@ -323,8 +321,7 @@ Status BlobFileBuilder::CloseBlobFile() {
|
||||
std::string checksum_method;
|
||||
std::string checksum_value;
|
||||
|
||||
Status s = writer_->AppendFooter(*write_options_, footer, &checksum_method,
|
||||
&checksum_value);
|
||||
Status s = writer_->AppendFooter(footer, &checksum_method, &checksum_value);
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("BlobFileBuilder::WriteBlobToFile:AppendFooter", &s);
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "rocksdb/advanced_options.h"
|
||||
#include "rocksdb/compression_type.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "rocksdb/rocksdb_namespace.h"
|
||||
#include "rocksdb/types.h"
|
||||
|
||||
@@ -37,11 +36,11 @@ class BlobFileBuilder {
|
||||
BlobFileBuilder(VersionSet* versions, FileSystem* fs,
|
||||
const ImmutableOptions* immutable_options,
|
||||
const MutableCFOptions* mutable_cf_options,
|
||||
const FileOptions* file_options,
|
||||
const WriteOptions* write_options, std::string db_id,
|
||||
const FileOptions* file_options, std::string db_id,
|
||||
std::string db_session_id, int job_id,
|
||||
uint32_t column_family_id,
|
||||
const std::string& column_family_name,
|
||||
Env::IOPriority io_priority,
|
||||
Env::WriteLifeTimeHint write_hint,
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
BlobFileCompletionCallback* blob_callback,
|
||||
@@ -52,11 +51,11 @@ class BlobFileBuilder {
|
||||
BlobFileBuilder(std::function<uint64_t()> file_number_generator,
|
||||
FileSystem* fs, const ImmutableOptions* immutable_options,
|
||||
const MutableCFOptions* mutable_cf_options,
|
||||
const FileOptions* file_options,
|
||||
const WriteOptions* write_options, std::string db_id,
|
||||
const FileOptions* file_options, std::string db_id,
|
||||
std::string db_session_id, int job_id,
|
||||
uint32_t column_family_id,
|
||||
const std::string& column_family_name,
|
||||
Env::IOPriority io_priority,
|
||||
Env::WriteLifeTimeHint write_hint,
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
BlobFileCompletionCallback* blob_callback,
|
||||
@@ -93,12 +92,12 @@ class BlobFileBuilder {
|
||||
CompressionType blob_compression_type_;
|
||||
PrepopulateBlobCache prepopulate_blob_cache_;
|
||||
const FileOptions* file_options_;
|
||||
const WriteOptions* write_options_;
|
||||
const std::string db_id_;
|
||||
const std::string db_session_id_;
|
||||
int job_id_;
|
||||
uint32_t column_family_id_;
|
||||
std::string column_family_name_;
|
||||
Env::IOPriority io_priority_;
|
||||
Env::WriteLifeTimeHint write_hint_;
|
||||
std::shared_ptr<IOTracer> io_tracer_;
|
||||
BlobFileCompletionCallback* blob_callback_;
|
||||
|
||||
@@ -43,7 +43,6 @@ class BlobFileBuilderTest : public testing::Test {
|
||||
mock_env_.reset(MockEnv::Create(Env::Default()));
|
||||
fs_ = mock_env_->GetFileSystem().get();
|
||||
clock_ = mock_env_->GetSystemClock().get();
|
||||
write_options_.rate_limiter_priority = Env::IO_HIGH;
|
||||
}
|
||||
|
||||
void VerifyBlobFile(uint64_t blob_file_number,
|
||||
@@ -114,7 +113,6 @@ class BlobFileBuilderTest : public testing::Test {
|
||||
FileSystem* fs_;
|
||||
SystemClock* clock_;
|
||||
FileOptions file_options_;
|
||||
WriteOptions write_options_;
|
||||
};
|
||||
|
||||
TEST_F(BlobFileBuilderTest, BuildAndCheckOneFile) {
|
||||
@@ -138,6 +136,7 @@ TEST_F(BlobFileBuilderTest, BuildAndCheckOneFile) {
|
||||
constexpr int job_id = 1;
|
||||
constexpr uint32_t column_family_id = 123;
|
||||
constexpr char column_family_name[] = "foobar";
|
||||
constexpr Env::IOPriority io_priority = Env::IO_HIGH;
|
||||
constexpr Env::WriteLifeTimeHint write_hint = Env::WLTH_MEDIUM;
|
||||
|
||||
std::vector<std::string> blob_file_paths;
|
||||
@@ -145,8 +144,8 @@ TEST_F(BlobFileBuilderTest, BuildAndCheckOneFile) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -222,6 +221,7 @@ TEST_F(BlobFileBuilderTest, BuildAndCheckMultipleFiles) {
|
||||
constexpr int job_id = 1;
|
||||
constexpr uint32_t column_family_id = 123;
|
||||
constexpr char column_family_name[] = "foobar";
|
||||
constexpr Env::IOPriority io_priority = Env::IO_HIGH;
|
||||
constexpr Env::WriteLifeTimeHint write_hint = Env::WLTH_MEDIUM;
|
||||
|
||||
std::vector<std::string> blob_file_paths;
|
||||
@@ -229,8 +229,8 @@ TEST_F(BlobFileBuilderTest, BuildAndCheckMultipleFiles) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -309,6 +309,7 @@ TEST_F(BlobFileBuilderTest, InlinedValues) {
|
||||
constexpr int job_id = 1;
|
||||
constexpr uint32_t column_family_id = 123;
|
||||
constexpr char column_family_name[] = "foobar";
|
||||
constexpr Env::IOPriority io_priority = Env::IO_HIGH;
|
||||
constexpr Env::WriteLifeTimeHint write_hint = Env::WLTH_MEDIUM;
|
||||
|
||||
std::vector<std::string> blob_file_paths;
|
||||
@@ -316,8 +317,8 @@ TEST_F(BlobFileBuilderTest, InlinedValues) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -363,6 +364,7 @@ TEST_F(BlobFileBuilderTest, Compression) {
|
||||
constexpr int job_id = 1;
|
||||
constexpr uint32_t column_family_id = 123;
|
||||
constexpr char column_family_name[] = "foobar";
|
||||
constexpr Env::IOPriority io_priority = Env::IO_HIGH;
|
||||
constexpr Env::WriteLifeTimeHint write_hint = Env::WLTH_MEDIUM;
|
||||
|
||||
std::vector<std::string> blob_file_paths;
|
||||
@@ -370,8 +372,8 @@ TEST_F(BlobFileBuilderTest, Compression) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -446,6 +448,7 @@ TEST_F(BlobFileBuilderTest, CompressionError) {
|
||||
constexpr int job_id = 1;
|
||||
constexpr uint32_t column_family_id = 123;
|
||||
constexpr char column_family_name[] = "foobar";
|
||||
constexpr Env::IOPriority io_priority = Env::IO_HIGH;
|
||||
constexpr Env::WriteLifeTimeHint write_hint = Env::WLTH_MEDIUM;
|
||||
|
||||
std::vector<std::string> blob_file_paths;
|
||||
@@ -453,8 +456,8 @@ TEST_F(BlobFileBuilderTest, CompressionError) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -525,6 +528,7 @@ TEST_F(BlobFileBuilderTest, Checksum) {
|
||||
constexpr int job_id = 1;
|
||||
constexpr uint32_t column_family_id = 123;
|
||||
constexpr char column_family_name[] = "foobar";
|
||||
constexpr Env::IOPriority io_priority = Env::IO_HIGH;
|
||||
constexpr Env::WriteLifeTimeHint write_hint = Env::WLTH_MEDIUM;
|
||||
|
||||
std::vector<std::string> blob_file_paths;
|
||||
@@ -532,8 +536,8 @@ TEST_F(BlobFileBuilderTest, Checksum) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -585,13 +589,11 @@ class BlobFileBuilderIOErrorTest
|
||||
BlobFileBuilderIOErrorTest() : sync_point_(GetParam()) {
|
||||
mock_env_.reset(MockEnv::Create(Env::Default()));
|
||||
fs_ = mock_env_->GetFileSystem().get();
|
||||
write_options_.rate_limiter_priority = Env::IO_HIGH;
|
||||
}
|
||||
|
||||
std::unique_ptr<Env> mock_env_;
|
||||
FileSystem* fs_;
|
||||
FileOptions file_options_;
|
||||
WriteOptions write_options_;
|
||||
std::string sync_point_;
|
||||
};
|
||||
|
||||
@@ -624,6 +626,7 @@ TEST_P(BlobFileBuilderIOErrorTest, IOError) {
|
||||
constexpr int job_id = 1;
|
||||
constexpr uint32_t column_family_id = 123;
|
||||
constexpr char column_family_name[] = "foobar";
|
||||
constexpr Env::IOPriority io_priority = Env::IO_HIGH;
|
||||
constexpr Env::WriteLifeTimeHint write_hint = Env::WLTH_MEDIUM;
|
||||
|
||||
std::vector<std::string> blob_file_paths;
|
||||
@@ -631,8 +634,8 @@ TEST_P(BlobFileBuilderIOErrorTest, IOError) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ void WriteBlobFile(uint32_t column_family_id,
|
||||
BlobLogHeader header(column_family_id, kNoCompression, has_ttl,
|
||||
expiration_range);
|
||||
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(WriteOptions(), header));
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(header));
|
||||
|
||||
constexpr char key[] = "key";
|
||||
constexpr char blob[] = "blob";
|
||||
@@ -67,8 +67,7 @@ void WriteBlobFile(uint32_t column_family_id,
|
||||
uint64_t key_offset = 0;
|
||||
uint64_t blob_offset = 0;
|
||||
|
||||
ASSERT_OK(blob_log_writer.AddRecord(WriteOptions(), key, blob, &key_offset,
|
||||
&blob_offset));
|
||||
ASSERT_OK(blob_log_writer.AddRecord(key, blob, &key_offset, &blob_offset));
|
||||
|
||||
BlobLogFooter footer;
|
||||
footer.blob_count = 1;
|
||||
@@ -77,8 +76,8 @@ void WriteBlobFile(uint32_t column_family_id,
|
||||
std::string checksum_method;
|
||||
std::string checksum_value;
|
||||
|
||||
ASSERT_OK(blob_log_writer.AppendFooter(WriteOptions(), footer,
|
||||
&checksum_method, &checksum_value));
|
||||
ASSERT_OK(
|
||||
blob_log_writer.AppendFooter(footer, &checksum_method, &checksum_value));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -63,7 +63,7 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
BlobLogHeader header(column_family_id, compression, has_ttl,
|
||||
expiration_range_header);
|
||||
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(WriteOptions(), header));
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(header));
|
||||
|
||||
std::vector<std::string> compressed_blobs(num);
|
||||
std::vector<Slice> blobs_to_write(num);
|
||||
@@ -91,8 +91,7 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
uint64_t key_offset = 0;
|
||||
ASSERT_OK(blob_log_writer.AddRecord(WriteOptions(), keys[i],
|
||||
blobs_to_write[i], &key_offset,
|
||||
ASSERT_OK(blob_log_writer.AddRecord(keys[i], blobs_to_write[i], &key_offset,
|
||||
&blob_offsets[i]));
|
||||
}
|
||||
|
||||
@@ -102,8 +101,8 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
|
||||
std::string checksum_method;
|
||||
std::string checksum_value;
|
||||
ASSERT_OK(blob_log_writer.AppendFooter(WriteOptions(), footer,
|
||||
&checksum_method, &checksum_value));
|
||||
ASSERT_OK(
|
||||
blob_log_writer.AppendFooter(footer, &checksum_method, &checksum_value));
|
||||
}
|
||||
|
||||
// Creates a test blob file with a single blob in it. Note: this method
|
||||
@@ -474,7 +473,7 @@ TEST_F(BlobFileReaderTest, Malformed) {
|
||||
BlobLogHeader header(column_family_id, kNoCompression, has_ttl,
|
||||
expiration_range);
|
||||
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(WriteOptions(), header));
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(header));
|
||||
}
|
||||
|
||||
constexpr HistogramImpl* blob_file_read_hist = nullptr;
|
||||
|
||||
+27
-56
@@ -33,49 +33,35 @@ BlobLogWriter::BlobLogWriter(std::unique_ptr<WritableFileWriter>&& dest,
|
||||
|
||||
BlobLogWriter::~BlobLogWriter() = default;
|
||||
|
||||
Status BlobLogWriter::Sync(const WriteOptions& write_options) {
|
||||
Status BlobLogWriter::Sync() {
|
||||
TEST_SYNC_POINT("BlobLogWriter::Sync");
|
||||
|
||||
StopWatch sync_sw(clock_, statistics_, BLOB_DB_BLOB_FILE_SYNC_MICROS);
|
||||
IOOptions opts;
|
||||
Status s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (s.ok()) {
|
||||
s = dest_->Sync(opts, use_fsync_);
|
||||
}
|
||||
if (s.ok()) {
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_SYNCED);
|
||||
}
|
||||
Status s = dest_->Sync(use_fsync_);
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_SYNCED);
|
||||
return s;
|
||||
}
|
||||
|
||||
Status BlobLogWriter::WriteHeader(const WriteOptions& write_options,
|
||||
BlobLogHeader& header) {
|
||||
Status BlobLogWriter::WriteHeader(BlobLogHeader& header) {
|
||||
assert(block_offset_ == 0);
|
||||
assert(last_elem_type_ == kEtNone);
|
||||
std::string str;
|
||||
header.EncodeTo(&str);
|
||||
|
||||
IOOptions opts;
|
||||
Status s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(opts, Slice(str));
|
||||
}
|
||||
Status s = dest_->Append(Slice(str));
|
||||
if (s.ok()) {
|
||||
block_offset_ += str.size();
|
||||
if (do_flush_) {
|
||||
s = dest_->Flush(opts);
|
||||
s = dest_->Flush();
|
||||
}
|
||||
}
|
||||
last_elem_type_ = kEtFileHdr;
|
||||
if (s.ok()) {
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogHeader::kSize);
|
||||
}
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogHeader::kSize);
|
||||
return s;
|
||||
}
|
||||
|
||||
Status BlobLogWriter::AppendFooter(const WriteOptions& write_options,
|
||||
BlobLogFooter& footer,
|
||||
Status BlobLogWriter::AppendFooter(BlobLogFooter& footer,
|
||||
std::string* checksum_method,
|
||||
std::string* checksum_value) {
|
||||
assert(block_offset_ != 0);
|
||||
@@ -89,17 +75,14 @@ Status BlobLogWriter::AppendFooter(const WriteOptions& write_options,
|
||||
s.PermitUncheckedError();
|
||||
return Status::IOError("Seen Error. Skip closing.");
|
||||
} else {
|
||||
IOOptions opts;
|
||||
s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(opts, Slice(str));
|
||||
}
|
||||
s = dest_->Append(Slice(str));
|
||||
if (s.ok()) {
|
||||
block_offset_ += str.size();
|
||||
s = Sync(write_options);
|
||||
|
||||
s = Sync();
|
||||
|
||||
if (s.ok()) {
|
||||
s = dest_->Close(opts);
|
||||
s = dest_->Close();
|
||||
|
||||
if (s.ok()) {
|
||||
assert(!!checksum_method == !!checksum_value);
|
||||
@@ -128,15 +111,12 @@ Status BlobLogWriter::AppendFooter(const WriteOptions& write_options,
|
||||
}
|
||||
|
||||
last_elem_type_ = kEtFileFooter;
|
||||
if (s.ok()) {
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogFooter::kSize);
|
||||
}
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogFooter::kSize);
|
||||
return s;
|
||||
}
|
||||
|
||||
Status BlobLogWriter::AddRecord(const WriteOptions& write_options,
|
||||
const Slice& key, const Slice& val,
|
||||
Status BlobLogWriter::AddRecord(const Slice& key, const Slice& val,
|
||||
uint64_t expiration, uint64_t* key_offset,
|
||||
uint64_t* blob_offset) {
|
||||
assert(block_offset_ != 0);
|
||||
@@ -145,13 +125,11 @@ Status BlobLogWriter::AddRecord(const WriteOptions& write_options,
|
||||
std::string buf;
|
||||
ConstructBlobHeader(&buf, key, val, expiration);
|
||||
|
||||
Status s =
|
||||
EmitPhysicalRecord(write_options, buf, key, val, key_offset, blob_offset);
|
||||
Status s = EmitPhysicalRecord(buf, key, val, key_offset, blob_offset);
|
||||
return s;
|
||||
}
|
||||
|
||||
Status BlobLogWriter::AddRecord(const WriteOptions& write_options,
|
||||
const Slice& key, const Slice& val,
|
||||
Status BlobLogWriter::AddRecord(const Slice& key, const Slice& val,
|
||||
uint64_t* key_offset, uint64_t* blob_offset) {
|
||||
assert(block_offset_ != 0);
|
||||
assert(last_elem_type_ == kEtFileHdr || last_elem_type_ == kEtRecord);
|
||||
@@ -159,8 +137,7 @@ Status BlobLogWriter::AddRecord(const WriteOptions& write_options,
|
||||
std::string buf;
|
||||
ConstructBlobHeader(&buf, key, val, 0);
|
||||
|
||||
Status s =
|
||||
EmitPhysicalRecord(write_options, buf, key, val, key_offset, blob_offset);
|
||||
Status s = EmitPhysicalRecord(buf, key, val, key_offset, blob_offset);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -173,34 +150,28 @@ void BlobLogWriter::ConstructBlobHeader(std::string* buf, const Slice& key,
|
||||
record.EncodeHeaderTo(buf);
|
||||
}
|
||||
|
||||
Status BlobLogWriter::EmitPhysicalRecord(const WriteOptions& write_options,
|
||||
const std::string& headerbuf,
|
||||
Status BlobLogWriter::EmitPhysicalRecord(const std::string& headerbuf,
|
||||
const Slice& key, const Slice& val,
|
||||
uint64_t* key_offset,
|
||||
uint64_t* blob_offset) {
|
||||
IOOptions opts;
|
||||
Status s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
StopWatch write_sw(clock_, statistics_, BLOB_DB_BLOB_FILE_WRITE_MICROS);
|
||||
Status s = dest_->Append(Slice(headerbuf));
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(opts, Slice(headerbuf));
|
||||
s = dest_->Append(key);
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(opts, key);
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(opts, val);
|
||||
s = dest_->Append(val);
|
||||
}
|
||||
if (do_flush_ && s.ok()) {
|
||||
s = dest_->Flush(opts);
|
||||
s = dest_->Flush();
|
||||
}
|
||||
|
||||
*key_offset = block_offset_ + BlobLogRecord::kHeaderSize;
|
||||
*blob_offset = *key_offset + key.size();
|
||||
block_offset_ = *blob_offset + val.size();
|
||||
last_elem_type_ = kEtRecord;
|
||||
if (s.ok()) {
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogRecord::kHeaderSize + key.size() + val.size());
|
||||
}
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogRecord::kHeaderSize + key.size() + val.size());
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,24 +43,20 @@ class BlobLogWriter {
|
||||
static void ConstructBlobHeader(std::string* buf, const Slice& key,
|
||||
const Slice& val, uint64_t expiration);
|
||||
|
||||
Status AddRecord(const WriteOptions& write_options, const Slice& key,
|
||||
const Slice& val, uint64_t* key_offset,
|
||||
Status AddRecord(const Slice& key, const Slice& val, uint64_t* key_offset,
|
||||
uint64_t* blob_offset);
|
||||
|
||||
Status AddRecord(const WriteOptions& write_options, const Slice& key,
|
||||
const Slice& val, uint64_t expiration, uint64_t* key_offset,
|
||||
uint64_t* blob_offset);
|
||||
Status AddRecord(const Slice& key, const Slice& val, uint64_t expiration,
|
||||
uint64_t* key_offset, uint64_t* blob_offset);
|
||||
|
||||
Status EmitPhysicalRecord(const WriteOptions& write_options,
|
||||
const std::string& headerbuf, const Slice& key,
|
||||
Status EmitPhysicalRecord(const std::string& headerbuf, const Slice& key,
|
||||
const Slice& val, uint64_t* key_offset,
|
||||
uint64_t* blob_offset);
|
||||
|
||||
Status AppendFooter(const WriteOptions& write_options, BlobLogFooter& footer,
|
||||
std::string* checksum_method,
|
||||
Status AppendFooter(BlobLogFooter& footer, std::string* checksum_method,
|
||||
std::string* checksum_value);
|
||||
|
||||
Status WriteHeader(const WriteOptions& write_options, BlobLogHeader& header);
|
||||
Status WriteHeader(BlobLogHeader& header);
|
||||
|
||||
WritableFileWriter* file() { return dest_.get(); }
|
||||
|
||||
@@ -68,7 +64,7 @@ class BlobLogWriter {
|
||||
|
||||
uint64_t get_log_number() const { return log_number_; }
|
||||
|
||||
Status Sync(const WriteOptions& write_options);
|
||||
Status Sync();
|
||||
|
||||
private:
|
||||
std::unique_ptr<WritableFileWriter> dest_;
|
||||
|
||||
@@ -65,7 +65,7 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
BlobLogHeader header(column_family_id, compression, has_ttl,
|
||||
expiration_range_header);
|
||||
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(WriteOptions(), header));
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(header));
|
||||
|
||||
std::vector<std::string> compressed_blobs(num);
|
||||
std::vector<Slice> blobs_to_write(num);
|
||||
@@ -93,8 +93,7 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
uint64_t key_offset = 0;
|
||||
ASSERT_OK(blob_log_writer.AddRecord(WriteOptions(), keys[i],
|
||||
blobs_to_write[i], &key_offset,
|
||||
ASSERT_OK(blob_log_writer.AddRecord(keys[i], blobs_to_write[i], &key_offset,
|
||||
&blob_offsets[i]));
|
||||
}
|
||||
|
||||
@@ -104,8 +103,8 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
|
||||
std::string checksum_method;
|
||||
std::string checksum_value;
|
||||
ASSERT_OK(blob_log_writer.AppendFooter(WriteOptions(), footer,
|
||||
&checksum_method, &checksum_value));
|
||||
ASSERT_OK(
|
||||
blob_log_writer.AppendFooter(footer, &checksum_method, &checksum_value));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
@@ -1221,7 +1220,7 @@ TEST_F(BlobSecondaryCacheTest, GetBlobsFromSecondaryCache) {
|
||||
auto sec_handle0 = secondary_cache->Lookup(
|
||||
key0, BlobSource::SharedCacheInterface::GetFullHelper(),
|
||||
/*context*/ nullptr, true,
|
||||
/*advise_erase=*/true, /*stats=*/nullptr, kept_in_sec_cache);
|
||||
/*advise_erase=*/true, kept_in_sec_cache);
|
||||
ASSERT_FALSE(kept_in_sec_cache);
|
||||
ASSERT_NE(sec_handle0, nullptr);
|
||||
ASSERT_TRUE(sec_handle0->IsReady());
|
||||
@@ -1249,7 +1248,7 @@ TEST_F(BlobSecondaryCacheTest, GetBlobsFromSecondaryCache) {
|
||||
auto sec_handle1 = secondary_cache->Lookup(
|
||||
key1, BlobSource::SharedCacheInterface::GetFullHelper(),
|
||||
/*context*/ nullptr, true,
|
||||
/*advise_erase=*/true, /*stats=*/nullptr, kept_in_sec_cache);
|
||||
/*advise_erase=*/true, kept_in_sec_cache);
|
||||
ASSERT_FALSE(kept_in_sec_cache);
|
||||
ASSERT_EQ(sec_handle1, nullptr);
|
||||
|
||||
|
||||
@@ -11,10 +11,8 @@ FilePrefetchBuffer* PrefetchBufferCollection::GetOrCreatePrefetchBuffer(
|
||||
uint64_t file_number) {
|
||||
auto& prefetch_buffer = prefetch_buffers_[file_number];
|
||||
if (!prefetch_buffer) {
|
||||
ReadaheadParams readahead_params;
|
||||
readahead_params.initial_readahead_size = readahead_size_;
|
||||
readahead_params.max_readahead_size = readahead_size_;
|
||||
prefetch_buffer.reset(new FilePrefetchBuffer(readahead_params));
|
||||
prefetch_buffer.reset(
|
||||
new FilePrefetchBuffer(readahead_size_, readahead_size_));
|
||||
}
|
||||
|
||||
return prefetch_buffer.get();
|
||||
|
||||
+26
-42
@@ -32,11 +32,9 @@
|
||||
#include "options/options_helper.h"
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/file_system.h"
|
||||
#include "rocksdb/iterator.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "rocksdb/table.h"
|
||||
#include "seqno_to_time_mapping.h"
|
||||
#include "table/block_based/block_based_table_builder.h"
|
||||
#include "table/format.h"
|
||||
#include "table/internal_iterator.h"
|
||||
@@ -59,8 +57,8 @@ TableBuilder* NewTableBuilder(const TableBuilderOptions& tboptions,
|
||||
Status BuildTable(
|
||||
const std::string& dbname, VersionSet* versions,
|
||||
const ImmutableDBOptions& db_options, const TableBuilderOptions& tboptions,
|
||||
const FileOptions& file_options, TableCache* table_cache,
|
||||
InternalIterator* iter,
|
||||
const FileOptions& file_options, const ReadOptions& read_options,
|
||||
TableCache* table_cache, InternalIterator* iter,
|
||||
std::vector<std::unique_ptr<FragmentedRangeTombstoneIterator>>
|
||||
range_del_iters,
|
||||
FileMetaData* meta, std::vector<BlobFileAddition>* blob_file_additions,
|
||||
@@ -71,8 +69,9 @@ Status BuildTable(
|
||||
IOStatus* io_status, const std::shared_ptr<IOTracer>& io_tracer,
|
||||
BlobFileCreationReason blob_creation_reason,
|
||||
const SeqnoToTimeMapping& seqno_to_time_mapping, EventLogger* event_logger,
|
||||
int job_id, TableProperties* table_properties,
|
||||
Env::WriteLifeTimeHint write_hint, const std::string* full_history_ts_low,
|
||||
int job_id, const Env::IOPriority io_priority,
|
||||
TableProperties* table_properties, Env::WriteLifeTimeHint write_hint,
|
||||
const std::string* full_history_ts_low,
|
||||
BlobFileCompletionCallback* blob_callback, Version* version,
|
||||
uint64_t* num_input_entries, uint64_t* memtable_payload_bytes,
|
||||
uint64_t* memtable_garbage_bytes) {
|
||||
@@ -165,11 +164,11 @@ Status BuildTable(
|
||||
|
||||
table_file_created = true;
|
||||
FileTypeSet tmp_set = ioptions.checksum_handoff_file_types;
|
||||
file->SetIOPriority(tboptions.write_options.rate_limiter_priority);
|
||||
file->SetIOPriority(io_priority);
|
||||
file->SetWriteLifeTimeHint(write_hint);
|
||||
file_writer.reset(new WritableFileWriter(
|
||||
std::move(file), fname, file_options, ioptions.clock, io_tracer,
|
||||
ioptions.stats, Histograms::SST_WRITE_MICROS, ioptions.listeners,
|
||||
ioptions.stats, ioptions.listeners,
|
||||
ioptions.file_checksum_gen_factory.get(),
|
||||
tmp_set.Contains(FileType::kTableFile), false));
|
||||
|
||||
@@ -189,11 +188,10 @@ Status BuildTable(
|
||||
blob_file_additions)
|
||||
? new BlobFileBuilder(
|
||||
versions, fs, &ioptions, &mutable_cf_options, &file_options,
|
||||
&(tboptions.write_options), tboptions.db_id,
|
||||
tboptions.db_session_id, job_id, tboptions.column_family_id,
|
||||
tboptions.column_family_name, write_hint, io_tracer,
|
||||
blob_callback, blob_creation_reason, &blob_file_paths,
|
||||
blob_file_additions)
|
||||
tboptions.db_id, tboptions.db_session_id, job_id,
|
||||
tboptions.column_family_id, tboptions.column_family_name,
|
||||
io_priority, write_hint, io_tracer, blob_callback,
|
||||
blob_creation_reason, &blob_file_paths, blob_file_additions)
|
||||
: nullptr);
|
||||
|
||||
const std::atomic<bool> kManualCompactionCanceledFalse{false};
|
||||
@@ -246,11 +244,7 @@ Status BuildTable(
|
||||
}
|
||||
|
||||
// TODO(noetzli): Update stats after flush, too.
|
||||
// TODO(hx235): Replace `rate_limiter_priority` with `io_activity` for
|
||||
// flush IO in repair when we have an `Env::IOActivity` enum for it
|
||||
if ((tboptions.write_options.io_activity == Env::IOActivity::kFlush ||
|
||||
tboptions.write_options.io_activity == Env::IOActivity::kDBOpen ||
|
||||
tboptions.write_options.rate_limiter_priority == Env::IO_HIGH) &&
|
||||
if (io_priority == Env::IO_HIGH &&
|
||||
IOSTATS(bytes_written) >= kReportFlushIOStatsEvery) {
|
||||
ThreadStatusUtil::SetThreadOperationProperty(
|
||||
ThreadStatus::FLUSH_BYTES_WRITTEN, IOSTATS(bytes_written));
|
||||
@@ -281,7 +275,7 @@ Status BuildTable(
|
||||
SizeApproximationOptions approx_opts;
|
||||
approx_opts.files_size_error_margin = 0.1;
|
||||
meta->compensated_range_deletion_size += versions->ApproximateSize(
|
||||
approx_opts, tboptions.read_options, version, kv.first.Encode(),
|
||||
approx_opts, read_options, version, kv.first.Encode(),
|
||||
tombstone_end.Encode(), 0 /* start_level */, -1 /* end_level */,
|
||||
TableReaderCaller::kFlush);
|
||||
}
|
||||
@@ -300,14 +294,12 @@ Status BuildTable(
|
||||
if (!s.ok() || empty) {
|
||||
builder->Abandon();
|
||||
} else {
|
||||
SeqnoToTimeMapping relevant_mapping;
|
||||
relevant_mapping.CopyFromSeqnoRange(seqno_to_time_mapping,
|
||||
meta->fd.smallest_seqno,
|
||||
meta->fd.largest_seqno);
|
||||
relevant_mapping.SetCapacity(kMaxSeqnoTimePairsPerSST);
|
||||
relevant_mapping.Enforce(tboptions.file_creation_time);
|
||||
std::string seqno_to_time_mapping_str;
|
||||
seqno_to_time_mapping.Encode(
|
||||
seqno_to_time_mapping_str, meta->fd.smallest_seqno,
|
||||
meta->fd.largest_seqno, meta->file_creation_time);
|
||||
builder->SetSeqnoTimeTableProperties(
|
||||
relevant_mapping,
|
||||
seqno_to_time_mapping_str,
|
||||
ioptions.compaction_style == CompactionStyle::kCompactionStyleFIFO
|
||||
? meta->file_creation_time
|
||||
: meta->oldest_ancester_time);
|
||||
@@ -354,16 +346,13 @@ Status BuildTable(
|
||||
|
||||
// Finish and check for file errors
|
||||
TEST_SYNC_POINT("BuildTable:BeforeSyncTable");
|
||||
IOOptions opts;
|
||||
*io_status =
|
||||
WritableFileWriter::PrepareIOOptions(tboptions.write_options, opts);
|
||||
if (s.ok() && io_status->ok() && !empty) {
|
||||
if (s.ok() && !empty) {
|
||||
StopWatch sw(ioptions.clock, ioptions.stats, TABLE_SYNC_MICROS);
|
||||
*io_status = file_writer->Sync(opts, ioptions.use_fsync);
|
||||
*io_status = file_writer->Sync(ioptions.use_fsync);
|
||||
}
|
||||
TEST_SYNC_POINT("BuildTable:BeforeCloseTableFile");
|
||||
if (s.ok() && io_status->ok() && !empty) {
|
||||
*io_status = file_writer->Close(opts);
|
||||
*io_status = file_writer->Close();
|
||||
}
|
||||
if (s.ok() && io_status->ok() && !empty) {
|
||||
// Add the checksum information to file metadata.
|
||||
@@ -407,9 +396,9 @@ Status BuildTable(
|
||||
// No matter whether use_direct_io_for_flush_and_compaction is true,
|
||||
// the goal is to cache it here for further user reads.
|
||||
std::unique_ptr<InternalIterator> it(table_cache->NewIterator(
|
||||
tboptions.read_options, file_options, tboptions.internal_comparator,
|
||||
*meta, nullptr /* range_del_agg */,
|
||||
mutable_cf_options.prefix_extractor, nullptr,
|
||||
read_options, file_options, tboptions.internal_comparator, *meta,
|
||||
nullptr /* range_del_agg */, mutable_cf_options.prefix_extractor,
|
||||
nullptr,
|
||||
(internal_stats == nullptr) ? nullptr
|
||||
: internal_stats->GetFileReadHist(0),
|
||||
TableReaderCaller::kFlush, /*arena=*/nullptr,
|
||||
@@ -447,13 +436,8 @@ Status BuildTable(
|
||||
constexpr IODebugContext* dbg = nullptr;
|
||||
|
||||
if (table_file_created) {
|
||||
IOOptions opts;
|
||||
Status prepare =
|
||||
WritableFileWriter::PrepareIOOptions(tboptions.write_options, opts);
|
||||
if (prepare.ok()) {
|
||||
Status ignored = fs->DeleteFile(fname, opts, dbg);
|
||||
ignored.PermitUncheckedError();
|
||||
}
|
||||
Status ignored = fs->DeleteFile(fname, IOOptions(), dbg);
|
||||
ignored.PermitUncheckedError();
|
||||
}
|
||||
|
||||
assert(blob_file_additions || blob_file_paths.empty());
|
||||
|
||||
+3
-2
@@ -53,8 +53,8 @@ TableBuilder* NewTableBuilder(const TableBuilderOptions& tboptions,
|
||||
extern Status BuildTable(
|
||||
const std::string& dbname, VersionSet* versions,
|
||||
const ImmutableDBOptions& db_options, const TableBuilderOptions& tboptions,
|
||||
const FileOptions& file_options, TableCache* table_cache,
|
||||
InternalIterator* iter,
|
||||
const FileOptions& file_options, const ReadOptions& read_options,
|
||||
TableCache* table_cache, InternalIterator* iter,
|
||||
std::vector<std::unique_ptr<FragmentedRangeTombstoneIterator>>
|
||||
range_del_iters,
|
||||
FileMetaData* meta, std::vector<BlobFileAddition>* blob_file_additions,
|
||||
@@ -66,6 +66,7 @@ extern Status BuildTable(
|
||||
BlobFileCreationReason blob_creation_reason,
|
||||
const SeqnoToTimeMapping& seqno_to_time_mapping,
|
||||
EventLogger* event_logger = nullptr, int job_id = 0,
|
||||
const Env::IOPriority io_priority = Env::IO_HIGH,
|
||||
TableProperties* table_properties = nullptr,
|
||||
Env::WriteLifeTimeHint write_hint = Env::WLTH_NOT_SET,
|
||||
const std::string* full_history_ts_low = nullptr,
|
||||
|
||||
@@ -3049,14 +3049,6 @@ void rocksdb_options_set_max_bytes_for_level_multiplier_additional(
|
||||
}
|
||||
}
|
||||
|
||||
void rocksdb_options_set_ttl(rocksdb_options_t* opt, uint64_t seconds) {
|
||||
opt->rep.ttl = seconds;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_options_get_ttl(rocksdb_options_t* opt) {
|
||||
return opt->rep.ttl;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_periodic_compaction_seconds(rocksdb_options_t* opt,
|
||||
uint64_t seconds) {
|
||||
opt->rep.periodic_compaction_seconds = seconds;
|
||||
|
||||
@@ -1925,9 +1925,6 @@ int main(int argc, char** argv) {
|
||||
CheckCondition(100000 ==
|
||||
rocksdb_options_get_periodic_compaction_seconds(o));
|
||||
|
||||
rocksdb_options_set_ttl(o, 5000);
|
||||
CheckCondition(5000 == rocksdb_options_get_ttl(o));
|
||||
|
||||
rocksdb_options_set_skip_stats_update_on_db_open(o, 1);
|
||||
CheckCondition(1 == rocksdb_options_get_skip_stats_update_on_db_open(o));
|
||||
|
||||
@@ -2364,10 +2361,6 @@ int main(int argc, char** argv) {
|
||||
CheckCondition(100000 ==
|
||||
rocksdb_options_get_periodic_compaction_seconds(o));
|
||||
|
||||
rocksdb_options_set_ttl(copy, 8000);
|
||||
CheckCondition(8000 == rocksdb_options_get_ttl(copy));
|
||||
CheckCondition(5000 == rocksdb_options_get_ttl(o));
|
||||
|
||||
rocksdb_options_set_skip_stats_update_on_db_open(copy, 0);
|
||||
CheckCondition(0 == rocksdb_options_get_skip_stats_update_on_db_open(copy));
|
||||
CheckCondition(1 == rocksdb_options_get_skip_stats_update_on_db_open(o));
|
||||
|
||||
+22
-51
@@ -322,8 +322,8 @@ ColumnFamilyOptions SanitizeOptions(const ImmutableDBOptions& db_options,
|
||||
}
|
||||
ROCKS_LOG_WARN(db_options.logger,
|
||||
"Adjust the value to "
|
||||
"level0_stop_writes_trigger(%d) "
|
||||
"level0_slowdown_writes_trigger(%d) "
|
||||
"level0_stop_writes_trigger(%d)"
|
||||
"level0_slowdown_writes_trigger(%d)"
|
||||
"level0_file_num_compaction_trigger(%d)",
|
||||
result.level0_stop_writes_trigger,
|
||||
result.level0_slowdown_writes_trigger,
|
||||
@@ -358,16 +358,16 @@ ColumnFamilyOptions SanitizeOptions(const ImmutableDBOptions& db_options,
|
||||
|
||||
if (result.level_compaction_dynamic_level_bytes) {
|
||||
if (result.compaction_style != kCompactionStyleLevel) {
|
||||
ROCKS_LOG_INFO(db_options.info_log.get(),
|
||||
"level_compaction_dynamic_level_bytes only makes sense "
|
||||
ROCKS_LOG_WARN(db_options.info_log.get(),
|
||||
"level_compaction_dynamic_level_bytes only makes sense"
|
||||
"for level-based compaction");
|
||||
result.level_compaction_dynamic_level_bytes = false;
|
||||
} else if (result.cf_paths.size() > 1U) {
|
||||
// we don't yet know how to make both of this feature and multiple
|
||||
// DB path work.
|
||||
ROCKS_LOG_WARN(db_options.info_log.get(),
|
||||
"multiple cf_paths/db_paths and "
|
||||
"level_compaction_dynamic_level_bytes "
|
||||
"multiple cf_paths/db_paths and"
|
||||
"level_compaction_dynamic_level_bytes"
|
||||
"can't be used together");
|
||||
result.level_compaction_dynamic_level_bytes = false;
|
||||
}
|
||||
@@ -833,8 +833,8 @@ std::unique_ptr<WriteControllerToken> SetupDelay(
|
||||
return write_controller->GetDelayToken(write_rate);
|
||||
}
|
||||
|
||||
int GetL0FileCountForCompactionSpeedup(int level0_file_num_compaction_trigger,
|
||||
int level0_slowdown_writes_trigger) {
|
||||
int GetL0ThresholdSpeedupCompaction(int level0_file_num_compaction_trigger,
|
||||
int level0_slowdown_writes_trigger) {
|
||||
// SanitizeOptions() ensures it.
|
||||
assert(level0_file_num_compaction_trigger <= level0_slowdown_writes_trigger);
|
||||
|
||||
@@ -864,35 +864,6 @@ int GetL0FileCountForCompactionSpeedup(int level0_file_num_compaction_trigger,
|
||||
return static_cast<int>(res);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t GetPendingCompactionBytesForCompactionSpeedup(
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
const VersionStorageInfo* vstorage) {
|
||||
// Compaction debt relatively large compared to the stable (bottommost) data
|
||||
// size indicates compaction fell behind.
|
||||
const uint64_t kBottommostSizeDivisor = 8;
|
||||
// Meaningful progress toward the slowdown trigger is another good indication.
|
||||
const uint64_t kSlowdownTriggerDivisor = 4;
|
||||
|
||||
uint64_t bottommost_files_size = 0;
|
||||
for (const auto& level_and_file : vstorage->BottommostFiles()) {
|
||||
bottommost_files_size += level_and_file.second->fd.GetFileSize();
|
||||
}
|
||||
|
||||
// Slowdown trigger might be zero but that means compaction speedup should
|
||||
// always happen (undocumented/historical), so no special treatment is needed.
|
||||
uint64_t slowdown_threshold =
|
||||
mutable_cf_options.soft_pending_compaction_bytes_limit /
|
||||
kSlowdownTriggerDivisor;
|
||||
|
||||
// Size of zero, however, should not be used to decide to speedup compaction.
|
||||
if (bottommost_files_size == 0) {
|
||||
return slowdown_threshold;
|
||||
}
|
||||
|
||||
uint64_t size_threshold = bottommost_files_size / kBottommostSizeDivisor;
|
||||
return std::min(size_threshold, slowdown_threshold);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
std::pair<WriteStallCondition, WriteStallCause>
|
||||
@@ -1048,7 +1019,7 @@ WriteStallCondition ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
} else {
|
||||
assert(write_stall_condition == WriteStallCondition::kNormal);
|
||||
if (vstorage->l0_delay_trigger_count() >=
|
||||
GetL0FileCountForCompactionSpeedup(
|
||||
GetL0ThresholdSpeedupCompaction(
|
||||
mutable_cf_options.level0_file_num_compaction_trigger,
|
||||
mutable_cf_options.level0_slowdown_writes_trigger)) {
|
||||
write_controller_token_ =
|
||||
@@ -1058,22 +1029,22 @@ WriteStallCondition ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
"[%s] Increasing compaction threads because we have %d level-0 "
|
||||
"files ",
|
||||
name_.c_str(), vstorage->l0_delay_trigger_count());
|
||||
} else if (mutable_cf_options.soft_pending_compaction_bytes_limit == 0) {
|
||||
} else if (vstorage->estimated_compaction_needed_bytes() >=
|
||||
mutable_cf_options.soft_pending_compaction_bytes_limit / 4) {
|
||||
// Increase compaction threads if bytes needed for compaction exceeds
|
||||
// 1/4 of threshold for slowing down.
|
||||
// If soft pending compaction byte limit is not set, always speed up
|
||||
// compaction.
|
||||
write_controller_token_ =
|
||||
write_controller->GetCompactionPressureToken();
|
||||
} else if (vstorage->estimated_compaction_needed_bytes() >=
|
||||
GetPendingCompactionBytesForCompactionSpeedup(
|
||||
mutable_cf_options, vstorage)) {
|
||||
write_controller_token_ =
|
||||
write_controller->GetCompactionPressureToken();
|
||||
ROCKS_LOG_INFO(
|
||||
ioptions_.logger,
|
||||
"[%s] Increasing compaction threads because of estimated pending "
|
||||
"compaction "
|
||||
"bytes %" PRIu64,
|
||||
name_.c_str(), vstorage->estimated_compaction_needed_bytes());
|
||||
if (mutable_cf_options.soft_pending_compaction_bytes_limit > 0) {
|
||||
ROCKS_LOG_INFO(
|
||||
ioptions_.logger,
|
||||
"[%s] Increasing compaction threads because of estimated pending "
|
||||
"compaction "
|
||||
"bytes %" PRIu64,
|
||||
name_.c_str(), vstorage->estimated_compaction_needed_bytes());
|
||||
}
|
||||
} else {
|
||||
write_controller_token_.reset();
|
||||
}
|
||||
@@ -1167,7 +1138,7 @@ Status ColumnFamilyData::RangesOverlapWithMemtables(
|
||||
*overlap = false;
|
||||
// Create an InternalIterator over all unflushed memtables
|
||||
Arena arena;
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
ReadOptions read_opts;
|
||||
read_opts.total_order_seek = true;
|
||||
MergeIteratorBuilder merge_iter_builder(&internal_comparator_, &arena);
|
||||
|
||||
@@ -2971,43 +2971,6 @@ TEST_P(ColumnFamilyTest, CompactionSpeedupTwoColumnFamilies) {
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
|
||||
TEST_P(ColumnFamilyTest, CompactionSpeedupForCompactionDebt) {
|
||||
db_options_.max_background_compactions = 6;
|
||||
Open();
|
||||
ColumnFamilyData* cfd =
|
||||
static_cast<ColumnFamilyHandleImpl*>(db_->DefaultColumnFamily())->cfd();
|
||||
MutableCFOptions mutable_cf_options(column_family_options_);
|
||||
mutable_cf_options.soft_pending_compaction_bytes_limit =
|
||||
std::numeric_limits<uint64_t>::max();
|
||||
|
||||
{
|
||||
// No bottommost data, so debt ratio cannot trigger speedup.
|
||||
VersionStorageInfo* vstorage = cfd->current()->storage_info();
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(1048576 /* 1MB */);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
|
||||
// Add a tiny amount of bottommost data.
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo", "bar"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
|
||||
{
|
||||
// 1MB debt is way bigger than bottommost data so definitely triggers
|
||||
// speedup.
|
||||
VersionStorageInfo* vstorage = cfd->current()->storage_info();
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(1048576 /* 1MB */);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
// Eight bytes is way smaller than bottommost data so definitely does not
|
||||
// trigger speedup.
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(8);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(ColumnFamilyTest, CreateAndDestroyOptions) {
|
||||
std::unique_ptr<ColumnFamilyOptions> cfo(new ColumnFamilyOptions());
|
||||
ColumnFamilyHandle* cfh;
|
||||
|
||||
@@ -288,37 +288,39 @@ void CompactionJob::Prepare() {
|
||||
|
||||
if (preserve_time_duration > 0) {
|
||||
const ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
// Setup seqno_to_time_mapping_ with relevant time range.
|
||||
seqno_to_time_mapping_.SetMaxTimeSpan(preserve_time_duration);
|
||||
// setup seqno_to_time_mapping_
|
||||
seqno_to_time_mapping_.SetMaxTimeDuration(preserve_time_duration);
|
||||
for (const auto& each_level : *c->inputs()) {
|
||||
for (const auto& fmd : each_level.files) {
|
||||
std::shared_ptr<const TableProperties> tp;
|
||||
Status s =
|
||||
cfd->current()->GetTableProperties(read_options, &tp, fmd, nullptr);
|
||||
if (s.ok()) {
|
||||
s = seqno_to_time_mapping_.DecodeFrom(tp->seqno_to_time_mapping);
|
||||
}
|
||||
if (!s.ok()) {
|
||||
ROCKS_LOG_WARN(
|
||||
db_options_.info_log,
|
||||
"Problem reading or processing seqno-to-time mapping: %s",
|
||||
s.ToString().c_str());
|
||||
seqno_to_time_mapping_.Add(tp->seqno_to_time_mapping)
|
||||
.PermitUncheckedError();
|
||||
seqno_to_time_mapping_.Add(fmd->fd.smallest_seqno,
|
||||
fmd->oldest_ancester_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto status = seqno_to_time_mapping_.Sort();
|
||||
if (!status.ok()) {
|
||||
ROCKS_LOG_WARN(db_options_.info_log,
|
||||
"Invalid sequence number to time mapping: Status: %s",
|
||||
status.ToString().c_str());
|
||||
}
|
||||
int64_t _current_time = 0;
|
||||
Status s = db_options_.clock->GetCurrentTime(&_current_time);
|
||||
if (!s.ok()) {
|
||||
status = db_options_.clock->GetCurrentTime(&_current_time);
|
||||
if (!status.ok()) {
|
||||
ROCKS_LOG_WARN(db_options_.info_log,
|
||||
"Failed to get current time in compaction: Status: %s",
|
||||
s.ToString().c_str());
|
||||
status.ToString().c_str());
|
||||
// preserve all time information
|
||||
preserve_time_min_seqno_ = 0;
|
||||
preclude_last_level_min_seqno_ = 0;
|
||||
seqno_to_time_mapping_.Enforce();
|
||||
} else {
|
||||
seqno_to_time_mapping_.Enforce(_current_time);
|
||||
seqno_to_time_mapping_.TruncateOldEntries(_current_time);
|
||||
uint64_t preserve_time =
|
||||
static_cast<uint64_t>(_current_time) > preserve_time_duration
|
||||
? _current_time - preserve_time_duration
|
||||
@@ -342,16 +344,6 @@ void CompactionJob::Prepare() {
|
||||
1;
|
||||
}
|
||||
}
|
||||
// For accuracy of the GetProximalSeqnoBeforeTime queries above, we only
|
||||
// limit the capacity after them.
|
||||
// Here If we set capacity to the per-SST limit, we could be throwing away
|
||||
// fidelity when a compaction output file has a narrower seqno range than
|
||||
// all the inputs. If we only limit capacity for each compaction output, we
|
||||
// could be doing a lot of unnecessary recomputation in a large compaction
|
||||
// (up to quadratic in number of files). Thus, we do soemthing in the
|
||||
// middle: enforce a resonably large constant size limit substantially
|
||||
// larger than kMaxSeqnoTimePairsPerSST.
|
||||
seqno_to_time_mapping_.SetCapacity(kMaxSeqnoToTimeEntries);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,8 +476,7 @@ void CompactionJob::GenSubcompactionBoundaries() {
|
||||
// overlap with N-1 other ranges. Since we requested a relatively large number
|
||||
// (128) of ranges from each input files, even N range overlapping would
|
||||
// cause relatively small inaccuracy.
|
||||
ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
read_options.rate_limiter_priority = GetRateLimiterPriority();
|
||||
const ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
auto* c = compact_->compaction;
|
||||
if (c->max_subcompactions() <= 1 &&
|
||||
!(c->immutable_options()->compaction_pri == kRoundRobin &&
|
||||
@@ -737,9 +728,8 @@ Status CompactionJob::Run() {
|
||||
// use_direct_io_for_flush_and_compaction is true, we will regard this
|
||||
// verification as user reads since the goal is to cache it here for
|
||||
// further user reads
|
||||
ReadOptions verify_table_read_options(Env::IOActivity::kCompaction);
|
||||
verify_table_read_options.rate_limiter_priority =
|
||||
GetRateLimiterPriority();
|
||||
const ReadOptions verify_table_read_options(
|
||||
Env::IOActivity::kCompaction);
|
||||
InternalIterator* iter = cfd->table_cache()->NewIterator(
|
||||
verify_table_read_options, file_options_,
|
||||
cfd->internal_comparator(), files_output[file_idx]->meta,
|
||||
@@ -1140,9 +1130,6 @@ void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
|
||||
// (b) CompactionFilter::Decision::kRemoveAndSkipUntil.
|
||||
read_options.total_order_seek = true;
|
||||
|
||||
const WriteOptions write_options(Env::IOPriority::IO_LOW,
|
||||
Env::IOActivity::kCompaction);
|
||||
|
||||
// Remove the timestamps from boundaries because boundaries created in
|
||||
// GenSubcompactionBoundaries doesn't strip away the timestamp.
|
||||
size_t ts_sz = cfd->user_comparator()->timestamp_size();
|
||||
@@ -1277,8 +1264,8 @@ void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
|
||||
? new BlobFileBuilder(
|
||||
versions_, fs_.get(),
|
||||
sub_compact->compaction->immutable_options(),
|
||||
mutable_cf_options, &file_options_, &write_options, db_id_,
|
||||
db_session_id_, job_id_, cfd->GetID(), cfd->GetName(),
|
||||
mutable_cf_options, &file_options_, db_id_, db_session_id_,
|
||||
job_id_, cfd->GetID(), cfd->GetName(), Env::IOPriority::IO_LOW,
|
||||
write_hint_, io_tracer_, blob_callback_,
|
||||
BlobFileCreationReason::kCompaction, &blob_file_paths,
|
||||
sub_compact->Current().GetBlobFileAdditionsPtr())
|
||||
@@ -1723,8 +1710,6 @@ Status CompactionJob::InstallCompactionResults(
|
||||
db_mutex_->AssertHeld();
|
||||
|
||||
const ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
const WriteOptions write_options(Env::IOActivity::kCompaction);
|
||||
|
||||
auto* compaction = compact_->compaction;
|
||||
assert(compaction);
|
||||
|
||||
@@ -1807,9 +1792,8 @@ Status CompactionJob::InstallCompactionResults(
|
||||
};
|
||||
|
||||
return versions_->LogAndApply(
|
||||
compaction->column_family_data(), mutable_cf_options, read_options,
|
||||
write_options, edit, db_mutex_, db_directory_,
|
||||
/*new_descriptor_log=*/false,
|
||||
compaction->column_family_data(), mutable_cf_options, read_options, edit,
|
||||
db_mutex_, db_directory_, /*new_descriptor_log=*/false,
|
||||
/*column_family_options=*/nullptr, manifest_wcb);
|
||||
}
|
||||
|
||||
@@ -1959,17 +1943,13 @@ Status CompactionJob::OpenCompactionOutputFile(SubcompactionState* sub_compact,
|
||||
sub_compact->compaction->immutable_options()->listeners;
|
||||
outputs.AssignFileWriter(new WritableFileWriter(
|
||||
std::move(writable_file), fname, fo_copy, db_options_.clock, io_tracer_,
|
||||
db_options_.stats, Histograms::SST_WRITE_MICROS, listeners,
|
||||
db_options_.file_checksum_gen_factory.get(),
|
||||
db_options_.stats, listeners, db_options_.file_checksum_gen_factory.get(),
|
||||
tmp_set.Contains(FileType::kTableFile), false));
|
||||
|
||||
// TODO(hx235): pass in the correct `oldest_key_time` instead of `0`
|
||||
const ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
const WriteOptions write_options(Env::IOActivity::kCompaction);
|
||||
TableBuilderOptions tboptions(
|
||||
*cfd->ioptions(), *(sub_compact->compaction->mutable_cf_options()),
|
||||
read_options, write_options, cfd->internal_comparator(),
|
||||
cfd->int_tbl_prop_collector_factories(),
|
||||
cfd->internal_comparator(), cfd->int_tbl_prop_collector_factories(),
|
||||
sub_compact->compaction->output_compression(),
|
||||
sub_compact->compaction->output_compression_opts(), cfd->GetID(),
|
||||
cfd->GetName(), sub_compact->compaction->output_level(),
|
||||
|
||||
@@ -217,7 +217,7 @@ class CompactionJobTestBase : public testing::Test {
|
||||
/*block_cache_tracer=*/nullptr,
|
||||
/*io_tracer=*/nullptr, /*db_id=*/"", /*db_session_id=*/"",
|
||||
/*daily_offpeak_time_utc=*/"",
|
||||
/*error_handler=*/nullptr, /*read_only=*/false)),
|
||||
/*error_handler=*/nullptr)),
|
||||
shutting_down_(false),
|
||||
mock_table_factory_(new mock::MockTableFactory()),
|
||||
error_handler_(nullptr, db_options_, &mutex_),
|
||||
@@ -295,12 +295,9 @@ class CompactionJobTestBase : public testing::Test {
|
||||
Status s = WritableFileWriter::Create(fs_, table_name, FileOptions(),
|
||||
&file_writer, nullptr);
|
||||
ASSERT_OK(s);
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
std::unique_ptr<TableBuilder> table_builder(
|
||||
cf_options_.table_factory->NewTableBuilder(
|
||||
TableBuilderOptions(*cfd_->ioptions(), mutable_cf_options_,
|
||||
read_options, write_options,
|
||||
cfd_->internal_comparator(),
|
||||
cfd_->int_tbl_prop_collector_factories(),
|
||||
CompressionType::kNoCompression,
|
||||
@@ -397,7 +394,7 @@ class CompactionJobTestBase : public testing::Test {
|
||||
mutex_.Lock();
|
||||
EXPECT_OK(versions_->LogAndApply(
|
||||
versions_->GetColumnFamilySet()->GetDefault(), mutable_cf_options_,
|
||||
read_options_, write_options_, &edit, &mutex_, nullptr));
|
||||
read_options_, &edit, &mutex_, nullptr));
|
||||
mutex_.Unlock();
|
||||
}
|
||||
|
||||
@@ -550,9 +547,9 @@ class CompactionJobTestBase : public testing::Test {
|
||||
&write_buffer_manager_, &write_controller_,
|
||||
/*block_cache_tracer=*/nullptr, /*io_tracer=*/nullptr,
|
||||
/*db_id=*/"", /*db_session_id=*/"", /*daily_offpeak_time_utc=*/"",
|
||||
/*error_handler=*/nullptr, /*read_only=*/false));
|
||||
/*error_handler=*/nullptr));
|
||||
compaction_job_stats_.Reset();
|
||||
ASSERT_OK(SetIdentityFile(WriteOptions(), env_, dbname_));
|
||||
ASSERT_OK(SetIdentityFile(env_, dbname_));
|
||||
|
||||
VersionEdit new_db;
|
||||
new_db.SetLogNumber(0);
|
||||
@@ -571,11 +568,11 @@ class CompactionJobTestBase : public testing::Test {
|
||||
log::Writer log(std::move(file_writer), 0, false);
|
||||
std::string record;
|
||||
new_db.EncodeTo(&record);
|
||||
s = log.AddRecord(WriteOptions(), record);
|
||||
s = log.AddRecord(record);
|
||||
}
|
||||
ASSERT_OK(s);
|
||||
// Make "CURRENT" file that points to the new manifest file.
|
||||
s = SetCurrentFile(WriteOptions(), fs_.get(), dbname_, 1, nullptr);
|
||||
s = SetCurrentFile(fs_.get(), dbname_, 1, nullptr);
|
||||
|
||||
ASSERT_OK(s);
|
||||
|
||||
@@ -739,7 +736,6 @@ class CompactionJobTestBase : public testing::Test {
|
||||
MutableCFOptions mutable_cf_options_;
|
||||
MutableDBOptions mutable_db_options_;
|
||||
const ReadOptions read_options_;
|
||||
const WriteOptions write_options_;
|
||||
std::shared_ptr<Cache> table_cache_;
|
||||
WriteController write_controller_;
|
||||
WriteBufferManager write_buffer_manager_;
|
||||
|
||||
@@ -25,11 +25,11 @@ Status CompactionOutputs::Finish(
|
||||
assert(meta != nullptr);
|
||||
Status s = intput_status;
|
||||
if (s.ok()) {
|
||||
SeqnoToTimeMapping relevant_mapping;
|
||||
relevant_mapping.CopyFromSeqnoRange(
|
||||
seqno_to_time_mapping, meta->fd.smallest_seqno, meta->fd.largest_seqno);
|
||||
relevant_mapping.SetCapacity(kMaxSeqnoTimePairsPerSST);
|
||||
builder_->SetSeqnoTimeTableProperties(relevant_mapping,
|
||||
std::string seqno_to_time_mapping_str;
|
||||
seqno_to_time_mapping.Encode(
|
||||
seqno_to_time_mapping_str, meta->fd.smallest_seqno,
|
||||
meta->fd.largest_seqno, meta->file_creation_time);
|
||||
builder_->SetSeqnoTimeTableProperties(seqno_to_time_mapping_str,
|
||||
meta->oldest_ancester_time);
|
||||
s = builder_->Finish();
|
||||
|
||||
@@ -62,15 +62,12 @@ IOStatus CompactionOutputs::WriterSyncClose(const Status& input_status,
|
||||
Statistics* statistics,
|
||||
bool use_fsync) {
|
||||
IOStatus io_s;
|
||||
IOOptions opts;
|
||||
io_s = WritableFileWriter::PrepareIOOptions(
|
||||
WriteOptions(Env::IOActivity::kCompaction), opts);
|
||||
if (input_status.ok() && io_s.ok()) {
|
||||
if (input_status.ok()) {
|
||||
StopWatch sw(clock, statistics, COMPACTION_OUTFILE_SYNC_MICROS);
|
||||
io_s = file_writer_->Sync(opts, use_fsync);
|
||||
io_s = file_writer_->Sync(use_fsync);
|
||||
}
|
||||
if (input_status.ok() && io_s.ok()) {
|
||||
io_s = file_writer_->Close(opts);
|
||||
io_s = file_writer_->Close();
|
||||
}
|
||||
|
||||
if (input_status.ok() && io_s.ok()) {
|
||||
|
||||
@@ -45,13 +45,6 @@ bool LevelCompactionPicker::NeedsCompaction(
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
enum class CompactToNextLevel {
|
||||
kNo, // compact to the same level as the input file
|
||||
kYes, // compact to the next level except the last level to the same level
|
||||
kSkipLastLevel, // compact to the next level but skip the last level
|
||||
};
|
||||
|
||||
// A class to build a leveled compaction step-by-step.
|
||||
class LevelCompactionBuilder {
|
||||
public:
|
||||
@@ -122,10 +115,9 @@ class LevelCompactionBuilder {
|
||||
// level_files is a vector of (level, file metadata) in ascending order of
|
||||
// level. If compact_to_next_level is true, compact the file to the next
|
||||
// level, otherwise, compact to the same level as the input file.
|
||||
// If skip_last_level is true, skip the last level.
|
||||
void PickFileToCompact(
|
||||
const autovector<std::pair<int, FileMetaData*>>& level_files,
|
||||
CompactToNextLevel compact_to_next_level);
|
||||
bool compact_to_next_level);
|
||||
|
||||
const std::string& cf_name_;
|
||||
VersionStorageInfo* vstorage_;
|
||||
@@ -157,24 +149,20 @@ class LevelCompactionBuilder {
|
||||
|
||||
void LevelCompactionBuilder::PickFileToCompact(
|
||||
const autovector<std::pair<int, FileMetaData*>>& level_files,
|
||||
CompactToNextLevel compact_to_next_level) {
|
||||
bool compact_to_next_level) {
|
||||
for (auto& level_file : level_files) {
|
||||
// If it's being compacted it has nothing to do here.
|
||||
// If this assert() fails that means that some function marked some
|
||||
// files as being_compacted, but didn't call ComputeCompactionScore()
|
||||
assert(!level_file.second->being_compacted);
|
||||
start_level_ = level_file.first;
|
||||
if ((compact_to_next_level == CompactToNextLevel::kSkipLastLevel &&
|
||||
if ((compact_to_next_level &&
|
||||
start_level_ == vstorage_->num_non_empty_levels() - 1) ||
|
||||
(start_level_ == 0 &&
|
||||
!compaction_picker_->level0_compactions_in_progress()->empty())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compact to the next level only if the file is not in the last level and
|
||||
// compact_to_next_level is kYes or kSkipLastLevel.
|
||||
if (compact_to_next_level != CompactToNextLevel::kNo &&
|
||||
(start_level_ < vstorage_->num_non_empty_levels() - 1)) {
|
||||
if (compact_to_next_level) {
|
||||
output_level_ =
|
||||
(start_level_ == 0) ? vstorage_->base_level() : start_level_ + 1;
|
||||
} else {
|
||||
@@ -260,8 +248,7 @@ void LevelCompactionBuilder::SetupInitialFiles() {
|
||||
}
|
||||
|
||||
// Bottommost Files Compaction on deleting tombstones
|
||||
PickFileToCompact(vstorage_->BottommostFilesMarkedForCompaction(),
|
||||
CompactToNextLevel::kNo);
|
||||
PickFileToCompact(vstorage_->BottommostFilesMarkedForCompaction(), false);
|
||||
if (!start_level_inputs_.empty()) {
|
||||
compaction_reason_ = CompactionReason::kBottommostFiles;
|
||||
return;
|
||||
@@ -287,26 +274,21 @@ void LevelCompactionBuilder::SetupInitialFiles() {
|
||||
}
|
||||
}
|
||||
|
||||
PickFileToCompact(vstorage_->ExpiredTtlFiles(),
|
||||
CompactToNextLevel::kSkipLastLevel);
|
||||
PickFileToCompact(vstorage_->ExpiredTtlFiles(), true);
|
||||
if (!start_level_inputs_.empty()) {
|
||||
compaction_reason_ = CompactionReason::kTtl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Periodic Compaction
|
||||
PickFileToCompact(vstorage_->FilesMarkedForPeriodicCompaction(),
|
||||
ioptions_.level_compaction_dynamic_level_bytes
|
||||
? CompactToNextLevel::kYes
|
||||
: CompactToNextLevel::kNo);
|
||||
PickFileToCompact(vstorage_->FilesMarkedForPeriodicCompaction(), false);
|
||||
if (!start_level_inputs_.empty()) {
|
||||
compaction_reason_ = CompactionReason::kPeriodicCompaction;
|
||||
return;
|
||||
}
|
||||
|
||||
// Forced blob garbage collection
|
||||
PickFileToCompact(vstorage_->FilesMarkedForForcedBlobGC(),
|
||||
CompactToNextLevel::kNo);
|
||||
PickFileToCompact(vstorage_->FilesMarkedForForcedBlobGC(), false);
|
||||
if (!start_level_inputs_.empty()) {
|
||||
compaction_reason_ = CompactionReason::kForcedBlobGC;
|
||||
return;
|
||||
|
||||
@@ -4149,122 +4149,6 @@ TEST_P(PerKeyPlacementCompactionPickerTest,
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CompactionPickerTest,
|
||||
LevelCompactionPrioritizeFilesMarkedForCompaction1) {
|
||||
int num_levels = ioptions_.num_levels;
|
||||
ioptions_.level_compaction_dynamic_level_bytes = true;
|
||||
ioptions_.compaction_pri = kMinOverlappingRatio;
|
||||
mutable_cf_options_.max_bytes_for_level_base = 200;
|
||||
mutable_cf_options_.max_bytes_for_level_multiplier = 10;
|
||||
NewVersionStorage(num_levels, kCompactionStyleLevel);
|
||||
// L5
|
||||
// F4 [100, 200] size:100, F5 [300, 400] size:100, F6 [500, 600] size:200
|
||||
// F5 is marked for compaction
|
||||
// L6
|
||||
// F1 [100, 200] size:100, F2 [300, 400] size:1000, F3 [500, 600] size:100
|
||||
//
|
||||
// First compaction should pick F5 since it's marked for compaction.
|
||||
// Second compaction should pick F6 since it has min overlap ratio.
|
||||
Add(/*level=*/num_levels - 1, /*file_number=*/1U, /*smallest=*/"100",
|
||||
/*largest=*/"200",
|
||||
/*file_size=*/100, /*path_id=*/0, /*smallest_seq=*/0,
|
||||
/*largest_seq=*/0, /*compensated_file_size=*/100,
|
||||
/*marked_for_compact=*/false);
|
||||
Add(/*level=*/num_levels - 1, /*file_number=*/2U, /*smallest=*/"300",
|
||||
/*largest=*/"400",
|
||||
/*file_size=*/1000, /*path_id=*/0, /*smallest_seq=*/0,
|
||||
/*largest_seq=*/0, /*compensated_file_size=*/1000,
|
||||
/*marked_for_compact=*/false);
|
||||
Add(/*level=*/num_levels - 1, /*file_number=*/3U, /*smallest=*/"500",
|
||||
/*largest=*/"600",
|
||||
/*file_size=*/100, /*path_id=*/0, /*smallest_seq=*/0,
|
||||
/*largest_seq=*/0, /*compensated_file_size=*/100,
|
||||
/*marked_for_compact=*/false);
|
||||
|
||||
Add(/*level=*/num_levels - 2, /*file_number=*/4U, /*smallest=*/"100",
|
||||
/*largest=*/"200",
|
||||
/*file_size=*/100, /*path_id=*/0, /*smallest_seq=*/100,
|
||||
/*largest_seq=*/200, /*compensated_file_size=*/100,
|
||||
/*marked_for_compact=*/false);
|
||||
// Marked for compaction, but with a larger overlap ratio.
|
||||
Add(/*level=*/num_levels - 2, /*file_number=*/5U, /*smallest=*/"300",
|
||||
/*largest=*/"400",
|
||||
/*file_size=*/100, /*path_id=*/0, /*smallest_seq=*/300,
|
||||
/*largest_seq=*/400, /*compensated_file_size=*/100,
|
||||
/*marked_for_compact=*/true);
|
||||
Add(/*level=*/num_levels - 2, /*file_number=*/6U, /*smallest=*/"500",
|
||||
/*largest=*/"600",
|
||||
/*file_size=*/200, /*path_id=*/0, /*smallest_seq=*/400,
|
||||
/*largest_seq=*/500, /*compensated_file_size=*/200,
|
||||
/*marked_for_compact=*/false);
|
||||
UpdateVersionStorageInfo();
|
||||
|
||||
std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
|
||||
cf_name_, mutable_cf_options_, mutable_db_options_, vstorage_.get(),
|
||||
&log_buffer_));
|
||||
ASSERT_TRUE(compaction);
|
||||
ASSERT_EQ(num_levels - 2, compaction->start_level());
|
||||
ASSERT_EQ(num_levels - 1, compaction->output_level());
|
||||
ASSERT_EQ(1U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(5U, compaction->input(0, 0)->fd.GetNumber());
|
||||
|
||||
std::unique_ptr<Compaction> second_compaction(
|
||||
level_compaction_picker.PickCompaction(cf_name_, mutable_cf_options_,
|
||||
mutable_db_options_,
|
||||
vstorage_.get(), &log_buffer_));
|
||||
ASSERT_TRUE(second_compaction);
|
||||
ASSERT_EQ(num_levels - 1, compaction->output_level());
|
||||
ASSERT_EQ(num_levels - 2, compaction->start_level());
|
||||
ASSERT_EQ(1U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(6U, second_compaction->input(0, 0)->fd.GetNumber());
|
||||
}
|
||||
|
||||
TEST_F(CompactionPickerTest,
|
||||
LevelCompactionPrioritizeFilesMarkedForCompaction2) {
|
||||
int num_levels = ioptions_.num_levels;
|
||||
ioptions_.level_compaction_dynamic_level_bytes = true;
|
||||
ioptions_.compaction_pri = kMinOverlappingRatio;
|
||||
mutable_cf_options_.max_bytes_for_level_base = 200;
|
||||
mutable_cf_options_.max_bytes_for_level_multiplier = 10;
|
||||
// L4
|
||||
// F3 [100, 200] size:2000
|
||||
// L5
|
||||
// F2 [100, 200] size:2000, marked for compaction
|
||||
// L6
|
||||
// F1 [100, 200] size: 20000
|
||||
//
|
||||
// L4 should be prioritized over L5 since L4 has a higher compaction score.
|
||||
// Files marked for compaction do not affect level picking order.
|
||||
NewVersionStorage(num_levels, kCompactionStyleLevel);
|
||||
Add(/*level=*/num_levels - 1, /*file_number=*/1U, /*smallest=*/"100",
|
||||
/*largest=*/"200",
|
||||
/*file_size=*/20000, /*path_id=*/0, /*smallest_seq=*/0,
|
||||
/*largest_seq=*/0, /*compensated_file_size=*/100,
|
||||
/*marked_for_compact=*/false);
|
||||
// Level score should be 1.
|
||||
Add(/*level=*/num_levels - 2, /*file_number=*/2U, /*smallest=*/"100",
|
||||
/*largest=*/"200",
|
||||
/*file_size=*/2000, /*path_id=*/0, /*smallest_seq=*/100,
|
||||
/*largest_seq=*/200, /*compensated_file_size=*/2000,
|
||||
/*marked_for_compact=*/true);
|
||||
// Level score should be larger than L5.
|
||||
Add(/*level=*/num_levels - 3, /*file_number=*/3U, /*smallest=*/"100",
|
||||
/*largest=*/"200",
|
||||
/*file_size=*/2000, /*path_id=*/0, /*smallest_seq=*/300,
|
||||
/*largest_seq=*/400, /*compensated_file_size=*/2000,
|
||||
/*marked_for_compact=*/false);
|
||||
UpdateVersionStorageInfo();
|
||||
|
||||
std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
|
||||
cf_name_, mutable_cf_options_, mutable_db_options_, vstorage_.get(),
|
||||
&log_buffer_));
|
||||
ASSERT_TRUE(compaction);
|
||||
ASSERT_EQ(num_levels - 3, compaction->start_level());
|
||||
ASSERT_EQ(num_levels - 2, compaction->output_level());
|
||||
ASSERT_EQ(1U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(3U, compaction->input(0, 0)->fd.GetNumber());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PerKeyPlacementCompactionPickerTest,
|
||||
PerKeyPlacementCompactionPickerTest, ::testing::Bool());
|
||||
|
||||
|
||||
@@ -1575,8 +1575,9 @@ TEST_F(PrecludeLastLevelTest, SmallPrecludeTime) {
|
||||
ASSERT_EQ(tables_props.size(), 1);
|
||||
ASSERT_FALSE(tables_props.begin()->second->seqno_to_time_mapping.empty());
|
||||
SeqnoToTimeMapping tp_mapping;
|
||||
ASSERT_OK(tp_mapping.DecodeFrom(
|
||||
tables_props.begin()->second->seqno_to_time_mapping));
|
||||
ASSERT_OK(
|
||||
tp_mapping.Add(tables_props.begin()->second->seqno_to_time_mapping));
|
||||
ASSERT_OK(tp_mapping.Sort());
|
||||
ASSERT_FALSE(tp_mapping.Empty());
|
||||
auto seqs = tp_mapping.TEST_GetInternalMapping();
|
||||
ASSERT_FALSE(seqs.empty());
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ Status DeleteFilesInRanges(DB* db, ColumnFamilyHandle* column_family,
|
||||
Status VerifySstFileChecksum(const Options& options,
|
||||
const EnvOptions& env_options,
|
||||
const std::string& file_path) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
return VerifySstFileChecksum(options, env_options, read_options, file_path);
|
||||
}
|
||||
|
||||
+1
-52
@@ -1853,56 +1853,6 @@ TEST_P(DBMultiGetTestWithParam, MultiGetBatchedMultiLevel) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(DBMultiGetTestWithParam, MultiGetBatchedEmptyLevel) {
|
||||
#ifndef USE_COROUTINES
|
||||
if (std::get<1>(GetParam())) {
|
||||
ROCKSDB_GTEST_BYPASS("This test requires coroutine support");
|
||||
return;
|
||||
}
|
||||
#endif // USE_COROUTINES
|
||||
// Skip for unbatched MultiGet
|
||||
if (!std::get<0>(GetParam())) {
|
||||
ROCKSDB_GTEST_BYPASS("This test is only for batched MultiGet");
|
||||
return;
|
||||
}
|
||||
Options options = CurrentOptions();
|
||||
options.disable_auto_compactions = true;
|
||||
options.merge_operator = MergeOperators::CreateStringAppendOperator();
|
||||
Reopen(options);
|
||||
int key;
|
||||
|
||||
key = 9;
|
||||
ASSERT_OK(Put("key_" + std::to_string(key), "val_l2_" + std::to_string(key)));
|
||||
ASSERT_OK(Flush());
|
||||
MoveFilesToLevel(4);
|
||||
|
||||
key = 5;
|
||||
ASSERT_OK(Put("key_" + std::to_string(key), "val_l2_" + std::to_string(key)));
|
||||
key = 9;
|
||||
ASSERT_OK(
|
||||
Merge("key_" + std::to_string(key), "val_l2_" + std::to_string(key)));
|
||||
ASSERT_OK(Flush());
|
||||
// Leave level 3 empty
|
||||
MoveFilesToLevel(2);
|
||||
|
||||
key = 2;
|
||||
ASSERT_OK(Put("key_" + std::to_string(key), "val_l2_" + std::to_string(key)));
|
||||
key = 6;
|
||||
ASSERT_OK(
|
||||
Merge("key_" + std::to_string(key), "val_l2_" + std::to_string(key)));
|
||||
ASSERT_OK(Flush());
|
||||
MoveFilesToLevel(1);
|
||||
|
||||
std::vector<std::string> keys;
|
||||
std::vector<std::string> values;
|
||||
|
||||
keys.push_back("key_" + std::to_string(9));
|
||||
keys.push_back("key_" + std::to_string(9));
|
||||
|
||||
values = MultiGet(keys, nullptr, std::get<1>(GetParam()));
|
||||
ASSERT_EQ(values.size(), 2);
|
||||
}
|
||||
|
||||
TEST_P(DBMultiGetTestWithParam, MultiGetBatchedMultiLevelMerge) {
|
||||
#ifndef USE_COROUTINES
|
||||
if (std::get<1>(GetParam())) {
|
||||
@@ -3176,8 +3126,7 @@ TEST_F(DBBasicTest, LastSstFileNotInManifest) {
|
||||
// Manually add a sst file.
|
||||
constexpr uint64_t kSstFileNumber = 100;
|
||||
const std::string kSstFile = MakeTableFileName(dbname_, kSstFileNumber);
|
||||
ASSERT_OK(WriteStringToFile(env_,
|
||||
/* data = */ "bad sst file content",
|
||||
ASSERT_OK(WriteStringToFile(env_, /* data = */ "bad sst file content",
|
||||
/* fname = */ kSstFile,
|
||||
/* should_sync = */ true));
|
||||
ASSERT_OK(env_->FileExists(kSstFile));
|
||||
|
||||
+20
-34
@@ -76,7 +76,7 @@ class CompactionStatsCollector : public EventListener {
|
||||
class DBCompactionTest : public DBTestBase {
|
||||
public:
|
||||
DBCompactionTest()
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/false) {}
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/true) {}
|
||||
|
||||
protected:
|
||||
/*
|
||||
@@ -121,7 +121,7 @@ class DBCompactionTestWithParam
|
||||
public testing::WithParamInterface<std::tuple<uint32_t, bool>> {
|
||||
public:
|
||||
DBCompactionTestWithParam()
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/false) {
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/true) {
|
||||
max_subcompactions_ = std::get<0>(GetParam());
|
||||
exclusive_manual_compaction_ = std::get<1>(GetParam());
|
||||
}
|
||||
@@ -140,7 +140,7 @@ class DBCompactionTestWithBottommostParam
|
||||
std::tuple<BottommostLevelCompaction, bool>> {
|
||||
public:
|
||||
DBCompactionTestWithBottommostParam()
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/false) {
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/true) {
|
||||
bottommost_level_compaction_ = std::get<0>(GetParam());
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ class DBCompactionWaitForCompactTest
|
||||
std::tuple<bool, bool, bool, std::chrono::microseconds>> {
|
||||
public:
|
||||
DBCompactionWaitForCompactTest()
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/false) {
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/true) {
|
||||
abort_on_pause_ = std::get<0>(GetParam());
|
||||
flush_ = std::get<1>(GetParam());
|
||||
close_db_ = std::get<2>(GetParam());
|
||||
@@ -845,20 +845,6 @@ TEST_F(DBCompactionTest, BGCompactionsAllowed) {
|
||||
options.memtable_factory.reset(
|
||||
test::NewSpecialSkipListFactory(kNumKeysPerFile));
|
||||
|
||||
CreateAndReopenWithCF({"one", "two", "three"}, options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int cf = 0; cf < 4; cf++) {
|
||||
// Make a trivial L1 for L0 to compact into. L2 will be large so debt ratio
|
||||
// will not cause compaction pressure.
|
||||
ASSERT_OK(Put(cf, Key(0), rnd.RandomString(102400)));
|
||||
ASSERT_OK(Flush(cf));
|
||||
MoveFilesToLevel(2, cf);
|
||||
ASSERT_OK(Put(cf, Key(0), ""));
|
||||
ASSERT_OK(Flush(cf));
|
||||
MoveFilesToLevel(1, cf);
|
||||
}
|
||||
|
||||
// Block all threads in thread pool.
|
||||
const size_t kTotalTasks = 4;
|
||||
env_->SetBackgroundThreads(4, Env::LOW);
|
||||
@@ -869,6 +855,9 @@ TEST_F(DBCompactionTest, BGCompactionsAllowed) {
|
||||
sleeping_tasks[i].WaitUntilSleeping();
|
||||
}
|
||||
|
||||
CreateAndReopenWithCF({"one", "two", "three"}, options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int cf = 0; cf < 4; cf++) {
|
||||
for (int num = 0; num < options.level0_file_num_compaction_trigger; num++) {
|
||||
for (int i = 0; i < kNumKeysPerFile; i++) {
|
||||
@@ -6161,7 +6150,7 @@ class CompactionPriTest : public DBTestBase,
|
||||
public testing::WithParamInterface<uint32_t> {
|
||||
public:
|
||||
CompactionPriTest()
|
||||
: DBTestBase("compaction_pri_test", /*env_do_fsync=*/false) {
|
||||
: DBTestBase("compaction_pri_test", /*env_do_fsync=*/true) {
|
||||
compaction_pri_ = GetParam();
|
||||
}
|
||||
|
||||
@@ -6281,30 +6270,26 @@ TEST_F(DBCompactionTest, PersistRoundRobinCompactCursor) {
|
||||
|
||||
TEST_P(RoundRobinSubcompactionsAgainstPressureToken, PressureTokenTest) {
|
||||
const int kKeysPerBuffer = 100;
|
||||
const int kNumSubcompactions = 2;
|
||||
const int kFilesPerLevel = 50;
|
||||
Options options = CurrentOptions();
|
||||
options.num_levels = 3;
|
||||
options.num_levels = 4;
|
||||
options.max_bytes_for_level_multiplier = 2;
|
||||
options.level0_file_num_compaction_trigger = 4;
|
||||
options.target_file_size_base = kKeysPerBuffer * 1024;
|
||||
options.compaction_pri = CompactionPri::kRoundRobin;
|
||||
// Target size is chosen so that filling the level with `kFilesPerLevel` files
|
||||
// will make it oversized by `kNumSubcompactions` files.
|
||||
options.max_bytes_for_level_base =
|
||||
(kFilesPerLevel - kNumSubcompactions) * kKeysPerBuffer * 1024;
|
||||
options.max_bytes_for_level_base = 8 * kKeysPerBuffer * 1024;
|
||||
options.disable_auto_compactions = true;
|
||||
// Setup `kNumSubcompactions` threads but limited subcompactions so
|
||||
// that RoundRobin requires extra compactions from reserved threads
|
||||
// Setup 7 threads but limited subcompactions so that
|
||||
// RoundRobin requires extra compactions from reserved threads
|
||||
options.max_subcompactions = 1;
|
||||
options.max_background_compactions = kNumSubcompactions;
|
||||
options.max_background_compactions = 7;
|
||||
options.max_compaction_bytes = 100000000;
|
||||
DestroyAndReopen(options);
|
||||
env_->SetBackgroundThreads(kNumSubcompactions, Env::LOW);
|
||||
env_->SetBackgroundThreads(7, Env::LOW);
|
||||
|
||||
Random rnd(301);
|
||||
const std::vector<int> files_per_level = {0, 15, 25};
|
||||
for (int lvl = 2; lvl > 0; lvl--) {
|
||||
for (int i = 0; i < kFilesPerLevel; i++) {
|
||||
for (int i = 0; i < files_per_level[lvl]; i++) {
|
||||
for (int j = 0; j < kKeysPerBuffer; j++) {
|
||||
// Add (lvl-1) to ensure nearly equivallent number of files
|
||||
// in L2 are overlapped with fils selected to compact from
|
||||
@@ -6315,8 +6300,9 @@ TEST_P(RoundRobinSubcompactionsAgainstPressureToken, PressureTokenTest) {
|
||||
ASSERT_OK(Flush());
|
||||
}
|
||||
MoveFilesToLevel(lvl);
|
||||
ASSERT_EQ(kFilesPerLevel, NumTableFilesAtLevel(lvl, 0));
|
||||
ASSERT_EQ(files_per_level[lvl], NumTableFilesAtLevel(lvl, 0));
|
||||
}
|
||||
// 15 files in L1; 25 files in L2
|
||||
|
||||
// This is a variable for making sure the following callback is called
|
||||
// and the assertions in it are indeed excuted.
|
||||
@@ -6325,10 +6311,10 @@ TEST_P(RoundRobinSubcompactionsAgainstPressureToken, PressureTokenTest) {
|
||||
"CompactionJob::GenSubcompactionBoundaries:0", [&](void* arg) {
|
||||
uint64_t num_planned_subcompactions = *(static_cast<uint64_t*>(arg));
|
||||
if (grab_pressure_token_) {
|
||||
// `kNumSubcompactions` files are selected for round-robin under auto
|
||||
// 7 files are selected for round-robin under auto
|
||||
// compaction. The number of planned subcompaction is restricted by
|
||||
// the limited number of max_background_compactions
|
||||
ASSERT_EQ(num_planned_subcompactions, kNumSubcompactions);
|
||||
ASSERT_EQ(num_planned_subcompactions, 7);
|
||||
} else {
|
||||
ASSERT_EQ(num_planned_subcompactions, 1);
|
||||
}
|
||||
|
||||
@@ -3035,39 +3035,6 @@ TEST_P(DBAtomicFlushTest, RollbackAfterFailToInstallResults) {
|
||||
SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
}
|
||||
|
||||
TEST_P(DBAtomicFlushTest, FailureInMultiCfAutomaticFlush) {
|
||||
bool atomic_flush = GetParam();
|
||||
auto fault_injection_env = std::make_shared<FaultInjectionTestEnv>(env_);
|
||||
Options options = CurrentOptions();
|
||||
options.env = fault_injection_env.get();
|
||||
options.create_if_missing = true;
|
||||
options.atomic_flush = atomic_flush;
|
||||
const int kNumKeysTriggerFlush = 4;
|
||||
options.memtable_factory.reset(
|
||||
test::NewSpecialSkipListFactory(kNumKeysTriggerFlush));
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
ASSERT_EQ(2, handles_.size());
|
||||
for (size_t cf = 0; cf < handles_.size(); ++cf) {
|
||||
ASSERT_OK(Put(static_cast<int>(cf), "a", "value"));
|
||||
}
|
||||
SyncPoint::GetInstance()->DisableProcessing();
|
||||
SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::ScheduleFlushes:PreSwitchMemtable",
|
||||
[&](void* /*arg*/) { fault_injection_env->SetFilesystemActive(false); });
|
||||
SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
for (int i = 1; i < kNumKeysTriggerFlush; ++i) {
|
||||
ASSERT_OK(Put(0, "key" + std::to_string(i), "value" + std::to_string(i)));
|
||||
}
|
||||
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||
// Next write after failed flush should fail.
|
||||
ASSERT_NOK(Put(0, "x", "y"));
|
||||
fault_injection_env->SetFilesystemActive(true);
|
||||
Close();
|
||||
SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
}
|
||||
|
||||
// In atomic flush, concurrent bg flush threads commit to the MANIFEST in
|
||||
// serial, in the order of their picked memtables for each column family.
|
||||
// Only when a bg flush thread finds out that its memtables are the earliest
|
||||
|
||||
+100
-168
@@ -280,7 +280,7 @@ DBImpl::DBImpl(const DBOptions& options, const std::string& dbname,
|
||||
dbname_, &immutable_db_options_, file_options_, table_cache_.get(),
|
||||
write_buffer_manager_, &write_controller_, &block_cache_tracer_,
|
||||
io_tracer_, db_id_, db_session_id_, options.daily_offpeak_time_utc,
|
||||
&error_handler_, read_only));
|
||||
&error_handler_));
|
||||
column_family_memtables_.reset(
|
||||
new ColumnFamilyMemTablesImpl(versions_->GetColumnFamilySet()));
|
||||
|
||||
@@ -333,10 +333,8 @@ Status DBImpl::Resume() {
|
||||
Status DBImpl::ResumeImpl(DBRecoverContext context) {
|
||||
mutex_.AssertHeld();
|
||||
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
WaitForBackgroundWork();
|
||||
|
||||
Status s;
|
||||
@@ -375,8 +373,8 @@ Status DBImpl::ResumeImpl(DBRecoverContext context) {
|
||||
assert(cfh);
|
||||
ColumnFamilyData* cfd = cfh->cfd();
|
||||
const MutableCFOptions& cf_opts = *cfd->GetLatestMutableCFOptions();
|
||||
s = versions_->LogAndApply(cfd, cf_opts, read_options, write_options,
|
||||
&edit, &mutex_, directories_.GetDbDir());
|
||||
s = versions_->LogAndApply(cfd, cf_opts, read_options, &edit, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
if (!s.ok()) {
|
||||
io_s = versions_->io_status();
|
||||
if (!io_s.ok()) {
|
||||
@@ -659,18 +657,6 @@ Status DBImpl::CloseHelper() {
|
||||
|
||||
// versions need to be destroyed before table_cache since it can hold
|
||||
// references to table_cache.
|
||||
{
|
||||
Status s = versions_->Close(directories_.GetDbDir(), &mutex_);
|
||||
if (!s.ok()) {
|
||||
ROCKS_LOG_ERROR(immutable_db_options_.info_log,
|
||||
"Unable to close MANIFEST with error -- %s",
|
||||
s.ToString().c_str());
|
||||
if (ret.ok()) {
|
||||
ret = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
versions_.reset();
|
||||
mutex_.Unlock();
|
||||
if (db_lock_ != nullptr) {
|
||||
@@ -718,26 +704,23 @@ Status DBImpl::CloseHelper() {
|
||||
Status DBImpl::CloseImpl() { return CloseHelper(); }
|
||||
|
||||
DBImpl::~DBImpl() {
|
||||
ThreadStatus::OperationType cur_op_type =
|
||||
ThreadStatusUtil::GetThreadOperation();
|
||||
ThreadStatusUtil::SetThreadOperation(ThreadStatus::OperationType::OP_UNKNOWN);
|
||||
|
||||
// TODO: remove this.
|
||||
init_logger_creation_s_.PermitUncheckedError();
|
||||
|
||||
InstrumentedMutexLock closing_lock_guard(&closing_mutex_);
|
||||
if (!closed_) {
|
||||
closed_ = true;
|
||||
|
||||
{
|
||||
const Status s = MaybeReleaseTimestampedSnapshotsAndCheck();
|
||||
s.PermitUncheckedError();
|
||||
}
|
||||
|
||||
closing_status_ = CloseImpl();
|
||||
closing_status_.PermitUncheckedError();
|
||||
if (closed_) {
|
||||
return;
|
||||
}
|
||||
ThreadStatusUtil::SetThreadOperation(cur_op_type);
|
||||
|
||||
closed_ = true;
|
||||
|
||||
{
|
||||
const Status s = MaybeReleaseTimestampedSnapshotsAndCheck();
|
||||
s.PermitUncheckedError();
|
||||
}
|
||||
|
||||
closing_status_ = CloseImpl();
|
||||
closing_status_.PermitUncheckedError();
|
||||
}
|
||||
|
||||
void DBImpl::MaybeIgnoreError(Status* s) const {
|
||||
@@ -812,9 +795,7 @@ Status DBImpl::StartPeriodicTaskScheduler() {
|
||||
return s;
|
||||
}
|
||||
|
||||
Status DBImpl::RegisterRecordSeqnoTimeWorker(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
bool is_new_db) {
|
||||
Status DBImpl::RegisterRecordSeqnoTimeWorker(bool is_new_db) {
|
||||
options_mutex_.AssertHeld();
|
||||
|
||||
uint64_t min_preserve_seconds = std::numeric_limits<uint64_t>::max();
|
||||
@@ -834,15 +815,9 @@ Status DBImpl::RegisterRecordSeqnoTimeWorker(const ReadOptions& read_options,
|
||||
}
|
||||
}
|
||||
if (min_preserve_seconds == std::numeric_limits<uint64_t>::max()) {
|
||||
// Don't track
|
||||
seqno_to_time_mapping_.SetCapacity(0);
|
||||
seqno_to_time_mapping_.SetMaxTimeSpan(UINT64_MAX);
|
||||
seqno_to_time_mapping_.Resize(0, 0);
|
||||
} else {
|
||||
uint64_t cap = std::min(kMaxSeqnoToTimeEntries,
|
||||
max_preserve_seconds * kMaxSeqnoTimePairsPerCF /
|
||||
min_preserve_seconds);
|
||||
seqno_to_time_mapping_.SetCapacity(cap);
|
||||
seqno_to_time_mapping_.SetMaxTimeSpan(max_preserve_seconds);
|
||||
seqno_to_time_mapping_.Resize(min_preserve_seconds, max_preserve_seconds);
|
||||
}
|
||||
mapping_was_empty = seqno_to_time_mapping_.Empty();
|
||||
}
|
||||
@@ -851,8 +826,9 @@ Status DBImpl::RegisterRecordSeqnoTimeWorker(const ReadOptions& read_options,
|
||||
if (min_preserve_seconds != std::numeric_limits<uint64_t>::max()) {
|
||||
// round up to 1 when the time_duration is smaller than
|
||||
// kMaxSeqnoTimePairsPerCF
|
||||
seqno_time_cadence = (min_preserve_seconds + kMaxSeqnoTimePairsPerCF - 1) /
|
||||
kMaxSeqnoTimePairsPerCF;
|
||||
seqno_time_cadence = (min_preserve_seconds +
|
||||
SeqnoToTimeMapping::kMaxSeqnoTimePairsPerCF - 1) /
|
||||
SeqnoToTimeMapping::kMaxSeqnoTimePairsPerCF;
|
||||
}
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
@@ -889,7 +865,7 @@ Status DBImpl::RegisterRecordSeqnoTimeWorker(const ReadOptions& read_options,
|
||||
assert(mapping_was_empty);
|
||||
|
||||
// We can simply modify these, before writes are allowed
|
||||
constexpr uint64_t kMax = kMaxSeqnoTimePairsPerSST;
|
||||
constexpr uint64_t kMax = SeqnoToTimeMapping::kMaxSeqnoTimePairsPerSST;
|
||||
versions_->SetLastAllocatedSequence(kMax);
|
||||
versions_->SetLastPublishedSequence(kMax);
|
||||
versions_->SetLastSequence(kMax);
|
||||
@@ -902,8 +878,7 @@ Status DBImpl::RegisterRecordSeqnoTimeWorker(const ReadOptions& read_options,
|
||||
VersionEdit edit;
|
||||
edit.SetLastSequence(kMax);
|
||||
s = versions_->LogAndApplyToDefaultColumnFamily(
|
||||
read_options, write_options, &edit, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
{}, &edit, &mutex_, directories_.GetDbDir());
|
||||
if (!s.ok() && versions_->io_status().IsIOError()) {
|
||||
s = error_handler_.SetBGError(versions_->io_status(),
|
||||
BackgroundErrorReason::kManifestWrite);
|
||||
@@ -1013,7 +988,6 @@ void DBImpl::PersistStats() {
|
||||
stats_slice_initialized_ = true;
|
||||
std::swap(stats_slice_, stats_map);
|
||||
if (s.ok()) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
WriteOptions wo;
|
||||
wo.low_pri = true;
|
||||
wo.no_slowdown = true;
|
||||
@@ -1228,10 +1202,8 @@ FSDirectory* DBImpl::GetDataDir(ColumnFamilyData* cfd, size_t path_id) const {
|
||||
Status DBImpl::SetOptions(
|
||||
ColumnFamilyHandle* column_family,
|
||||
const std::unordered_map<std::string, std::string>& options_map) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
auto* cfd =
|
||||
static_cast_with_check<ColumnFamilyHandleImpl>(column_family)->cfd();
|
||||
if (options_map.empty()) {
|
||||
@@ -1254,15 +1226,14 @@ Status DBImpl::SetOptions(
|
||||
new_options = *cfd->GetLatestMutableCFOptions();
|
||||
// Append new version to recompute compaction score.
|
||||
VersionEdit dummy_edit;
|
||||
s = versions_->LogAndApply(cfd, new_options, read_options, write_options,
|
||||
&dummy_edit, &mutex_, directories_.GetDbDir());
|
||||
s = versions_->LogAndApply(cfd, new_options, read_options, &dummy_edit,
|
||||
&mutex_, directories_.GetDbDir());
|
||||
// Trigger possible flush/compactions. This has to be before we persist
|
||||
// options to file, otherwise there will be a deadlock with writer
|
||||
// thread.
|
||||
InstallSuperVersionAndScheduleWork(cfd, &sv_context, new_options);
|
||||
|
||||
persist_options_status =
|
||||
WriteOptionsFile(write_options, true /*db_mutex_already_held*/);
|
||||
persist_options_status = WriteOptionsFile(true /*db_mutex_already_held*/);
|
||||
bg_cv_.SignalAll();
|
||||
}
|
||||
}
|
||||
@@ -1441,8 +1412,7 @@ Status DBImpl::SetDBOptions(
|
||||
}
|
||||
write_thread_.ExitUnbatched(&w);
|
||||
}
|
||||
persist_options_status =
|
||||
WriteOptionsFile(WriteOptions(), true /*db_mutex_already_held*/);
|
||||
persist_options_status = WriteOptionsFile(true /*db_mutex_already_held*/);
|
||||
} else {
|
||||
// To get here, we must have had invalid options and will not attempt to
|
||||
// persist the options, which means the status is "OK/Uninitialized.
|
||||
@@ -1494,14 +1464,14 @@ int DBImpl::FindMinimumEmptyLevelFitting(
|
||||
return minimum_level;
|
||||
}
|
||||
|
||||
Status DBImpl::FlushWAL(const WriteOptions& write_options, bool sync) {
|
||||
Status DBImpl::FlushWAL(bool sync) {
|
||||
if (manual_wal_flush_) {
|
||||
IOStatus io_s;
|
||||
{
|
||||
// We need to lock log_write_mutex_ since logs_ might change concurrently
|
||||
InstrumentedMutexLock wl(&log_write_mutex_);
|
||||
log::Writer* cur_log_writer = logs_.back().writer;
|
||||
io_s = cur_log_writer->WriteBuffer(write_options);
|
||||
io_s = cur_log_writer->WriteBuffer();
|
||||
}
|
||||
if (!io_s.ok()) {
|
||||
ROCKS_LOG_ERROR(immutable_db_options_.info_log, "WAL flush error %s",
|
||||
@@ -1574,22 +1544,11 @@ Status DBImpl::SyncWAL() {
|
||||
RecordTick(stats_, WAL_FILE_SYNCED);
|
||||
Status status;
|
||||
IOStatus io_s;
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
IOOptions opts;
|
||||
io_s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (!io_s.ok()) {
|
||||
status = io_s;
|
||||
}
|
||||
if (io_s.ok()) {
|
||||
for (log::Writer* log : logs_to_sync) {
|
||||
io_s =
|
||||
log->file()->SyncWithoutFlush(opts, immutable_db_options_.use_fsync);
|
||||
if (!io_s.ok()) {
|
||||
status = io_s;
|
||||
break;
|
||||
}
|
||||
for (log::Writer* log : logs_to_sync) {
|
||||
io_s = log->file()->SyncWithoutFlush(immutable_db_options_.use_fsync);
|
||||
if (!io_s.ok()) {
|
||||
status = io_s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!io_s.ok()) {
|
||||
@@ -1618,7 +1577,9 @@ Status DBImpl::SyncWAL() {
|
||||
}
|
||||
if (status.ok() && synced_wals.IsWalAddition()) {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
status = ApplyWALToManifest(read_options, write_options, &synced_wals);
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
status = ApplyWALToManifest(read_options, &synced_wals);
|
||||
}
|
||||
|
||||
TEST_SYNC_POINT("DBImpl::SyncWAL:BeforeMarkLogsSynced:2");
|
||||
@@ -1627,14 +1588,12 @@ Status DBImpl::SyncWAL() {
|
||||
}
|
||||
|
||||
Status DBImpl::ApplyWALToManifest(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
VersionEdit* synced_wals) {
|
||||
// not empty, write to MANIFEST.
|
||||
mutex_.AssertHeld();
|
||||
|
||||
Status status = versions_->LogAndApplyToDefaultColumnFamily(
|
||||
read_options, write_options, synced_wals, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
read_options, synced_wals, &mutex_, directories_.GetDbDir());
|
||||
if (!status.ok() && versions_->io_status().IsIOError()) {
|
||||
status = error_handler_.SetBGError(versions_->io_status(),
|
||||
BackgroundErrorReason::kManifestWrite);
|
||||
@@ -3515,7 +3474,6 @@ void DBImpl::MultiGetEntity(const ReadOptions& _read_options, size_t num_keys,
|
||||
}
|
||||
|
||||
Status DBImpl::WrapUpCreateColumnFamilies(
|
||||
const ReadOptions& read_options, const WriteOptions& write_options,
|
||||
const std::vector<const ColumnFamilyOptions*>& cf_options) {
|
||||
// NOTE: this function is skipped for create_missing_column_families and
|
||||
// DB::Open, so new functionality here might need to go into Open also.
|
||||
@@ -3528,32 +3486,26 @@ Status DBImpl::WrapUpCreateColumnFamilies(
|
||||
}
|
||||
}
|
||||
// Attempt both follow-up actions even if one fails
|
||||
Status s = WriteOptionsFile(write_options, false /*db_mutex_already_held*/);
|
||||
Status s = WriteOptionsFile(false /*db_mutex_already_held*/);
|
||||
if (register_worker) {
|
||||
s.UpdateIfOk(RegisterRecordSeqnoTimeWorker(read_options, write_options,
|
||||
/* is_new_db */ false));
|
||||
s.UpdateIfOk(RegisterRecordSeqnoTimeWorker(/*from_db_open=*/false));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Status DBImpl::CreateColumnFamily(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
const ColumnFamilyOptions& cf_options,
|
||||
Status DBImpl::CreateColumnFamily(const ColumnFamilyOptions& cf_options,
|
||||
const std::string& column_family,
|
||||
ColumnFamilyHandle** handle) {
|
||||
assert(handle != nullptr);
|
||||
InstrumentedMutexLock ol(&options_mutex_);
|
||||
Status s = CreateColumnFamilyImpl(read_options, write_options, cf_options,
|
||||
column_family, handle);
|
||||
Status s = CreateColumnFamilyImpl(cf_options, column_family, handle);
|
||||
if (s.ok()) {
|
||||
s.UpdateIfOk(
|
||||
WrapUpCreateColumnFamilies(read_options, write_options, {&cf_options}));
|
||||
s.UpdateIfOk(WrapUpCreateColumnFamilies({&cf_options}));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Status DBImpl::CreateColumnFamilies(
|
||||
const ReadOptions& read_options, const WriteOptions& write_options,
|
||||
const ColumnFamilyOptions& cf_options,
|
||||
const std::vector<std::string>& column_family_names,
|
||||
std::vector<ColumnFamilyHandle*>* handles) {
|
||||
@@ -3565,8 +3517,7 @@ Status DBImpl::CreateColumnFamilies(
|
||||
bool success_once = false;
|
||||
for (size_t i = 0; i < num_cf; i++) {
|
||||
ColumnFamilyHandle* handle;
|
||||
s = CreateColumnFamilyImpl(read_options, write_options, cf_options,
|
||||
column_family_names[i], &handle);
|
||||
s = CreateColumnFamilyImpl(cf_options, column_family_names[i], &handle);
|
||||
if (!s.ok()) {
|
||||
break;
|
||||
}
|
||||
@@ -3574,14 +3525,12 @@ Status DBImpl::CreateColumnFamilies(
|
||||
success_once = true;
|
||||
}
|
||||
if (success_once) {
|
||||
s.UpdateIfOk(
|
||||
WrapUpCreateColumnFamilies(read_options, write_options, {&cf_options}));
|
||||
s.UpdateIfOk(WrapUpCreateColumnFamilies({&cf_options}));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Status DBImpl::CreateColumnFamilies(
|
||||
const ReadOptions& read_options, const WriteOptions& write_options,
|
||||
const std::vector<ColumnFamilyDescriptor>& column_families,
|
||||
std::vector<ColumnFamilyHandle*>* handles) {
|
||||
assert(handles != nullptr);
|
||||
@@ -3594,8 +3543,7 @@ Status DBImpl::CreateColumnFamilies(
|
||||
cf_opts.reserve(num_cf);
|
||||
for (size_t i = 0; i < num_cf; i++) {
|
||||
ColumnFamilyHandle* handle;
|
||||
s = CreateColumnFamilyImpl(read_options, write_options,
|
||||
column_families[i].options,
|
||||
s = CreateColumnFamilyImpl(column_families[i].options,
|
||||
column_families[i].name, &handle);
|
||||
if (!s.ok()) {
|
||||
break;
|
||||
@@ -3605,18 +3553,17 @@ Status DBImpl::CreateColumnFamilies(
|
||||
cf_opts.push_back(&column_families[i].options);
|
||||
}
|
||||
if (success_once) {
|
||||
s.UpdateIfOk(
|
||||
WrapUpCreateColumnFamilies(read_options, write_options, cf_opts));
|
||||
s.UpdateIfOk(WrapUpCreateColumnFamilies(cf_opts));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Status DBImpl::CreateColumnFamilyImpl(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
const ColumnFamilyOptions& cf_options,
|
||||
Status DBImpl::CreateColumnFamilyImpl(const ColumnFamilyOptions& cf_options,
|
||||
const std::string& column_family_name,
|
||||
ColumnFamilyHandle** handle) {
|
||||
options_mutex_.AssertHeld();
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
Status s;
|
||||
*handle = nullptr;
|
||||
|
||||
@@ -3660,7 +3607,7 @@ Status DBImpl::CreateColumnFamilyImpl(const ReadOptions& read_options,
|
||||
// LogAndApply will both write the creation in MANIFEST and create
|
||||
// ColumnFamilyData object
|
||||
s = versions_->LogAndApply(nullptr, MutableCFOptions(cf_options),
|
||||
read_options, write_options, &edit, &mutex_,
|
||||
read_options, &edit, &mutex_,
|
||||
directories_.GetDbDir(), false, &cf_options);
|
||||
write_thread_.ExitUnbatched(&w);
|
||||
}
|
||||
@@ -3709,8 +3656,7 @@ Status DBImpl::DropColumnFamily(ColumnFamilyHandle* column_family) {
|
||||
InstrumentedMutexLock ol(&options_mutex_);
|
||||
Status s = DropColumnFamilyImpl(column_family);
|
||||
if (s.ok()) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
s = WriteOptionsFile(WriteOptions(), false /*db_mutex_already_held*/);
|
||||
s = WriteOptionsFile(false /*db_mutex_already_held*/);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -3728,9 +3674,8 @@ Status DBImpl::DropColumnFamilies(
|
||||
success_once = true;
|
||||
}
|
||||
if (success_once) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
Status persist_options_status =
|
||||
WriteOptionsFile(WriteOptions(), false /*db_mutex_already_held*/);
|
||||
WriteOptionsFile(false /*db_mutex_already_held*/);
|
||||
if (s.ok() && !persist_options_status.ok()) {
|
||||
s = persist_options_status;
|
||||
}
|
||||
@@ -3739,10 +3684,8 @@ Status DBImpl::DropColumnFamilies(
|
||||
}
|
||||
|
||||
Status DBImpl::DropColumnFamilyImpl(ColumnFamilyHandle* column_family) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
|
||||
auto cfd = cfh->cfd();
|
||||
if (cfd->GetID() == 0) {
|
||||
@@ -3766,7 +3709,7 @@ Status DBImpl::DropColumnFamilyImpl(ColumnFamilyHandle* column_family) {
|
||||
WriteThread::Writer w;
|
||||
write_thread_.EnterUnbatched(&w, &mutex_);
|
||||
s = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
|
||||
read_options, write_options, &edit, &mutex_,
|
||||
read_options, &edit, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
write_thread_.ExitUnbatched(&w);
|
||||
}
|
||||
@@ -3793,8 +3736,7 @@ Status DBImpl::DropColumnFamilyImpl(ColumnFamilyHandle* column_family) {
|
||||
|
||||
if (cfd->ioptions()->preserve_internal_time_seconds > 0 ||
|
||||
cfd->ioptions()->preclude_last_level_data_seconds > 0) {
|
||||
s = RegisterRecordSeqnoTimeWorker(read_options, write_options,
|
||||
/* is_new_db */ false);
|
||||
s = RegisterRecordSeqnoTimeWorker(/*from_db_open=*/false);
|
||||
}
|
||||
|
||||
if (s.ok()) {
|
||||
@@ -3825,7 +3767,7 @@ bool DBImpl::KeyMayExist(const ReadOptions& read_options,
|
||||
// falsify later if key-may-exist but can't fetch value
|
||||
*value_found = true;
|
||||
}
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
ReadOptions roptions = read_options;
|
||||
roptions.read_tier = kBlockCacheTier; // read from block cache only
|
||||
PinnableSlice pinnable_val;
|
||||
@@ -4344,7 +4286,7 @@ Status DBImpl::GetPropertiesOfAllTables(ColumnFamilyHandle* column_family,
|
||||
version->Ref();
|
||||
mutex_.Unlock();
|
||||
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
auto s = version->GetPropertiesOfAllTables(read_options, props);
|
||||
|
||||
@@ -4368,7 +4310,7 @@ Status DBImpl::GetPropertiesOfTablesInRange(ColumnFamilyHandle* column_family,
|
||||
version->Ref();
|
||||
mutex_.Unlock();
|
||||
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
auto s = version->GetPropertiesOfTablesInRange(read_options, range, n, props);
|
||||
|
||||
@@ -4710,7 +4652,7 @@ Status DBImpl::GetApproximateSizes(const SizeApproximationOptions& options,
|
||||
SuperVersion* sv = GetAndRefSuperVersion(cfd);
|
||||
v = sv->current;
|
||||
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
for (int i = 0; i < n; i++) {
|
||||
// Add timestamp if needed
|
||||
@@ -4774,10 +4716,8 @@ Status DBImpl::GetUpdatesSince(
|
||||
}
|
||||
|
||||
Status DBImpl::DeleteFile(std::string name) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
uint64_t number;
|
||||
FileType type;
|
||||
WalFileType log_type;
|
||||
@@ -4857,7 +4797,7 @@ Status DBImpl::DeleteFile(std::string name) {
|
||||
edit.SetColumnFamily(cfd->GetID());
|
||||
edit.DeleteFile(level, number);
|
||||
status = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
|
||||
read_options, write_options, &edit, &mutex_,
|
||||
read_options, &edit, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
if (status.ok()) {
|
||||
InstallSuperVersionAndScheduleWork(cfd,
|
||||
@@ -4880,10 +4820,8 @@ Status DBImpl::DeleteFile(std::string name) {
|
||||
Status DBImpl::DeleteFilesInRanges(ColumnFamilyHandle* column_family,
|
||||
const RangePtr* ranges, size_t n,
|
||||
bool include_end) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
Status status = Status::OK();
|
||||
auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
|
||||
ColumnFamilyData* cfd = cfh->cfd();
|
||||
@@ -4951,7 +4889,7 @@ Status DBImpl::DeleteFilesInRanges(ColumnFamilyHandle* column_family,
|
||||
}
|
||||
input_version->Ref();
|
||||
status = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
|
||||
read_options, write_options, &edit, &mutex_,
|
||||
read_options, &edit, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
if (status.ok()) {
|
||||
InstallSuperVersionAndScheduleWork(cfd,
|
||||
@@ -5365,8 +5303,7 @@ Status DestroyDB(const std::string& dbname, const Options& options,
|
||||
return result;
|
||||
}
|
||||
|
||||
Status DBImpl::WriteOptionsFile(const WriteOptions& write_options,
|
||||
bool db_mutex_already_held) {
|
||||
Status DBImpl::WriteOptionsFile(bool db_mutex_already_held) {
|
||||
options_mutex_.AssertHeld();
|
||||
|
||||
if (db_mutex_already_held) {
|
||||
@@ -5400,8 +5337,8 @@ Status DBImpl::WriteOptionsFile(const WriteOptions& write_options,
|
||||
|
||||
std::string file_name =
|
||||
TempOptionsFileName(GetName(), versions_->NewFileNumber());
|
||||
Status s = PersistRocksDBOptions(write_options, db_options, cf_names, cf_opts,
|
||||
file_name, fs_.get());
|
||||
Status s = PersistRocksDBOptions(db_options, cf_names, cf_opts, file_name,
|
||||
fs_.get());
|
||||
|
||||
if (s.ok()) {
|
||||
s = RenameTempFileToOptionsFile(file_name);
|
||||
@@ -5594,7 +5531,7 @@ Status DBImpl::GetLatestSequenceForKey(
|
||||
MergeContext merge_context;
|
||||
SequenceNumber max_covering_tombstone_seq = 0;
|
||||
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
ReadOptions read_options;
|
||||
SequenceNumber current_seq = versions_->LastSequence();
|
||||
|
||||
@@ -5750,10 +5687,8 @@ Status DBImpl::IngestExternalFile(
|
||||
|
||||
Status DBImpl::IngestExternalFiles(
|
||||
const std::vector<IngestExternalFileArg>& args) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
if (args.empty()) {
|
||||
return Status::InvalidArgument("ingestion arg list is empty");
|
||||
}
|
||||
@@ -5971,10 +5906,9 @@ Status DBImpl::IngestExternalFiles(
|
||||
}
|
||||
assert(0 == num_entries);
|
||||
}
|
||||
status = versions_->LogAndApply(
|
||||
cfds_to_commit, mutable_cf_options_list, read_options, write_options,
|
||||
|
||||
edit_lists, &mutex_, directories_.GetDbDir());
|
||||
status = versions_->LogAndApply(cfds_to_commit, mutable_cf_options_list,
|
||||
read_options, edit_lists, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
// It is safe to update VersionSet last seqno here after LogAndApply since
|
||||
// LogAndApply persists last sequence number from VersionEdits,
|
||||
// which are from file's largest seqno and not from VersionSet.
|
||||
@@ -6076,10 +6010,8 @@ Status DBImpl::CreateColumnFamilyWithImport(
|
||||
ColumnFamilyHandle** handle) {
|
||||
assert(handle != nullptr);
|
||||
assert(*handle == nullptr);
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
std::string cf_comparator_name = options.comparator->Name();
|
||||
|
||||
size_t total_file_num = 0;
|
||||
@@ -6095,8 +6027,7 @@ Status DBImpl::CreateColumnFamilyWithImport(
|
||||
}
|
||||
|
||||
// Create column family.
|
||||
auto status = CreateColumnFamily(read_options, write_options, options,
|
||||
column_family_name, handle);
|
||||
auto status = CreateColumnFamily(options, column_family_name, handle);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
@@ -6132,8 +6063,8 @@ Status DBImpl::CreateColumnFamilyWithImport(
|
||||
next_file_number = versions_->FetchAddFileNumber(total_file_num);
|
||||
auto cf_options = cfd->GetLatestMutableCFOptions();
|
||||
status =
|
||||
versions_->LogAndApply(cfd, *cf_options, read_options, write_options,
|
||||
&dummy_edit, &mutex_, directories_.GetDbDir());
|
||||
versions_->LogAndApply(cfd, *cf_options, read_options, &dummy_edit,
|
||||
&mutex_, directories_.GetDbDir());
|
||||
if (status.ok()) {
|
||||
InstallSuperVersionAndScheduleWork(cfd, &dummy_sv_ctx, *cf_options);
|
||||
}
|
||||
@@ -6170,8 +6101,8 @@ Status DBImpl::CreateColumnFamilyWithImport(
|
||||
if (status.ok()) {
|
||||
auto cf_options = cfd->GetLatestMutableCFOptions();
|
||||
status = versions_->LogAndApply(cfd, *cf_options, read_options,
|
||||
write_options, import_job.edit(),
|
||||
&mutex_, directories_.GetDbDir());
|
||||
import_job.edit(), &mutex_,
|
||||
directories_.GetDbDir());
|
||||
if (status.ok()) {
|
||||
InstallSuperVersionAndScheduleWork(cfd, &sv_context, *cf_options);
|
||||
}
|
||||
@@ -6255,7 +6186,6 @@ Status DBImpl::ClipColumnFamily(ColumnFamilyHandle* column_family,
|
||||
empty_after_delete = true;
|
||||
} else {
|
||||
const Comparator* const ucmp = column_family->GetComparator();
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
WriteOptions wo;
|
||||
// Delete [smallest_user_key, clip_begin_key)
|
||||
if (ucmp->Compare(smallest_user_key, begin_key) < 0) {
|
||||
@@ -6285,7 +6215,7 @@ Status DBImpl::ClipColumnFamily(ColumnFamilyHandle* column_family,
|
||||
// last level to compact to and that range tombstones are not dropped
|
||||
// during non-bottommost compactions, calling CompactRange() on these two
|
||||
// ranges may not clear all range tombstones.
|
||||
status = CompactRange(compact_options, column_family, nullptr, nullptr);
|
||||
status = CompactRange(compact_options, nullptr, nullptr);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -6576,10 +6506,8 @@ Status DBImpl::ReserveFileNumbersBeforeIngestion(
|
||||
ColumnFamilyData* cfd, uint64_t num,
|
||||
std::unique_ptr<std::list<uint64_t>::iterator>& pending_output_elem,
|
||||
uint64_t* next_file_number) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
Status s;
|
||||
SuperVersionContext dummy_sv_ctx(true /* create_superversion */);
|
||||
assert(nullptr != next_file_number);
|
||||
@@ -6597,8 +6525,8 @@ Status DBImpl::ReserveFileNumbersBeforeIngestion(
|
||||
// reuse the file number that has already assigned to the internal file,
|
||||
// and this will overwrite the external file. To protect the external
|
||||
// file, we have to make sure the file number will never being reused.
|
||||
s = versions_->LogAndApply(cfd, *cf_options, read_options, write_options,
|
||||
&dummy_edit, &mutex_, directories_.GetDbDir());
|
||||
s = versions_->LogAndApply(cfd, *cf_options, read_options, &dummy_edit,
|
||||
&mutex_, directories_.GetDbDir());
|
||||
if (s.ok()) {
|
||||
InstallSuperVersionAndScheduleWork(cfd, &dummy_sv_ctx, *cf_options);
|
||||
}
|
||||
@@ -6644,24 +6572,28 @@ void DBImpl::RecordSeqnoToTimeMapping(uint64_t populate_historical_seconds) {
|
||||
immutable_db_options_.clock->GetCurrentTime(&unix_time_signed)
|
||||
.PermitUncheckedError(); // Ignore error
|
||||
uint64_t unix_time = static_cast<uint64_t>(unix_time_signed);
|
||||
if (populate_historical_seconds > 0) {
|
||||
bool success = true;
|
||||
{
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
bool appended = false;
|
||||
{
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
if (populate_historical_seconds > 0) {
|
||||
if (seqno > 1 && unix_time > populate_historical_seconds) {
|
||||
// seqno=0 is reserved
|
||||
SequenceNumber from_seqno = 1;
|
||||
success = seqno_to_time_mapping_.PrePopulate(
|
||||
appended = seqno_to_time_mapping_.PrePopulate(
|
||||
from_seqno, seqno, unix_time - populate_historical_seconds,
|
||||
unix_time);
|
||||
} else {
|
||||
// One of these will fail
|
||||
assert(seqno > 1);
|
||||
assert(unix_time > populate_historical_seconds);
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
// FIXME: assert(seqno > 0);
|
||||
appended = seqno_to_time_mapping_.Append(seqno, unix_time);
|
||||
}
|
||||
if (success) {
|
||||
}
|
||||
if (populate_historical_seconds > 0) {
|
||||
if (appended) {
|
||||
ROCKS_LOG_INFO(
|
||||
immutable_db_options_.info_log,
|
||||
"Pre-populated sequence number to time entries: [1,%" PRIu64
|
||||
@@ -6674,11 +6606,11 @@ void DBImpl::RecordSeqnoToTimeMapping(uint64_t populate_historical_seconds) {
|
||||
"] -> [%" PRIu64 ",%" PRIu64 "]",
|
||||
seqno, unix_time - populate_historical_seconds, unix_time);
|
||||
}
|
||||
} else {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
// FIXME: assert(seqno > 0);
|
||||
// Always successful assuming seqno never go backwards
|
||||
seqno_to_time_mapping_.Append(seqno, unix_time);
|
||||
} else if (!appended) {
|
||||
ROCKS_LOG_WARN(immutable_db_options_.info_log,
|
||||
"Failed to insert sequence number to time entry: %" PRIu64
|
||||
" -> %" PRIu64,
|
||||
seqno, unix_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-61
@@ -321,41 +321,14 @@ class DBImpl : public DB {
|
||||
|
||||
virtual Status CreateColumnFamily(const ColumnFamilyOptions& cf_options,
|
||||
const std::string& column_family,
|
||||
ColumnFamilyHandle** handle) override {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
return CreateColumnFamily(ReadOptions(), WriteOptions(), cf_options,
|
||||
column_family, handle);
|
||||
}
|
||||
virtual Status CreateColumnFamily(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
const ColumnFamilyOptions& cf_options,
|
||||
const std::string& column_family,
|
||||
ColumnFamilyHandle** handle);
|
||||
ColumnFamilyHandle** handle) override;
|
||||
virtual Status CreateColumnFamilies(
|
||||
const ColumnFamilyOptions& cf_options,
|
||||
const std::vector<std::string>& column_family_names,
|
||||
std::vector<ColumnFamilyHandle*>* handles) override {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
return CreateColumnFamilies(ReadOptions(), WriteOptions(), cf_options,
|
||||
column_family_names, handles);
|
||||
}
|
||||
virtual Status CreateColumnFamilies(
|
||||
const ReadOptions& read_options, const WriteOptions& write_options,
|
||||
const ColumnFamilyOptions& cf_options,
|
||||
const std::vector<std::string>& column_family_names,
|
||||
std::vector<ColumnFamilyHandle*>* handles);
|
||||
|
||||
std::vector<ColumnFamilyHandle*>* handles) override;
|
||||
virtual Status CreateColumnFamilies(
|
||||
const std::vector<ColumnFamilyDescriptor>& column_families,
|
||||
std::vector<ColumnFamilyHandle*>* handles) override {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
return CreateColumnFamilies(ReadOptions(), WriteOptions(), column_families,
|
||||
handles);
|
||||
}
|
||||
virtual Status CreateColumnFamilies(
|
||||
const ReadOptions& read_options, const WriteOptions& write_options,
|
||||
const std::vector<ColumnFamilyDescriptor>& column_families,
|
||||
std::vector<ColumnFamilyHandle*>* handles);
|
||||
std::vector<ColumnFamilyHandle*>* handles) override;
|
||||
virtual Status DropColumnFamily(ColumnFamilyHandle* column_family) override;
|
||||
virtual Status DropColumnFamilies(
|
||||
const std::vector<ColumnFamilyHandle*>& column_families) override;
|
||||
@@ -467,12 +440,7 @@ class DBImpl : public DB {
|
||||
virtual Status Flush(
|
||||
const FlushOptions& options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_families) override;
|
||||
virtual Status FlushWAL(bool sync) override {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
return FlushWAL(WriteOptions(), sync);
|
||||
}
|
||||
|
||||
virtual Status FlushWAL(const WriteOptions& write_options, bool sync);
|
||||
virtual Status FlushWAL(bool sync) override;
|
||||
bool WALBufferIsEmpty();
|
||||
virtual Status SyncWAL() override;
|
||||
virtual Status LockWAL() override;
|
||||
@@ -1438,8 +1406,7 @@ class DBImpl : public DB {
|
||||
|
||||
// Persist options to options file. Must be holding options_mutex_.
|
||||
// Will lock DB mutex if !db_mutex_already_held.
|
||||
Status WriteOptionsFile(const WriteOptions& write_options,
|
||||
bool db_mutex_already_held);
|
||||
Status WriteOptionsFile(bool db_mutex_already_held);
|
||||
|
||||
Status CompactRangeInternal(const CompactRangeOptions& options,
|
||||
ColumnFamilyHandle* column_family,
|
||||
@@ -1565,8 +1532,7 @@ class DBImpl : public DB {
|
||||
virtual bool OwnTablesAndLogs() const { return true; }
|
||||
|
||||
// Setup DB identity file, and write DB ID to manifest if necessary.
|
||||
Status SetupDBId(const WriteOptions& write_options, bool read_only,
|
||||
RecoveryContext* recovery_ctx);
|
||||
Status SetupDBId(bool read_only, RecoveryContext* recovery_ctx);
|
||||
// Assign db_id_ and write DB ID to manifest if necessary.
|
||||
void SetDBId(std::string&& id, bool read_only, RecoveryContext* recovery_ctx);
|
||||
|
||||
@@ -1693,8 +1659,7 @@ class DBImpl : public DB {
|
||||
return w;
|
||||
}
|
||||
Status ClearWriter() {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
Status s = writer->WriteBuffer(WriteOptions());
|
||||
Status s = writer->WriteBuffer();
|
||||
delete writer;
|
||||
writer = nullptr;
|
||||
return s;
|
||||
@@ -1870,15 +1835,12 @@ class DBImpl : public DB {
|
||||
const Status CreateArchivalDirectory();
|
||||
|
||||
// Create a column family, without some of the follow-up work yet
|
||||
Status CreateColumnFamilyImpl(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
const ColumnFamilyOptions& cf_options,
|
||||
Status CreateColumnFamilyImpl(const ColumnFamilyOptions& cf_options,
|
||||
const std::string& cf_name,
|
||||
ColumnFamilyHandle** handle);
|
||||
|
||||
// Follow-up work to user creating a column family or (families)
|
||||
Status WrapUpCreateColumnFamilies(
|
||||
const ReadOptions& read_options, const WriteOptions& write_options,
|
||||
const std::vector<const ColumnFamilyOptions*>& cf_options);
|
||||
|
||||
Status DropColumnFamilyImpl(ColumnFamilyHandle* column_family);
|
||||
@@ -1910,8 +1872,7 @@ class DBImpl : public DB {
|
||||
void ReleaseFileNumberFromPendingOutputs(
|
||||
std::unique_ptr<std::list<uint64_t>::iterator>& v);
|
||||
|
||||
IOStatus SyncClosedLogs(const WriteOptions& write_options,
|
||||
JobContext* job_context, VersionEdit* synced_wals,
|
||||
IOStatus SyncClosedLogs(JobContext* job_context, VersionEdit* synced_wals,
|
||||
bool error_recovery_in_prog);
|
||||
|
||||
// Flush the in-memory write buffer to storage. Switches to a new
|
||||
@@ -2097,10 +2058,12 @@ class DBImpl : public DB {
|
||||
WriteBatch* tmp_batch, WriteBatch** merged_batch,
|
||||
size_t* write_with_wal, WriteBatch** to_be_cached_state);
|
||||
|
||||
IOStatus WriteToWAL(const WriteBatch& merged_batch,
|
||||
const WriteOptions& write_options,
|
||||
log::Writer* log_writer, uint64_t* log_used,
|
||||
uint64_t* log_size,
|
||||
// rate_limiter_priority is used to charge `DBOptions::rate_limiter`
|
||||
// for automatic WAL flush (`Options::manual_wal_flush` == false)
|
||||
// associated with this WriteToWAL
|
||||
IOStatus WriteToWAL(const WriteBatch& merged_batch, log::Writer* log_writer,
|
||||
uint64_t* log_used, uint64_t* log_size,
|
||||
Env::IOPriority rate_limiter_priority,
|
||||
LogFileNumberSize& log_file_number_size);
|
||||
|
||||
IOStatus WriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
@@ -2212,9 +2175,7 @@ class DBImpl : public DB {
|
||||
// Cancel scheduled periodic tasks
|
||||
Status CancelPeriodicTaskScheduler();
|
||||
|
||||
Status RegisterRecordSeqnoTimeWorker(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
bool is_new_db);
|
||||
Status RegisterRecordSeqnoTimeWorker(bool is_new_db);
|
||||
|
||||
void PrintStatistics();
|
||||
|
||||
@@ -2242,9 +2203,7 @@ class DBImpl : public DB {
|
||||
|
||||
// helper function to call after some of the logs_ were synced
|
||||
void MarkLogsSynced(uint64_t up_to, bool synced_dir, VersionEdit* edit);
|
||||
Status ApplyWALToManifest(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
VersionEdit* edit);
|
||||
Status ApplyWALToManifest(const ReadOptions& read_options, VersionEdit* edit);
|
||||
// WALs with log number up to up_to are not synced successfully.
|
||||
void MarkLogsNotSynced(uint64_t up_to);
|
||||
|
||||
@@ -2316,9 +2275,8 @@ class DBImpl : public DB {
|
||||
size_t GetWalPreallocateBlockSize(uint64_t write_buffer_size) const;
|
||||
Env::WriteLifeTimeHint CalculateWALWriteHint() { return Env::WLTH_SHORT; }
|
||||
|
||||
IOStatus CreateWAL(const WriteOptions& write_options, uint64_t log_file_num,
|
||||
uint64_t recycle_log_number, size_t preallocate_block_size,
|
||||
log::Writer** new_log);
|
||||
IOStatus CreateWAL(uint64_t log_file_num, uint64_t recycle_log_number,
|
||||
size_t preallocate_block_size, log::Writer** new_log);
|
||||
|
||||
// Validate self-consistency of DB options
|
||||
static Status ValidateOptions(const DBOptions& db_options);
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
#include "monitoring/perf_context_imp.h"
|
||||
#include "monitoring/thread_status_updater.h"
|
||||
#include "monitoring/thread_status_util.h"
|
||||
#include "rocksdb/file_system.h"
|
||||
#include "rocksdb/io_status.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "rocksdb/table.h"
|
||||
#include "test_util/sync_point.h"
|
||||
#include "util/cast_util.h"
|
||||
#include "util/coding.h"
|
||||
@@ -116,8 +112,7 @@ bool DBImpl::ShouldRescheduleFlushRequestToRetainUDT(
|
||||
return true;
|
||||
}
|
||||
|
||||
IOStatus DBImpl::SyncClosedLogs(const WriteOptions& write_options,
|
||||
JobContext* job_context,
|
||||
IOStatus DBImpl::SyncClosedLogs(JobContext* job_context,
|
||||
VersionEdit* synced_wals,
|
||||
bool error_recovery_in_prog) {
|
||||
TEST_SYNC_POINT("DBImpl::SyncClosedLogs:Start");
|
||||
@@ -148,13 +143,7 @@ IOStatus DBImpl::SyncClosedLogs(const WriteOptions& write_options,
|
||||
if (error_recovery_in_prog) {
|
||||
log->file()->reset_seen_error();
|
||||
}
|
||||
|
||||
IOOptions io_options;
|
||||
io_s = WritableFileWriter::PrepareIOOptions(write_options, io_options);
|
||||
if (!io_s.ok()) {
|
||||
break;
|
||||
}
|
||||
io_s = log->file()->Sync(io_options, immutable_db_options_.use_fsync);
|
||||
io_s = log->file()->Sync(immutable_db_options_.use_fsync);
|
||||
if (!io_s.ok()) {
|
||||
break;
|
||||
}
|
||||
@@ -163,21 +152,16 @@ IOStatus DBImpl::SyncClosedLogs(const WriteOptions& write_options,
|
||||
if (error_recovery_in_prog) {
|
||||
log->file()->reset_seen_error();
|
||||
}
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
io_s = log->Close(WriteOptions());
|
||||
io_s = log->Close();
|
||||
if (!io_s.ok()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (io_s.ok()) {
|
||||
IOOptions io_options;
|
||||
io_s = WritableFileWriter::PrepareIOOptions(write_options, io_options);
|
||||
if (io_s.ok()) {
|
||||
io_s = directories_.GetWalDir()->FsyncWithDirOptions(
|
||||
io_options, nullptr,
|
||||
DirFsyncOptions(DirFsyncOptions::FsyncReason::kNewFileSynced));
|
||||
}
|
||||
io_s = directories_.GetWalDir()->FsyncWithDirOptions(
|
||||
IOOptions(), nullptr,
|
||||
DirFsyncOptions(DirFsyncOptions::FsyncReason::kNewFileSynced));
|
||||
}
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::SyncClosedLogs:BeforeReLock",
|
||||
@@ -215,8 +199,6 @@ Status DBImpl::FlushMemTableToOutputFile(
|
||||
assert(cfd->imm()->IsFlushPending());
|
||||
assert(versions_);
|
||||
assert(versions_->GetColumnFamilySet());
|
||||
const ReadOptions read_options(Env::IOActivity::kFlush);
|
||||
const WriteOptions write_options(Env::IOActivity::kFlush);
|
||||
// If there are more than one column families, we need to make sure that
|
||||
// all the log files except the most recent one are synced. Otherwise if
|
||||
// the host crashes after flushing and before WAL is persistent, the
|
||||
@@ -283,12 +265,13 @@ Status DBImpl::FlushMemTableToOutputFile(
|
||||
VersionEdit synced_wals;
|
||||
bool error_recovery_in_prog = error_handler_.IsRecoveryInProgress();
|
||||
mutex_.Unlock();
|
||||
log_io_s = SyncClosedLogs(write_options, job_context, &synced_wals,
|
||||
error_recovery_in_prog);
|
||||
log_io_s =
|
||||
SyncClosedLogs(job_context, &synced_wals, error_recovery_in_prog);
|
||||
mutex_.Lock();
|
||||
if (log_io_s.ok() && synced_wals.IsWalAddition()) {
|
||||
log_io_s = status_to_io_status(
|
||||
ApplyWALToManifest(read_options, write_options, &synced_wals));
|
||||
const ReadOptions read_options(Env::IOActivity::kFlush);
|
||||
log_io_s =
|
||||
status_to_io_status(ApplyWALToManifest(read_options, &synced_wals));
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::FlushMemTableToOutputFile:CommitWal:1",
|
||||
nullptr);
|
||||
}
|
||||
@@ -482,8 +465,6 @@ Status DBImpl::AtomicFlushMemTablesToOutputFiles(
|
||||
const autovector<BGFlushArg>& bg_flush_args, bool* made_progress,
|
||||
JobContext* job_context, LogBuffer* log_buffer, Env::Priority thread_pri) {
|
||||
mutex_.AssertHeld();
|
||||
const ReadOptions read_options(Env::IOActivity::kFlush);
|
||||
const WriteOptions write_options(Env::IOActivity::kFlush);
|
||||
|
||||
autovector<ColumnFamilyData*> cfds;
|
||||
for (const auto& arg : bg_flush_args) {
|
||||
@@ -571,12 +552,13 @@ Status DBImpl::AtomicFlushMemTablesToOutputFiles(
|
||||
VersionEdit synced_wals;
|
||||
bool error_recovery_in_prog = error_handler_.IsRecoveryInProgress();
|
||||
mutex_.Unlock();
|
||||
log_io_s = SyncClosedLogs(write_options, job_context, &synced_wals,
|
||||
error_recovery_in_prog);
|
||||
log_io_s =
|
||||
SyncClosedLogs(job_context, &synced_wals, error_recovery_in_prog);
|
||||
mutex_.Lock();
|
||||
if (log_io_s.ok() && synced_wals.IsWalAddition()) {
|
||||
log_io_s = status_to_io_status(
|
||||
ApplyWALToManifest(read_options, write_options, &synced_wals));
|
||||
const ReadOptions read_options(Env::IOActivity::kFlush);
|
||||
log_io_s =
|
||||
status_to_io_status(ApplyWALToManifest(read_options, &synced_wals));
|
||||
}
|
||||
|
||||
if (!log_io_s.ok() && !log_io_s.IsShutdownInProgress() &&
|
||||
@@ -671,14 +653,9 @@ Status DBImpl::AtomicFlushMemTablesToOutputFiles(
|
||||
// Sync on all distinct output directories.
|
||||
for (auto dir : distinct_output_dirs) {
|
||||
if (dir != nullptr) {
|
||||
IOOptions io_options;
|
||||
Status error_status =
|
||||
WritableFileWriter::PrepareIOOptions(write_options, io_options);
|
||||
if (error_status.ok()) {
|
||||
error_status = dir->FsyncWithDirOptions(
|
||||
io_options, nullptr,
|
||||
DirFsyncOptions(DirFsyncOptions::FsyncReason::kNewFileSynced));
|
||||
}
|
||||
Status error_status = dir->FsyncWithDirOptions(
|
||||
IOOptions(), nullptr,
|
||||
DirFsyncOptions(DirFsyncOptions::FsyncReason::kNewFileSynced));
|
||||
if (!error_status.ok()) {
|
||||
s = error_status;
|
||||
break;
|
||||
@@ -1072,10 +1049,8 @@ Status DBImpl::IncreaseFullHistoryTsLowImpl(ColumnFamilyData* cfd,
|
||||
edit.SetColumnFamily(cfd->GetID());
|
||||
edit.SetFullHistoryTsLow(ts_low);
|
||||
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::IncreaseFullHistoryTsLowImpl:BeforeEdit",
|
||||
&edit);
|
||||
|
||||
@@ -1089,7 +1064,7 @@ Status DBImpl::IncreaseFullHistoryTsLowImpl(ColumnFamilyData* cfd,
|
||||
}
|
||||
|
||||
Status s = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
|
||||
read_options, write_options, &edit, &mutex_,
|
||||
read_options, &edit, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
@@ -1779,7 +1754,6 @@ Status DBImpl::ReFitLevel(ColumnFamilyData* cfd, int level, int target_level) {
|
||||
}
|
||||
|
||||
const ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
const WriteOptions write_options(Env::IOActivity::kCompaction);
|
||||
|
||||
SuperVersionContext sv_context(/* create_superversion */ true);
|
||||
|
||||
@@ -1896,9 +1870,9 @@ Status DBImpl::ReFitLevel(ColumnFamilyData* cfd, int level, int target_level) {
|
||||
"[%s] Apply version edit:\n%s", cfd->GetName().c_str(),
|
||||
edit.DebugString().data());
|
||||
|
||||
Status status = versions_->LogAndApply(cfd, mutable_cf_options,
|
||||
read_options, write_options, &edit,
|
||||
&mutex_, directories_.GetDbDir());
|
||||
Status status =
|
||||
versions_->LogAndApply(cfd, mutable_cf_options, read_options, &edit,
|
||||
&mutex_, directories_.GetDbDir());
|
||||
|
||||
cfd->compaction_picker()->UnregisterCompaction(c.get());
|
||||
c.reset();
|
||||
@@ -3327,7 +3301,7 @@ void DBImpl::BackgroundCallFlush(Env::Priority thread_pri) {
|
||||
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:FlushFinish:0");
|
||||
ReleaseFileNumberFromPendingOutputs(pending_outputs_inserted_elem);
|
||||
// There is no need to find obsolete files if the flush job is rescheduled
|
||||
// There is no need to do these clean up if the flush job is rescheduled
|
||||
// to retain user-defined timestamps because the job doesn't get to the
|
||||
// stage of actually flushing the MemTables.
|
||||
if (!flush_rescheduled_to_retain_udt) {
|
||||
@@ -3335,25 +3309,25 @@ void DBImpl::BackgroundCallFlush(Env::Priority thread_pri) {
|
||||
// have created. Thus, we force full scan in FindObsoleteFiles()
|
||||
FindObsoleteFiles(&job_context, !s.ok() && !s.IsShutdownInProgress() &&
|
||||
!s.IsColumnFamilyDropped());
|
||||
}
|
||||
// delete unnecessary files if any, this is done outside the mutex
|
||||
if (job_context.HaveSomethingToClean() ||
|
||||
job_context.HaveSomethingToDelete() || !log_buffer.IsEmpty()) {
|
||||
mutex_.Unlock();
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:FilesFound");
|
||||
// Have to flush the info logs before bg_flush_scheduled_--
|
||||
// because if bg_flush_scheduled_ becomes 0 and the lock is
|
||||
// released, the deconstructor of DB can kick in and destroy all the
|
||||
// states of DB so info_log might not be available after that point.
|
||||
// It also applies to access other states that DB owns.
|
||||
log_buffer.FlushBufferToLog();
|
||||
if (job_context.HaveSomethingToDelete()) {
|
||||
PurgeObsoleteFiles(job_context);
|
||||
// delete unnecessary files if any, this is done outside the mutex
|
||||
if (job_context.HaveSomethingToClean() ||
|
||||
job_context.HaveSomethingToDelete() || !log_buffer.IsEmpty()) {
|
||||
mutex_.Unlock();
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:FilesFound");
|
||||
// Have to flush the info logs before bg_flush_scheduled_--
|
||||
// because if bg_flush_scheduled_ becomes 0 and the lock is
|
||||
// released, the deconstructor of DB can kick in and destroy all the
|
||||
// states of DB so info_log might not be available after that point.
|
||||
// It also applies to access other states that DB owns.
|
||||
log_buffer.FlushBufferToLog();
|
||||
if (job_context.HaveSomethingToDelete()) {
|
||||
PurgeObsoleteFiles(job_context);
|
||||
}
|
||||
job_context.Clean();
|
||||
mutex_.Lock();
|
||||
}
|
||||
job_context.Clean();
|
||||
mutex_.Lock();
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:ContextCleanedUp");
|
||||
}
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:ContextCleanedUp");
|
||||
|
||||
assert(num_running_flushes_ > 0);
|
||||
num_running_flushes_--;
|
||||
@@ -3506,7 +3480,6 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCompaction:Start");
|
||||
|
||||
const ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
const WriteOptions write_options(Env::IOActivity::kCompaction);
|
||||
|
||||
bool is_manual = (manual_compaction != nullptr);
|
||||
std::unique_ptr<Compaction> c;
|
||||
@@ -3719,7 +3692,7 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
}
|
||||
status = versions_->LogAndApply(
|
||||
c->column_family_data(), *c->mutable_cf_options(), read_options,
|
||||
write_options, c->edit(), &mutex_, directories_.GetDbDir(),
|
||||
c->edit(), &mutex_, directories_.GetDbDir(),
|
||||
/*new_descriptor_log=*/false, /*column_family_options=*/nullptr,
|
||||
[&c, &compaction_released](const Status& s) {
|
||||
c->ReleaseCompactionFiles(s);
|
||||
@@ -3793,7 +3766,7 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
}
|
||||
status = versions_->LogAndApply(
|
||||
c->column_family_data(), *c->mutable_cf_options(), read_options,
|
||||
write_options, c->edit(), &mutex_, directories_.GetDbDir(),
|
||||
c->edit(), &mutex_, directories_.GetDbDir(),
|
||||
/*new_descriptor_log=*/false, /*column_family_options=*/nullptr,
|
||||
[&c, &compaction_released](const Status& s) {
|
||||
c->ReleaseCompactionFiles(s);
|
||||
|
||||
@@ -61,10 +61,8 @@ Status DBImpl::PromoteL0(ColumnFamilyHandle* column_family, int target_level) {
|
||||
"PromoteL0 FAILED. Invalid target level %d\n", target_level);
|
||||
return Status::InvalidArgument("Invalid target level");
|
||||
}
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
Status status;
|
||||
VersionEdit edit;
|
||||
JobContext job_context(next_job_id_.fetch_add(1), true);
|
||||
@@ -145,7 +143,7 @@ Status DBImpl::PromoteL0(ColumnFamilyHandle* column_family, int target_level) {
|
||||
}
|
||||
|
||||
status = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
|
||||
read_options, write_options, &edit, &mutex_,
|
||||
read_options, &edit, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
if (status.ok()) {
|
||||
InstallSuperVersionAndScheduleWork(cfd,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "file/sst_file_manager_impl.h"
|
||||
#include "logging/logging.h"
|
||||
#include "port/port.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "util/autovector.h"
|
||||
#include "util/defer.h"
|
||||
|
||||
@@ -511,8 +510,7 @@ void DBImpl::PurgeObsoleteFiles(JobContext& state, bool schedule_only) {
|
||||
// Close WALs before trying to delete them.
|
||||
for (const auto w : state.logs_to_free) {
|
||||
// TODO: maybe check the return value of Close.
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
auto s = w->Close(WriteOptions());
|
||||
auto s = w->Close();
|
||||
s.PermitUncheckedError();
|
||||
}
|
||||
|
||||
@@ -927,8 +925,7 @@ void DBImpl::SetDBId(std::string&& id, bool read_only,
|
||||
}
|
||||
}
|
||||
|
||||
Status DBImpl::SetupDBId(const WriteOptions& write_options, bool read_only,
|
||||
RecoveryContext* recovery_ctx) {
|
||||
Status DBImpl::SetupDBId(bool read_only, RecoveryContext* recovery_ctx) {
|
||||
Status s;
|
||||
// Check for the IDENTITY file and create it if not there or
|
||||
// broken or not matching manifest
|
||||
@@ -961,7 +958,7 @@ Status DBImpl::SetupDBId(const WriteOptions& write_options, bool read_only,
|
||||
}
|
||||
// Persist it to IDENTITY file if allowed
|
||||
if (!read_only) {
|
||||
s = SetIdentityFile(write_options, env_, dbname_, db_id_);
|
||||
s = SetIdentityFile(env_, dbname_, db_id_);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
+34
-64
@@ -21,7 +21,6 @@
|
||||
#include "monitoring/persistent_stats_history.h"
|
||||
#include "monitoring/thread_status_util.h"
|
||||
#include "options/options_helper.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "rocksdb/table.h"
|
||||
#include "rocksdb/wal_filter.h"
|
||||
#include "test_util/sync_point.h"
|
||||
@@ -310,8 +309,7 @@ Status DBImpl::ValidateOptions(const DBOptions& db_options) {
|
||||
|
||||
Status DBImpl::NewDB(std::vector<std::string>* new_filenames) {
|
||||
VersionEdit new_db;
|
||||
const WriteOptions write_options(Env::IOActivity::kDBOpen);
|
||||
Status s = SetIdentityFile(write_options, env_, dbname_);
|
||||
Status s = SetIdentityFile(env_, dbname_);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
@@ -341,23 +339,20 @@ Status DBImpl::NewDB(std::vector<std::string>* new_filenames) {
|
||||
immutable_db_options_.manifest_preallocation_size);
|
||||
std::unique_ptr<WritableFileWriter> file_writer(new WritableFileWriter(
|
||||
std::move(file), manifest, file_options, immutable_db_options_.clock,
|
||||
io_tracer_, nullptr /* stats */,
|
||||
Histograms::HISTOGRAM_ENUM_MAX /* hist_type */,
|
||||
immutable_db_options_.listeners, nullptr,
|
||||
tmp_set.Contains(FileType::kDescriptorFile),
|
||||
io_tracer_, nullptr /* stats */, immutable_db_options_.listeners,
|
||||
nullptr, tmp_set.Contains(FileType::kDescriptorFile),
|
||||
tmp_set.Contains(FileType::kDescriptorFile)));
|
||||
log::Writer log(std::move(file_writer), 0, false);
|
||||
std::string record;
|
||||
new_db.EncodeTo(&record);
|
||||
s = log.AddRecord(write_options, record);
|
||||
s = log.AddRecord(record);
|
||||
if (s.ok()) {
|
||||
s = SyncManifest(&immutable_db_options_, write_options, log.file());
|
||||
s = SyncManifest(&immutable_db_options_, log.file());
|
||||
}
|
||||
}
|
||||
if (s.ok()) {
|
||||
// Make "CURRENT" file that points to the new manifest file.
|
||||
s = SetCurrentFile(write_options, fs_.get(), dbname_, 1,
|
||||
directories_.GetDbDir());
|
||||
s = SetCurrentFile(fs_.get(), dbname_, 1, directories_.GetDbDir());
|
||||
if (new_filenames) {
|
||||
new_filenames->emplace_back(
|
||||
manifest.substr(manifest.find_last_of("/\\") + 1));
|
||||
@@ -423,7 +418,6 @@ Status DBImpl::Recover(
|
||||
uint64_t* recovered_seq, RecoveryContext* recovery_ctx) {
|
||||
mutex_.AssertHeld();
|
||||
|
||||
const WriteOptions write_options(Env::IOActivity::kDBOpen);
|
||||
bool tmp_is_new_db = false;
|
||||
bool& is_new_db = recovery_ctx ? recovery_ctx->is_new_db_ : tmp_is_new_db;
|
||||
assert(db_lock_ == nullptr);
|
||||
@@ -648,7 +642,7 @@ Status DBImpl::Recover(
|
||||
}
|
||||
}
|
||||
}
|
||||
s = SetupDBId(write_options, read_only, recovery_ctx);
|
||||
s = SetupDBId(read_only, recovery_ctx);
|
||||
ROCKS_LOG_INFO(immutable_db_options_.info_log, "DB ID: %s\n", db_id_.c_str());
|
||||
if (s.ok() && !read_only) {
|
||||
s = DeleteUnreferencedSstFiles(recovery_ctx);
|
||||
@@ -878,9 +872,8 @@ Status DBImpl::PersistentStatsProcessFormatVersion() {
|
||||
if (s.ok()) {
|
||||
ColumnFamilyOptions cfo;
|
||||
OptimizeForPersistentStats(&cfo);
|
||||
s = CreateColumnFamilyImpl(ReadOptions(Env::IOActivity::kDBOpen),
|
||||
WriteOptions(Env::IOActivity::kDBOpen), cfo,
|
||||
kPersistentStatsColumnFamilyName, &handle);
|
||||
s = CreateColumnFamilyImpl(cfo, kPersistentStatsColumnFamilyName,
|
||||
&handle);
|
||||
}
|
||||
if (s.ok()) {
|
||||
persist_stats_cf_handle_ = static_cast<ColumnFamilyHandleImpl*>(handle);
|
||||
@@ -902,7 +895,6 @@ Status DBImpl::PersistentStatsProcessFormatVersion() {
|
||||
std::to_string(kStatsCFCompatibleFormatVersion));
|
||||
}
|
||||
if (s.ok()) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
WriteOptions wo;
|
||||
wo.low_pri = true;
|
||||
wo.no_slowdown = true;
|
||||
@@ -934,9 +926,7 @@ Status DBImpl::InitPersistStatsColumnFamily() {
|
||||
ColumnFamilyHandle* handle = nullptr;
|
||||
ColumnFamilyOptions cfo;
|
||||
OptimizeForPersistentStats(&cfo);
|
||||
s = CreateColumnFamilyImpl(ReadOptions(Env::IOActivity::kDBOpen),
|
||||
WriteOptions(Env::IOActivity::kDBOpen), cfo,
|
||||
kPersistentStatsColumnFamilyName, &handle);
|
||||
s = CreateColumnFamilyImpl(cfo, kPersistentStatsColumnFamilyName, &handle);
|
||||
persist_stats_cf_handle_ = static_cast<ColumnFamilyHandleImpl*>(handle);
|
||||
mutex_.Lock();
|
||||
}
|
||||
@@ -947,12 +937,9 @@ Status DBImpl::LogAndApplyForRecovery(const RecoveryContext& recovery_ctx) {
|
||||
mutex_.AssertHeld();
|
||||
assert(versions_->descriptor_log_ == nullptr);
|
||||
const ReadOptions read_options(Env::IOActivity::kDBOpen);
|
||||
const WriteOptions write_options(Env::IOActivity::kDBOpen);
|
||||
|
||||
Status s = versions_->LogAndApply(recovery_ctx.cfds_,
|
||||
recovery_ctx.mutable_cf_opts_, read_options,
|
||||
write_options, recovery_ctx.edit_lists_,
|
||||
&mutex_, directories_.GetDbDir());
|
||||
Status s = versions_->LogAndApply(
|
||||
recovery_ctx.cfds_, recovery_ctx.mutable_cf_opts_, read_options,
|
||||
recovery_ctx.edit_lists_, &mutex_, directories_.GetDbDir());
|
||||
if (s.ok() && !(recovery_ctx.files_to_delete_.empty())) {
|
||||
mutex_.Unlock();
|
||||
for (const auto& stale_sst_file : recovery_ctx.files_to_delete_) {
|
||||
@@ -1678,11 +1665,9 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
|
||||
}
|
||||
|
||||
IOStatus io_s;
|
||||
const ReadOptions read_option(Env::IOActivity::kDBOpen);
|
||||
const WriteOptions write_option(Env::IO_HIGH, Env::IOActivity::kDBOpen);
|
||||
TableBuilderOptions tboptions(
|
||||
*cfd->ioptions(), mutable_cf_options, read_option, write_option,
|
||||
cfd->internal_comparator(), cfd->int_tbl_prop_collector_factories(),
|
||||
*cfd->ioptions(), mutable_cf_options, cfd->internal_comparator(),
|
||||
cfd->int_tbl_prop_collector_factories(),
|
||||
GetCompressionFlush(*cfd->ioptions(), mutable_cf_options),
|
||||
mutable_cf_options.compression_opts, cfd->GetID(), cfd->GetName(),
|
||||
0 /* level */, false /* is_bottommost */,
|
||||
@@ -1692,15 +1677,16 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
|
||||
SeqnoToTimeMapping empty_seqno_to_time_mapping;
|
||||
Version* version = cfd->current();
|
||||
version->Ref();
|
||||
const ReadOptions read_option(Env::IOActivity::kDBOpen);
|
||||
uint64_t num_input_entries = 0;
|
||||
s = BuildTable(
|
||||
dbname_, versions_.get(), immutable_db_options_, tboptions,
|
||||
file_options_for_compaction_, cfd->table_cache(), iter.get(),
|
||||
std::move(range_del_iters), &meta, &blob_file_additions,
|
||||
file_options_for_compaction_, read_option, cfd->table_cache(),
|
||||
iter.get(), std::move(range_del_iters), &meta, &blob_file_additions,
|
||||
snapshot_seqs, earliest_write_conflict_snapshot, kMaxSequenceNumber,
|
||||
snapshot_checker, paranoid_file_checks, cfd->internal_stats(), &io_s,
|
||||
io_tracer_, BlobFileCreationReason::kRecovery,
|
||||
empty_seqno_to_time_mapping, &event_logger_, job_id,
|
||||
empty_seqno_to_time_mapping, &event_logger_, job_id, Env::IO_HIGH,
|
||||
nullptr /* table_properties */, write_hint,
|
||||
nullptr /*full_history_ts_low*/, &blob_callback_, version,
|
||||
&num_input_entries);
|
||||
@@ -1902,8 +1888,7 @@ Status DB::OpenAndTrimHistory(
|
||||
return s;
|
||||
}
|
||||
|
||||
IOStatus DBImpl::CreateWAL(const WriteOptions& write_options,
|
||||
uint64_t log_file_num, uint64_t recycle_log_number,
|
||||
IOStatus DBImpl::CreateWAL(uint64_t log_file_num, uint64_t recycle_log_number,
|
||||
size_t preallocate_block_size,
|
||||
log::Writer** new_log) {
|
||||
IOStatus io_s;
|
||||
@@ -1937,15 +1922,14 @@ IOStatus DBImpl::CreateWAL(const WriteOptions& write_options,
|
||||
FileTypeSet tmp_set = immutable_db_options_.checksum_handoff_file_types;
|
||||
std::unique_ptr<WritableFileWriter> file_writer(new WritableFileWriter(
|
||||
std::move(lfile), log_fname, opt_file_options,
|
||||
immutable_db_options_.clock, io_tracer_, nullptr /* stats */,
|
||||
Histograms::HISTOGRAM_ENUM_MAX /* hist_type */, listeners, nullptr,
|
||||
tmp_set.Contains(FileType::kWalFile),
|
||||
immutable_db_options_.clock, io_tracer_, nullptr /* stats */, listeners,
|
||||
nullptr, tmp_set.Contains(FileType::kWalFile),
|
||||
tmp_set.Contains(FileType::kWalFile)));
|
||||
*new_log = new log::Writer(std::move(file_writer), log_file_num,
|
||||
immutable_db_options_.recycle_log_file_num > 0,
|
||||
immutable_db_options_.manual_wal_flush,
|
||||
immutable_db_options_.wal_compression);
|
||||
io_s = (*new_log)->AddCompressionTypeRecord(write_options);
|
||||
io_s = (*new_log)->AddCompressionTypeRecord();
|
||||
}
|
||||
return io_s;
|
||||
}
|
||||
@@ -1954,9 +1938,6 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
const std::vector<ColumnFamilyDescriptor>& column_families,
|
||||
std::vector<ColumnFamilyHandle*>* handles, DB** dbptr,
|
||||
const bool seq_per_batch, const bool batch_per_txn) {
|
||||
const WriteOptions write_options(Env::IOActivity::kDBOpen);
|
||||
const ReadOptions read_options(Env::IOActivity::kDBOpen);
|
||||
|
||||
Status s = ValidateOptionsByTable(db_options, column_families);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
@@ -2033,7 +2014,7 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
log::Writer* new_log = nullptr;
|
||||
const size_t preallocate_block_size =
|
||||
impl->GetWalPreallocateBlockSize(max_write_buffer_size);
|
||||
s = impl->CreateWAL(write_options, new_log_number, 0 /*recycle_log_number*/,
|
||||
s = impl->CreateWAL(new_log_number, 0 /*recycle_log_number*/,
|
||||
preallocate_block_size, &new_log);
|
||||
if (s.ok()) {
|
||||
InstrumentedMutexLock wl(&impl->log_write_mutex_);
|
||||
@@ -2058,25 +2039,21 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
if (recovered_seq != kMaxSequenceNumber) {
|
||||
WriteBatch empty_batch;
|
||||
WriteBatchInternal::SetSequence(&empty_batch, recovered_seq);
|
||||
WriteOptions write_options;
|
||||
uint64_t log_used, log_size;
|
||||
log::Writer* log_writer = impl->logs_.back().writer;
|
||||
LogFileNumberSize& log_file_number_size = impl->alive_log_files_.back();
|
||||
|
||||
assert(log_writer->get_log_number() == log_file_number_size.number);
|
||||
impl->mutex_.AssertHeld();
|
||||
s = impl->WriteToWAL(empty_batch, write_options, log_writer, &log_used,
|
||||
&log_size, log_file_number_size);
|
||||
s = impl->WriteToWAL(empty_batch, log_writer, &log_used, &log_size,
|
||||
Env::IO_TOTAL, log_file_number_size);
|
||||
if (s.ok()) {
|
||||
// Need to fsync, otherwise it might get lost after a power reset.
|
||||
s = impl->FlushWAL(write_options, false);
|
||||
s = impl->FlushWAL(false);
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::Open::BeforeSyncWAL", /*arg=*/&s);
|
||||
IOOptions opts;
|
||||
if (s.ok()) {
|
||||
s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = log_writer->file()->Sync(opts,
|
||||
impl->immutable_db_options_.use_fsync);
|
||||
s = log_writer->file()->Sync(impl->immutable_db_options_.use_fsync);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2107,8 +2084,7 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
impl->mutex_.Unlock();
|
||||
// NOTE: the work normally done in WrapUpCreateColumnFamilies will
|
||||
// be done separately below.
|
||||
s = impl->CreateColumnFamilyImpl(read_options, write_options,
|
||||
cf.options, cf.name, &handle);
|
||||
s = impl->CreateColumnFamilyImpl(cf.options, cf.name, &handle);
|
||||
impl->mutex_.Lock();
|
||||
if (s.ok()) {
|
||||
handles->push_back(handle);
|
||||
@@ -2160,7 +2136,7 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
// Persist RocksDB Options before scheduling the compaction.
|
||||
// The WriteOptionsFile() will release and lock the mutex internally.
|
||||
persist_options_status =
|
||||
impl->WriteOptionsFile(write_options, true /*db_mutex_already_held*/);
|
||||
impl->WriteOptionsFile(true /*db_mutex_already_held*/);
|
||||
*dbptr = impl;
|
||||
impl->opened_successfully_ = true;
|
||||
impl->DeleteObsoleteFiles();
|
||||
@@ -2260,17 +2236,12 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
impl);
|
||||
LogFlush(impl->immutable_db_options_.info_log);
|
||||
if (!impl->WALBufferIsEmpty()) {
|
||||
s = impl->FlushWAL(write_options, false);
|
||||
s = impl->FlushWAL(false);
|
||||
if (s.ok()) {
|
||||
// Sync is needed otherwise WAL buffered data might get lost after a
|
||||
// power reset.
|
||||
log::Writer* log_writer = impl->logs_.back().writer;
|
||||
IOOptions opts;
|
||||
s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (s.ok()) {
|
||||
s = log_writer->file()->Sync(opts,
|
||||
impl->immutable_db_options_.use_fsync);
|
||||
}
|
||||
s = log_writer->file()->Sync(impl->immutable_db_options_.use_fsync);
|
||||
}
|
||||
}
|
||||
if (s.ok() && !persist_options_status.ok()) {
|
||||
@@ -2287,8 +2258,7 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
s = impl->StartPeriodicTaskScheduler();
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = impl->RegisterRecordSeqnoTimeWorker(read_options, write_options,
|
||||
recovery_ctx.is_new_db_);
|
||||
s = impl->RegisterRecordSeqnoTimeWorker(recovery_ctx.is_new_db_);
|
||||
}
|
||||
impl->options_mutex_.Unlock();
|
||||
if (!s.ok()) {
|
||||
|
||||
+32
-51
@@ -437,10 +437,10 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
valid_batches += writer->batch_cnt;
|
||||
if (writer->ShouldWriteToMemtable()) {
|
||||
total_count += WriteBatchInternal::Count(writer->batch);
|
||||
total_byte_size = WriteBatchInternal::AppendedByteSize(
|
||||
total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
|
||||
parallel = parallel && !writer->batch->HasMerge();
|
||||
}
|
||||
total_byte_size = WriteBatchInternal::AppendedByteSize(
|
||||
total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
|
||||
if (writer->pre_release_callback) {
|
||||
pre_release_callback_cnt++;
|
||||
}
|
||||
@@ -620,9 +620,9 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
log_write_mutex_.Unlock();
|
||||
if (status.ok() && synced_wals.IsWalAddition()) {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
status = ApplyWALToManifest(read_options, write_options, &synced_wals);
|
||||
status = ApplyWALToManifest(read_options, &synced_wals);
|
||||
}
|
||||
|
||||
// Requesting sync with two_write_queues_ is expected to be very rare. We
|
||||
@@ -720,11 +720,11 @@ Status DBImpl::PipelinedWriteImpl(const WriteOptions& write_options,
|
||||
if (writer->ShouldWriteToMemtable()) {
|
||||
writer->sequence = next_sequence;
|
||||
size_t count = WriteBatchInternal::Count(writer->batch);
|
||||
total_byte_size = WriteBatchInternal::AppendedByteSize(
|
||||
total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
|
||||
next_sequence += count;
|
||||
total_count += count;
|
||||
}
|
||||
total_byte_size = WriteBatchInternal::AppendedByteSize(
|
||||
total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
|
||||
}
|
||||
}
|
||||
if (w.disable_wal) {
|
||||
@@ -783,9 +783,9 @@ Status DBImpl::PipelinedWriteImpl(const WriteOptions& write_options,
|
||||
}
|
||||
if (w.status.ok() && synced_wals.IsWalAddition()) {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
w.status = ApplyWALToManifest(read_options, write_options, &synced_wals);
|
||||
w.status = ApplyWALToManifest(read_options, &synced_wals);
|
||||
}
|
||||
write_thread_.ExitAsBatchGroupLeader(wal_write_group, w.status);
|
||||
}
|
||||
@@ -1318,9 +1318,9 @@ Status DBImpl::MergeBatch(const WriteThread::WriteGroup& write_group,
|
||||
// When two_write_queues_ is disabled, this function is called from the only
|
||||
// write thread. Otherwise this must be called holding log_write_mutex_.
|
||||
IOStatus DBImpl::WriteToWAL(const WriteBatch& merged_batch,
|
||||
const WriteOptions& write_options,
|
||||
log::Writer* log_writer, uint64_t* log_used,
|
||||
uint64_t* log_size,
|
||||
Env::IOPriority rate_limiter_priority,
|
||||
LogFileNumberSize& log_file_number_size) {
|
||||
assert(log_size != nullptr);
|
||||
|
||||
@@ -1343,11 +1343,12 @@ IOStatus DBImpl::WriteToWAL(const WriteBatch& merged_batch,
|
||||
log_write_mutex_.Lock();
|
||||
}
|
||||
IOStatus io_s = log_writer->MaybeAddUserDefinedTimestampSizeRecord(
|
||||
write_options, versions_->GetColumnFamiliesTimestampSizeForRecord());
|
||||
versions_->GetColumnFamiliesTimestampSizeForRecord(),
|
||||
rate_limiter_priority);
|
||||
if (!io_s.ok()) {
|
||||
return io_s;
|
||||
}
|
||||
io_s = log_writer->AddRecord(write_options, log_entry);
|
||||
io_s = log_writer->AddRecord(log_entry, rate_limiter_priority);
|
||||
|
||||
if (UNLIKELY(needs_locking)) {
|
||||
log_write_mutex_.Unlock();
|
||||
@@ -1390,13 +1391,9 @@ IOStatus DBImpl::WriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
WriteBatchInternal::SetSequence(merged_batch, sequence);
|
||||
|
||||
uint64_t log_size;
|
||||
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
WriteOptions write_options;
|
||||
write_options.rate_limiter_priority =
|
||||
write_group.leader->rate_limiter_priority;
|
||||
io_s = WriteToWAL(*merged_batch, write_options, log_writer, log_used,
|
||||
&log_size, log_file_number_size);
|
||||
io_s = WriteToWAL(*merged_batch, log_writer, log_used, &log_size,
|
||||
write_group.leader->rate_limiter_priority,
|
||||
log_file_number_size);
|
||||
if (to_be_cached_state) {
|
||||
cached_recoverable_state_ = *to_be_cached_state;
|
||||
cached_recoverable_state_empty_ = false;
|
||||
@@ -1423,17 +1420,10 @@ IOStatus DBImpl::WriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
log_write_mutex_.Lock();
|
||||
}
|
||||
|
||||
if (io_s.ok()) {
|
||||
for (auto& log : logs_) {
|
||||
IOOptions opts;
|
||||
io_s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (!io_s.ok()) {
|
||||
break;
|
||||
}
|
||||
io_s = log.writer->file()->Sync(opts, immutable_db_options_.use_fsync);
|
||||
if (!io_s.ok()) {
|
||||
break;
|
||||
}
|
||||
for (auto& log : logs_) {
|
||||
io_s = log.writer->file()->Sync(immutable_db_options_.use_fsync);
|
||||
if (!io_s.ok()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1506,13 +1496,9 @@ IOStatus DBImpl::ConcurrentWriteToWAL(
|
||||
assert(log_writer->get_log_number() == log_file_number_size.number);
|
||||
|
||||
uint64_t log_size;
|
||||
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
WriteOptions write_options;
|
||||
write_options.rate_limiter_priority =
|
||||
write_group.leader->rate_limiter_priority;
|
||||
io_s = WriteToWAL(*merged_batch, write_options, log_writer, log_used,
|
||||
&log_size, log_file_number_size);
|
||||
io_s = WriteToWAL(*merged_batch, log_writer, log_used, &log_size,
|
||||
write_group.leader->rate_limiter_priority,
|
||||
log_file_number_size);
|
||||
if (to_be_cached_state) {
|
||||
cached_recoverable_state_ = *to_be_cached_state;
|
||||
cached_recoverable_state_empty_ = false;
|
||||
@@ -1577,8 +1563,6 @@ Status DBImpl::WriteRecoverableState() {
|
||||
if (status.ok()) {
|
||||
cached_recoverable_state_.Clear();
|
||||
cached_recoverable_state_empty_ = true;
|
||||
} else {
|
||||
// FIXME: !ok status is untested
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -1855,12 +1839,11 @@ Status DBImpl::DelayWrite(uint64_t num_bytes, WriteThread& write_thread,
|
||||
delay = 0;
|
||||
}
|
||||
TEST_SYNC_POINT("DBImpl::DelayWrite:Start");
|
||||
start_time = immutable_db_options_.clock->NowMicros();
|
||||
|
||||
if (delay > 0) {
|
||||
if (write_options.no_slowdown) {
|
||||
return Status::Incomplete("Write stall");
|
||||
}
|
||||
start_time = immutable_db_options_.clock->NowMicros();
|
||||
TEST_SYNC_POINT("DBImpl::DelayWrite:Sleep");
|
||||
|
||||
// Notify write_thread about the stall so it can setup a barrier and
|
||||
@@ -2076,15 +2059,16 @@ Status DBImpl::ScheduleFlushes(WriteContext* context) {
|
||||
nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
|
||||
}
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::ScheduleFlushes:PreSwitchMemtable",
|
||||
nullptr);
|
||||
for (auto& cfd : cfds) {
|
||||
if (status.ok() && !cfd->mem()->IsEmpty()) {
|
||||
if (!cfd->mem()->IsEmpty()) {
|
||||
status = SwitchMemtable(cfd, context);
|
||||
}
|
||||
if (cfd->UnrefAndTryDelete()) {
|
||||
cfd = nullptr;
|
||||
}
|
||||
if (!status.ok()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (two_write_queues_) {
|
||||
@@ -2131,10 +2115,8 @@ void DBImpl::NotifyOnMemTableSealed(ColumnFamilyData* /*cfd*/,
|
||||
// two_write_queues_ is true (This is to simplify the reasoning.)
|
||||
Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
mutex_.AssertHeld();
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
log::Writer* new_log = nullptr;
|
||||
MemTable* new_mem = nullptr;
|
||||
IOStatus io_s;
|
||||
@@ -2181,8 +2163,8 @@ Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
if (creating_new_log) {
|
||||
// TODO: Write buffer size passed in should be max of all CF's instead
|
||||
// of mutable_cf_options.write_buffer_size.
|
||||
io_s = CreateWAL(write_options, new_log_number, recycle_log_number,
|
||||
preallocate_block_size, &new_log);
|
||||
io_s = CreateWAL(new_log_number, recycle_log_number, preallocate_block_size,
|
||||
&new_log);
|
||||
if (s.ok()) {
|
||||
s = io_s;
|
||||
}
|
||||
@@ -2219,7 +2201,7 @@ Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
// In recovery path, we force another try of writing WAL buffer.
|
||||
cur_log_writer->file()->reset_seen_error();
|
||||
}
|
||||
io_s = cur_log_writer->WriteBuffer(write_options);
|
||||
io_s = cur_log_writer->WriteBuffer();
|
||||
if (s.ok()) {
|
||||
s = io_s;
|
||||
}
|
||||
@@ -2287,8 +2269,7 @@ Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
VersionEdit wal_deletion;
|
||||
wal_deletion.DeleteWalsBefore(min_wal_number_to_keep);
|
||||
s = versions_->LogAndApplyToDefaultColumnFamily(
|
||||
read_options, write_options, &wal_deletion, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
read_options, &wal_deletion, &mutex_, directories_.GetDbDir());
|
||||
if (!s.ok() && versions_->io_status().IsIOError()) {
|
||||
s = error_handler_.SetBGError(versions_->io_status(),
|
||||
BackgroundErrorReason::kManifestWrite);
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
|
||||
#include "db/db_info_dumper.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
+32
-17
@@ -83,7 +83,8 @@ DBIter::DBIter(Env* _env, const ReadOptions& read_options,
|
||||
cfd_(cfd),
|
||||
timestamp_ub_(read_options.timestamp),
|
||||
timestamp_lb_(read_options.iter_start_ts),
|
||||
timestamp_size_(timestamp_ub_ ? timestamp_ub_->size() : 0) {
|
||||
timestamp_size_(timestamp_ub_ ? timestamp_ub_->size() : 0),
|
||||
auto_readahead_size_(read_options.auto_readahead_size) {
|
||||
RecordTick(statistics_, NO_ITERATOR_CREATED);
|
||||
if (pin_thru_lifetime_) {
|
||||
pinned_iters_mgr_.StartPinning();
|
||||
@@ -201,7 +202,6 @@ bool DBIter::SetBlobValueIfNeeded(const Slice& user_key,
|
||||
|
||||
// TODO: consider moving ReadOptions from ArenaWrappedDBIter to DBIter to
|
||||
// avoid having to copy options back and forth.
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
ReadOptions read_options;
|
||||
read_options.read_tier = read_tier_;
|
||||
read_options.fill_cache = fill_cache_;
|
||||
@@ -395,7 +395,9 @@ bool DBIter::FindNextUserEntryInternal(bool skipping_saved_key,
|
||||
case kTypeValue:
|
||||
case kTypeBlobIndex:
|
||||
case kTypeWideColumnEntity:
|
||||
if (!PrepareValue()) {
|
||||
if (!iter_.PrepareValue()) {
|
||||
assert(!iter_.status().ok());
|
||||
valid_ = false;
|
||||
return false;
|
||||
}
|
||||
if (timestamp_lb_) {
|
||||
@@ -426,7 +428,9 @@ bool DBIter::FindNextUserEntryInternal(bool skipping_saved_key,
|
||||
return true;
|
||||
break;
|
||||
case kTypeMerge:
|
||||
if (!PrepareValue()) {
|
||||
if (!iter_.PrepareValue()) {
|
||||
assert(!iter_.status().ok());
|
||||
valid_ = false;
|
||||
return false;
|
||||
}
|
||||
saved_key_.SetUserKey(
|
||||
@@ -571,7 +575,8 @@ bool DBIter::MergeValuesNewToOld() {
|
||||
iter_.Next();
|
||||
break;
|
||||
}
|
||||
if (!PrepareValue()) {
|
||||
if (!iter_.PrepareValue()) {
|
||||
valid_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -742,15 +747,22 @@ bool DBIter::ReverseToBackward() {
|
||||
// When current_entry_is_merged_ is true, iter_ may be positioned on the next
|
||||
// key, which may not exist or may have prefix different from current.
|
||||
// If that's the case, seek to saved_key_.
|
||||
if (current_entry_is_merged_ &&
|
||||
(!expect_total_order_inner_iter() || !iter_.Valid())) {
|
||||
//
|
||||
// In case of auto_readahead_size enabled, index_iter moves forward during
|
||||
// forward scan for block cache lookup and points to different block. If Prev
|
||||
// op is called, it needs to call SeekForPrev to point to right index_iter_ in
|
||||
// BlockBasedTableIterator. This only happens when direction is changed from
|
||||
// forward to backward.
|
||||
if ((current_entry_is_merged_ &&
|
||||
(!expect_total_order_inner_iter() || !iter_.Valid())) ||
|
||||
auto_readahead_size_) {
|
||||
IterKey last_key;
|
||||
// Using kMaxSequenceNumber and kValueTypeForSeek
|
||||
// (not kValueTypeForSeekForPrev) to seek to a key strictly smaller
|
||||
// than saved_key_.
|
||||
last_key.SetInternalKey(ParsedInternalKey(
|
||||
saved_key_.GetUserKey(), kMaxSequenceNumber, kValueTypeForSeek));
|
||||
if (!expect_total_order_inner_iter()) {
|
||||
if (!expect_total_order_inner_iter() || auto_readahead_size_) {
|
||||
iter_.SeekForPrev(last_key.GetInternalKey());
|
||||
} else {
|
||||
// Some iterators may not support SeekForPrev(), so we avoid using it
|
||||
@@ -897,7 +909,8 @@ bool DBIter::FindValueForCurrentKey() {
|
||||
return FindValueForCurrentKeyUsingSeek();
|
||||
}
|
||||
|
||||
if (!PrepareValue()) {
|
||||
if (!iter_.PrepareValue()) {
|
||||
valid_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1136,7 +1149,8 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!PrepareValue()) {
|
||||
if (!iter_.PrepareValue()) {
|
||||
valid_ = false;
|
||||
return false;
|
||||
}
|
||||
if (timestamp_size_ > 0) {
|
||||
@@ -1201,7 +1215,8 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
||||
ikey.type == kTypeDeletionWithTimestamp) {
|
||||
break;
|
||||
}
|
||||
if (!PrepareValue()) {
|
||||
if (!iter_.PrepareValue()) {
|
||||
valid_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1278,8 +1293,8 @@ bool DBIter::MergeWithNoBaseValue(const Slice& user_key) {
|
||||
const Status s = MergeHelper::TimedFullMerge(
|
||||
merge_operator_, user_key, MergeHelper::kNoBaseValue,
|
||||
merge_context_.GetOperands(), logger_, statistics_, clock_,
|
||||
/* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
|
||||
&saved_value_, &pinned_value_, &result_type);
|
||||
/* update_num_ops_stats */ true, &saved_value_, &pinned_value_,
|
||||
&result_type, /* op_failure_scope */ nullptr);
|
||||
return SetValueAndColumnsFromMergeResult(s, result_type);
|
||||
}
|
||||
|
||||
@@ -1291,8 +1306,8 @@ bool DBIter::MergeWithPlainBaseValue(const Slice& value,
|
||||
const Status s = MergeHelper::TimedFullMerge(
|
||||
merge_operator_, user_key, MergeHelper::kPlainBaseValue, value,
|
||||
merge_context_.GetOperands(), logger_, statistics_, clock_,
|
||||
/* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
|
||||
&saved_value_, &pinned_value_, &result_type);
|
||||
/* update_num_ops_stats */ true, &saved_value_, &pinned_value_,
|
||||
&result_type, /* op_failure_scope */ nullptr);
|
||||
return SetValueAndColumnsFromMergeResult(s, result_type);
|
||||
}
|
||||
|
||||
@@ -1304,8 +1319,8 @@ bool DBIter::MergeWithWideColumnBaseValue(const Slice& entity,
|
||||
const Status s = MergeHelper::TimedFullMerge(
|
||||
merge_operator_, user_key, MergeHelper::kWideBaseValue, entity,
|
||||
merge_context_.GetOperands(), logger_, statistics_, clock_,
|
||||
/* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
|
||||
&saved_value_, &pinned_value_, &result_type);
|
||||
/* update_num_ops_stats */ true, &saved_value_, &pinned_value_,
|
||||
&result_type, /* op_failure_scope */ nullptr);
|
||||
return SetValueAndColumnsFromMergeResult(s, result_type);
|
||||
}
|
||||
|
||||
|
||||
+1
-21
@@ -126,10 +126,6 @@ class DBIter final : public Iterator {
|
||||
void operator=(const DBIter&) = delete;
|
||||
|
||||
~DBIter() override {
|
||||
ThreadStatus::OperationType cur_op_type =
|
||||
ThreadStatusUtil::GetThreadOperation();
|
||||
ThreadStatusUtil::SetThreadOperation(
|
||||
ThreadStatus::OperationType::OP_UNKNOWN);
|
||||
// Release pinned data if any
|
||||
if (pinned_iters_mgr_.PinningEnabled()) {
|
||||
pinned_iters_mgr_.ReleasePinnedData();
|
||||
@@ -138,7 +134,6 @@ class DBIter final : public Iterator {
|
||||
ResetInternalKeysSkippedCounter();
|
||||
local_stats_.BumpGlobalStatistics(statistics_);
|
||||
iter_.DeleteIter(arena_mode_);
|
||||
ThreadStatusUtil::SetThreadOperation(cur_op_type);
|
||||
}
|
||||
void SetIter(InternalIterator* iter) {
|
||||
assert(iter_.iter() == nullptr);
|
||||
@@ -333,22 +328,6 @@ class DBIter final : public Iterator {
|
||||
bool MergeWithPlainBaseValue(const Slice& value, const Slice& user_key);
|
||||
bool MergeWithWideColumnBaseValue(const Slice& entity, const Slice& user_key);
|
||||
|
||||
bool PrepareValue() {
|
||||
if (!iter_.PrepareValue()) {
|
||||
assert(!iter_.status().ok());
|
||||
valid_ = false;
|
||||
return false;
|
||||
}
|
||||
// ikey_ could change as BlockBasedTableIterator does Block cache
|
||||
// lookup and index_iter_ could point to different block resulting
|
||||
// in ikey_ pointing to wrong key. So ikey_ needs to be updated in
|
||||
// case of Seek/Next calls to point to right key again.
|
||||
if (!ParseKey(&ikey_)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const SliceTransform* prefix_extractor_;
|
||||
Env* const env_;
|
||||
SystemClock* clock_;
|
||||
@@ -423,6 +402,7 @@ class DBIter final : public Iterator {
|
||||
const Slice* const timestamp_lb_;
|
||||
const size_t timestamp_size_;
|
||||
std::string saved_timestamp_;
|
||||
bool auto_readahead_size_;
|
||||
};
|
||||
|
||||
// Return a new iterator that converts internal keys (yielded by
|
||||
|
||||
+14
-34
@@ -50,9 +50,7 @@ struct Entry {
|
||||
bool visible = true;
|
||||
|
||||
bool operator<(const Entry& e) const {
|
||||
if (key != e.key) {
|
||||
return key < e.key;
|
||||
}
|
||||
if (key != e.key) return key < e.key;
|
||||
return std::tie(sequence, type) > std::tie(e.sequence, e.type);
|
||||
}
|
||||
};
|
||||
@@ -179,9 +177,7 @@ struct StressTestIterator : public InternalIterator {
|
||||
}
|
||||
|
||||
void SeekToFirst() override {
|
||||
if (MaybeFail()) {
|
||||
return;
|
||||
}
|
||||
if (MaybeFail()) return;
|
||||
MaybeMutate();
|
||||
|
||||
status_ = Status::OK();
|
||||
@@ -189,9 +185,7 @@ struct StressTestIterator : public InternalIterator {
|
||||
SkipForward();
|
||||
}
|
||||
void SeekToLast() override {
|
||||
if (MaybeFail()) {
|
||||
return;
|
||||
}
|
||||
if (MaybeFail()) return;
|
||||
MaybeMutate();
|
||||
|
||||
status_ = Status::OK();
|
||||
@@ -200,9 +194,7 @@ struct StressTestIterator : public InternalIterator {
|
||||
}
|
||||
|
||||
void Seek(const Slice& target) override {
|
||||
if (MaybeFail()) {
|
||||
return;
|
||||
}
|
||||
if (MaybeFail()) return;
|
||||
MaybeMutate();
|
||||
|
||||
status_ = Status::OK();
|
||||
@@ -214,9 +206,7 @@ struct StressTestIterator : public InternalIterator {
|
||||
SkipForward();
|
||||
}
|
||||
void SeekForPrev(const Slice& target) override {
|
||||
if (MaybeFail()) {
|
||||
return;
|
||||
}
|
||||
if (MaybeFail()) return;
|
||||
MaybeMutate();
|
||||
|
||||
status_ = Status::OK();
|
||||
@@ -231,18 +221,14 @@ struct StressTestIterator : public InternalIterator {
|
||||
|
||||
void Next() override {
|
||||
assert(Valid());
|
||||
if (MaybeFail()) {
|
||||
return;
|
||||
}
|
||||
if (MaybeFail()) return;
|
||||
MaybeMutate();
|
||||
++iter;
|
||||
SkipForward();
|
||||
}
|
||||
void Prev() override {
|
||||
assert(Valid());
|
||||
if (MaybeFail()) {
|
||||
return;
|
||||
}
|
||||
if (MaybeFail()) return;
|
||||
MaybeMutate();
|
||||
--iter;
|
||||
SkipBackward();
|
||||
@@ -332,9 +318,7 @@ struct ReferenceIterator {
|
||||
return false;
|
||||
}
|
||||
assert(e.sequence <= sequence);
|
||||
if (!e.visible) {
|
||||
continue;
|
||||
}
|
||||
if (!e.visible) continue;
|
||||
if (e.type == kTypeDeletion) {
|
||||
return false;
|
||||
}
|
||||
@@ -355,13 +339,11 @@ struct ReferenceIterator {
|
||||
break;
|
||||
}
|
||||
assert(e.sequence <= sequence);
|
||||
if (!e.visible) {
|
||||
continue;
|
||||
}
|
||||
if (!e.visible) continue;
|
||||
if (e.type == kTypeDeletion) {
|
||||
break;
|
||||
}
|
||||
operands.emplace_back(e.value);
|
||||
operands.push_back(e.value);
|
||||
if (e.type == kTypeValue) {
|
||||
break;
|
||||
}
|
||||
@@ -606,17 +588,15 @@ TEST_F(DBIteratorStressTest, StressTest) {
|
||||
|
||||
// Check that the key moved in the right direction.
|
||||
if (forward) {
|
||||
if (seek) {
|
||||
if (seek)
|
||||
ASSERT_GE(db_iter->key().ToString(), old_key);
|
||||
} else {
|
||||
else
|
||||
ASSERT_GT(db_iter->key().ToString(), old_key);
|
||||
}
|
||||
} else {
|
||||
if (seek) {
|
||||
if (seek)
|
||||
ASSERT_LE(db_iter->key().ToString(), old_key);
|
||||
} else {
|
||||
else
|
||||
ASSERT_LT(db_iter->key().ToString(), old_key);
|
||||
}
|
||||
}
|
||||
|
||||
if (ref_iter->Valid()) {
|
||||
|
||||
+3
-2
@@ -65,7 +65,8 @@ class TestIterator : public InternalIterator {
|
||||
size_t seq_num, bool update_iter = false) {
|
||||
valid_ = true;
|
||||
ParsedInternalKey internal_key(argkey, seq_num, type);
|
||||
data_.emplace_back(std::string(), argvalue);
|
||||
data_.push_back(
|
||||
std::pair<std::string, std::string>(std::string(), argvalue));
|
||||
AppendInternalKey(&data_.back().first, internal_key);
|
||||
if (update_iter && valid_ && cmp.Compare(data_.back().first, key()) < 0) {
|
||||
// insert a key smaller than current key
|
||||
@@ -2616,7 +2617,7 @@ class DBIterWithMergeIterTest : public testing::Test {
|
||||
child_iters.push_back(internal_iter2_);
|
||||
InternalKeyComparator icomp(BytewiseComparator());
|
||||
InternalIterator* merge_iter =
|
||||
NewMergingIterator(&icomp_, child_iters.data(), 2u);
|
||||
NewMergingIterator(&icomp_, &child_iters[0], 2u);
|
||||
|
||||
db_iter_.reset(NewDBIterator(
|
||||
env_, ro_, ImmutableOptions(options_), MutableCFOptions(options_),
|
||||
|
||||
@@ -86,7 +86,7 @@ TEST_F(DBIteratorBaseTest, APICallsWithPerfContext) {
|
||||
class DBIteratorTest : public DBIteratorBaseTest,
|
||||
public testing::WithParamInterface<bool> {
|
||||
public:
|
||||
DBIteratorTest() = default;
|
||||
DBIteratorTest() {}
|
||||
|
||||
Iterator* NewIterator(const ReadOptions& read_options,
|
||||
ColumnFamilyHandle* column_family = nullptr) {
|
||||
|
||||
@@ -658,7 +658,7 @@ TEST_F(DbKVChecksumWALToWriteBatchTest, WriteBatchChecksumHandoff) {
|
||||
Options options = CurrentOptions();
|
||||
Reopen(options);
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "key", "val"));
|
||||
std::string content;
|
||||
std::string content = "";
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::RecoverLogFiles:BeforeUpdateProtectionInfo:batch",
|
||||
[&](void* batch_ptr) {
|
||||
|
||||
@@ -1146,11 +1146,11 @@ TEST_F(DBOptionsTest, OffpeakTimes) {
|
||||
"1:0000000000000-2:000000000042", // Weird, but we can parse the int.
|
||||
};
|
||||
|
||||
for (const std::string& invalid_case : invalid_cases) {
|
||||
for (std::string invalid_case : invalid_cases) {
|
||||
options.daily_offpeak_time_utc = invalid_case;
|
||||
verify_invalid();
|
||||
}
|
||||
for (const std::string& valid_case : valid_cases) {
|
||||
for (std::string valid_case : valid_cases) {
|
||||
options.daily_offpeak_time_utc = valid_case;
|
||||
verify_valid();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "db/db_test_util.h"
|
||||
|
||||
@@ -22,7 +22,7 @@ class DBRangeDelTest : public DBTestBase {
|
||||
uint64_t uint64_key = static_cast<uint64_t>(key);
|
||||
std::string str;
|
||||
str.resize(8);
|
||||
memcpy(str.data(), static_cast<void*>(&uint64_key), 8);
|
||||
memcpy(&str[0], static_cast<void*>(&uint64_key), 8);
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -103,7 +103,7 @@ void DBSecondaryTestBase::CheckFileTypeCounts(const std::string& dir,
|
||||
ASSERT_OK(env_->GetChildren(dir, &filenames));
|
||||
|
||||
int log_cnt = 0, sst_cnt = 0, manifest_cnt = 0;
|
||||
for (const auto& file : filenames) {
|
||||
for (auto file : filenames) {
|
||||
uint64_t number;
|
||||
FileType type;
|
||||
if (ParseFileName(file, &number, &type)) {
|
||||
|
||||
+11
-14
@@ -27,8 +27,8 @@ class DBSSTTest : public DBTestBase {
|
||||
// A class which remembers the name of each flushed file.
|
||||
class FlushedFileCollector : public EventListener {
|
||||
public:
|
||||
FlushedFileCollector() = default;
|
||||
~FlushedFileCollector() override = default;
|
||||
FlushedFileCollector() {}
|
||||
~FlushedFileCollector() override {}
|
||||
|
||||
void OnFlushCompleted(DB* /*db*/, const FlushJobInfo& info) override {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
@@ -38,7 +38,7 @@ class FlushedFileCollector : public EventListener {
|
||||
std::vector<std::string> GetFlushedFiles() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::vector<std::string> result;
|
||||
for (const auto& fname : flushed_files_) {
|
||||
for (auto fname : flushed_files_) {
|
||||
result.push_back(fname);
|
||||
}
|
||||
return result;
|
||||
@@ -661,7 +661,7 @@ class DBSSTTestRateLimit : public DBSSTTest,
|
||||
public ::testing::WithParamInterface<bool> {
|
||||
public:
|
||||
DBSSTTestRateLimit() : DBSSTTest() {}
|
||||
~DBSSTTestRateLimit() override = default;
|
||||
~DBSSTTestRateLimit() override {}
|
||||
};
|
||||
|
||||
TEST_P(DBSSTTestRateLimit, RateLimitedDelete) {
|
||||
@@ -957,18 +957,15 @@ TEST_F(DBSSTTest, OpenDBWithExistingTrashAndObsoleteSstFile) {
|
||||
|
||||
// Add some trash files to the db directory so the DB can clean them up
|
||||
ASSERT_OK(env_->CreateDirIfMissing(dbname_));
|
||||
ASSERT_OK(
|
||||
WriteStringToFile(env_, "abc", dbname_ + "/" + "001.sst.trash", false));
|
||||
ASSERT_OK(
|
||||
WriteStringToFile(env_, "abc", dbname_ + "/" + "002.sst.trash", false));
|
||||
ASSERT_OK(
|
||||
WriteStringToFile(env_, "abc", dbname_ + "/" + "003.sst.trash", false));
|
||||
ASSERT_OK(WriteStringToFile(env_, "abc", dbname_ + "/" + "001.sst.trash"));
|
||||
ASSERT_OK(WriteStringToFile(env_, "abc", dbname_ + "/" + "002.sst.trash"));
|
||||
ASSERT_OK(WriteStringToFile(env_, "abc", dbname_ + "/" + "003.sst.trash"));
|
||||
// Manually add an obsolete sst file. Obsolete SST files are discovered and
|
||||
// deleted upon recovery.
|
||||
constexpr uint64_t kSstFileNumber = 100;
|
||||
const std::string kObsoleteSstFile =
|
||||
MakeTableFileName(dbname_, kSstFileNumber);
|
||||
ASSERT_OK(WriteStringToFile(env_, "abc", kObsoleteSstFile, false));
|
||||
ASSERT_OK(WriteStringToFile(env_, "abc", kObsoleteSstFile));
|
||||
|
||||
// Reopen the DB and verify that it deletes existing trash files and obsolete
|
||||
// SST files with rate limiting.
|
||||
@@ -1093,10 +1090,10 @@ TEST_F(DBSSTTest, DestroyDBWithRateLimitedDelete) {
|
||||
int num_wal_files = 0;
|
||||
std::vector<std::string> db_files;
|
||||
ASSERT_OK(env_->GetChildren(dbname_, &db_files));
|
||||
for (const std::string& f : db_files) {
|
||||
if (f.substr(f.find_last_of('.') + 1) == "sst") {
|
||||
for (std::string f : db_files) {
|
||||
if (f.substr(f.find_last_of(".") + 1) == "sst") {
|
||||
num_sst_files++;
|
||||
} else if (f.substr(f.find_last_of('.') + 1) == "log") {
|
||||
} else if (f.substr(f.find_last_of(".") + 1) == "log") {
|
||||
num_wal_files++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,9 @@
|
||||
#include <string>
|
||||
|
||||
#include "db/db_test_util.h"
|
||||
#include "db/write_batch_internal.h"
|
||||
#include "monitoring/thread_status_util.h"
|
||||
#include "port/stack_trace.h"
|
||||
#include "rocksdb/statistics.h"
|
||||
#include "rocksdb/utilities/transaction_db.h"
|
||||
#include "util/random.h"
|
||||
|
||||
namespace ROCKSDB_NAMESPACE {
|
||||
@@ -285,78 +283,6 @@ TEST_F(DBStatisticsTest, BlockChecksumStats) {
|
||||
options.statistics->getTickerCount(BLOCK_CHECKSUM_MISMATCH_COUNT));
|
||||
}
|
||||
|
||||
TEST_F(DBStatisticsTest, BytesWrittenStats) {
|
||||
Options options = CurrentOptions();
|
||||
options.statistics = ROCKSDB_NAMESPACE::CreateDBStatistics();
|
||||
options.statistics->set_stats_level(StatsLevel::kExceptHistogramOrTimers);
|
||||
Reopen(options);
|
||||
|
||||
EXPECT_EQ(0, options.statistics->getAndResetTickerCount(WAL_FILE_BYTES));
|
||||
EXPECT_EQ(0, options.statistics->getAndResetTickerCount(BYTES_WRITTEN));
|
||||
|
||||
const int kNumKeysWritten = 100;
|
||||
|
||||
// Scenario 0: Not using transactions.
|
||||
// This will write to WAL and memtable directly.
|
||||
ASSERT_OK(options.statistics->Reset());
|
||||
|
||||
for (int i = 0; i < kNumKeysWritten; ++i) {
|
||||
ASSERT_OK(Put(Key(i), "val"));
|
||||
}
|
||||
|
||||
EXPECT_EQ(options.statistics->getAndResetTickerCount(WAL_FILE_BYTES),
|
||||
options.statistics->getAndResetTickerCount(BYTES_WRITTEN));
|
||||
|
||||
// Scenario 1: Using transactions.
|
||||
// This should not double count BYTES_WRITTEN (issue #12061).
|
||||
for (bool enable_pipelined_write : {false, true}) {
|
||||
ASSERT_OK(options.statistics->Reset());
|
||||
|
||||
// Destroy the DB to recreate as a TransactionDB.
|
||||
Destroy(options, true);
|
||||
|
||||
// Create a TransactionDB.
|
||||
TransactionDB* txn_db = nullptr;
|
||||
TransactionDBOptions txn_db_opts;
|
||||
txn_db_opts.write_policy = TxnDBWritePolicy::WRITE_COMMITTED;
|
||||
options.enable_pipelined_write = enable_pipelined_write;
|
||||
ASSERT_OK(TransactionDB::Open(options, txn_db_opts, dbname_, &txn_db));
|
||||
ASSERT_NE(txn_db, nullptr);
|
||||
db_ = txn_db->GetBaseDB();
|
||||
|
||||
WriteOptions wopts;
|
||||
TransactionOptions txn_opts;
|
||||
Transaction* txn = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
|
||||
ASSERT_NE(txn, nullptr);
|
||||
ASSERT_OK(txn->SetName("txn1"));
|
||||
|
||||
for (int i = 0; i < kNumKeysWritten; ++i) {
|
||||
ASSERT_OK(txn->Put(Key(i), "val"));
|
||||
}
|
||||
|
||||
// Prepare() writes to WAL, but not to memtable. (WriteCommitted)
|
||||
ASSERT_OK(txn->Prepare());
|
||||
EXPECT_NE(0, options.statistics->getTickerCount(WAL_FILE_BYTES));
|
||||
// BYTES_WRITTEN would have been non-zero previously (issue #12061).
|
||||
EXPECT_EQ(0, options.statistics->getTickerCount(BYTES_WRITTEN));
|
||||
|
||||
// Commit() writes to memtable and also a commit marker to WAL.
|
||||
ASSERT_OK(txn->Commit());
|
||||
delete txn;
|
||||
|
||||
// The WAL has an extra header of size `kHeader` written to it,
|
||||
// as we are writing twice to it (first during Prepare, second during
|
||||
// Commit).
|
||||
EXPECT_EQ(options.statistics->getAndResetTickerCount(WAL_FILE_BYTES),
|
||||
options.statistics->getAndResetTickerCount(BYTES_WRITTEN) +
|
||||
WriteBatchInternal::kHeader);
|
||||
|
||||
// Cleanup
|
||||
db_ = nullptr;
|
||||
delete txn_db;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "table/table_properties_internal.h"
|
||||
#include "test_util/testharness.h"
|
||||
#include "test_util/testutil.h"
|
||||
#include "util/atomic.h"
|
||||
#include "util/random.h"
|
||||
|
||||
|
||||
@@ -246,7 +245,7 @@ DBTablePropertiesTest::TestGetPropertiesOfTablesInRange(
|
||||
// run the query
|
||||
TablePropertiesCollection props;
|
||||
EXPECT_OK(db_->GetPropertiesOfTablesInRange(
|
||||
db_->DefaultColumnFamily(), ranges.data(), ranges.size(), &props));
|
||||
db_->DefaultColumnFamily(), &ranges[0], ranges.size(), &props));
|
||||
|
||||
// Make sure that we've received properties for those and for those files
|
||||
// only which fall within requested ranges
|
||||
@@ -363,7 +362,7 @@ TEST_F(DBTablePropertiesTest, GetPropertiesOfTablesInRange) {
|
||||
std::vector<Range> ranges;
|
||||
auto it = random_keys.begin();
|
||||
while (it != random_keys.end()) {
|
||||
ranges.emplace_back(*it, *(it + 1));
|
||||
ranges.push_back(Range(*it, *(it + 1)));
|
||||
it += 2;
|
||||
}
|
||||
|
||||
@@ -418,71 +417,6 @@ TEST_F(DBTablePropertiesTest, GetDbIdentifiersProperty) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBTablePropertiesTest, FactoryReturnsNull) {
|
||||
struct JunkTablePropertiesCollector : public TablePropertiesCollector {
|
||||
const char* Name() const override { return "JunkTablePropertiesCollector"; }
|
||||
Status Finish(UserCollectedProperties* properties) override {
|
||||
properties->insert({"Junk", "Junk"});
|
||||
return Status::OK();
|
||||
}
|
||||
UserCollectedProperties GetReadableProperties() const override {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
// Alternates between putting a "Junk" property and using `nullptr` to
|
||||
// opt out.
|
||||
static RelaxedAtomic<int> count{0};
|
||||
struct SometimesTablePropertiesCollectorFactory
|
||||
: public TablePropertiesCollectorFactory {
|
||||
const char* Name() const override {
|
||||
return "SometimesTablePropertiesCollectorFactory";
|
||||
}
|
||||
TablePropertiesCollector* CreateTablePropertiesCollector(
|
||||
TablePropertiesCollectorFactory::Context /*context*/) override {
|
||||
if (count.FetchAddRelaxed(1) & 1) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return new JunkTablePropertiesCollector();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Options options = CurrentOptions();
|
||||
options.table_properties_collector_factories.emplace_back(
|
||||
std::make_shared<SometimesTablePropertiesCollectorFactory>());
|
||||
// For plain table
|
||||
options.prefix_extractor.reset(NewFixedPrefixTransform(4));
|
||||
for (const std::shared_ptr<TableFactory>& tf :
|
||||
{options.table_factory,
|
||||
std::shared_ptr<TableFactory>(NewPlainTableFactory({}))}) {
|
||||
SCOPED_TRACE("Table factory = " + std::string(tf->Name()));
|
||||
options.table_factory = tf;
|
||||
|
||||
DestroyAndReopen(options);
|
||||
|
||||
ASSERT_OK(Put("key0", "value1"));
|
||||
ASSERT_OK(Flush());
|
||||
ASSERT_OK(Put("key0", "value2"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
TablePropertiesCollection props;
|
||||
ASSERT_OK(db_->GetPropertiesOfAllTables(&props));
|
||||
int no_junk_count = 0;
|
||||
int junk_count = 0;
|
||||
for (const auto& item : props) {
|
||||
if (item.second->user_collected_properties.find("Junk") !=
|
||||
item.second->user_collected_properties.end()) {
|
||||
junk_count++;
|
||||
} else {
|
||||
no_junk_count++;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(1, no_junk_count);
|
||||
EXPECT_EQ(1, junk_count);
|
||||
}
|
||||
}
|
||||
|
||||
class DBTableHostnamePropertyTest
|
||||
: public DBTestBase,
|
||||
public ::testing::WithParamInterface<std::tuple<int, std::string>> {
|
||||
|
||||
@@ -360,9 +360,8 @@ TEST_P(DBTestTailingIterator, TailingIteratorDeletes) {
|
||||
|
||||
// make sure we can read all new records using the existing iterator
|
||||
int count = 0;
|
||||
for (; iter->Valid(); iter->Next(), ++count) {
|
||||
for (; iter->Valid(); iter->Next(), ++count)
|
||||
;
|
||||
}
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_EQ(count, num_records);
|
||||
}
|
||||
|
||||
+27
-39
@@ -678,8 +678,8 @@ TEST_F(DBTest, ReadFromPersistedTier) {
|
||||
multiget_cfs.push_back(handles_[1]);
|
||||
multiget_cfs.push_back(handles_[1]);
|
||||
std::vector<Slice> multiget_keys;
|
||||
multiget_keys.emplace_back("foo");
|
||||
multiget_keys.emplace_back("bar");
|
||||
multiget_keys.push_back("foo");
|
||||
multiget_keys.push_back("bar");
|
||||
std::vector<std::string> multiget_values;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
bool batched = i == 0;
|
||||
@@ -714,7 +714,7 @@ TEST_F(DBTest, ReadFromPersistedTier) {
|
||||
|
||||
// Expect same result in multiget
|
||||
multiget_cfs.push_back(handles_[1]);
|
||||
multiget_keys.emplace_back("rocksdb");
|
||||
multiget_keys.push_back("rocksdb");
|
||||
multiget_values.clear();
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
@@ -2701,7 +2701,7 @@ TEST_F(DBTest, PurgeInfoLogs) {
|
||||
ASSERT_OK(env_->GetChildren(
|
||||
options.db_log_dir.empty() ? dbname_ : options.db_log_dir, &files));
|
||||
int info_log_count = 0;
|
||||
for (const std::string& file : files) {
|
||||
for (std::string file : files) {
|
||||
if (file.find("LOG") != std::string::npos) {
|
||||
info_log_count++;
|
||||
}
|
||||
@@ -2719,7 +2719,7 @@ TEST_F(DBTest, PurgeInfoLogs) {
|
||||
if (mode == 1) {
|
||||
// Cleaning up
|
||||
ASSERT_OK(env_->GetChildren(options.db_log_dir, &files));
|
||||
for (const std::string& file : files) {
|
||||
for (std::string file : files) {
|
||||
ASSERT_OK(env_->DeleteFile(options.db_log_dir + "/" + file));
|
||||
}
|
||||
ASSERT_OK(env_->DeleteDir(options.db_log_dir));
|
||||
@@ -2879,9 +2879,7 @@ class MultiThreadedDBTest
|
||||
};
|
||||
|
||||
TEST_P(MultiThreadedDBTest, MultiThreaded) {
|
||||
if (option_config_ == kPipelinedWrite) {
|
||||
return;
|
||||
}
|
||||
if (option_config_ == kPipelinedWrite) return;
|
||||
anon::OptionsOverride options_override;
|
||||
options_override.skip_policy = kSkipNoSnapshot;
|
||||
Options options = CurrentOptions(options_override);
|
||||
@@ -2980,7 +2978,7 @@ TEST_F(DBTest, GroupCommitTest) {
|
||||
|
||||
Iterator* itr = db_->NewIterator(ReadOptions());
|
||||
itr->SeekToFirst();
|
||||
for (const auto& x : expected_db) {
|
||||
for (auto x : expected_db) {
|
||||
ASSERT_TRUE(itr->Valid());
|
||||
ASSERT_EQ(itr->key().ToString(), x);
|
||||
ASSERT_EQ(itr->value().ToString(), x);
|
||||
@@ -3304,9 +3302,9 @@ class ModelDB : public DB {
|
||||
return Status::NotSupported("Not supported operation.");
|
||||
}
|
||||
|
||||
void EnableManualCompaction() override {}
|
||||
void EnableManualCompaction() override { return; }
|
||||
|
||||
void DisableManualCompaction() override {}
|
||||
void DisableManualCompaction() override { return; }
|
||||
|
||||
virtual Status WaitForCompact(
|
||||
const WaitForCompactOptions& /* wait_for_compact_options */) override {
|
||||
@@ -3427,9 +3425,7 @@ class ModelDB : public DB {
|
||||
ModelIter(const KVMap* map, bool owned)
|
||||
: map_(map), owned_(owned), iter_(map_->end()) {}
|
||||
~ModelIter() override {
|
||||
if (owned_) {
|
||||
delete map_;
|
||||
}
|
||||
if (owned_) delete map_;
|
||||
}
|
||||
bool Valid() const override { return iter_ != map_->end(); }
|
||||
void SeekToFirst() override { iter_ = map_->begin(); }
|
||||
@@ -3467,7 +3463,7 @@ class ModelDB : public DB {
|
||||
};
|
||||
const Options options_;
|
||||
KVMap map_;
|
||||
std::string name_;
|
||||
std::string name_ = "";
|
||||
};
|
||||
|
||||
#if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
|
||||
@@ -3615,12 +3611,8 @@ TEST_P(DBTestRandomized, Randomized) {
|
||||
// Save a snapshot from each DB this time that we'll use next
|
||||
// time we compare things, to make sure the current state is
|
||||
// preserved with the snapshot
|
||||
if (model_snap != nullptr) {
|
||||
model.ReleaseSnapshot(model_snap);
|
||||
}
|
||||
if (db_snap != nullptr) {
|
||||
db_->ReleaseSnapshot(db_snap);
|
||||
}
|
||||
if (model_snap != nullptr) model.ReleaseSnapshot(model_snap);
|
||||
if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap);
|
||||
|
||||
Reopen(options);
|
||||
ASSERT_TRUE(CompareIterators(step, &model, db_, nullptr, nullptr));
|
||||
@@ -3629,12 +3621,8 @@ TEST_P(DBTestRandomized, Randomized) {
|
||||
db_snap = db_->GetSnapshot();
|
||||
}
|
||||
}
|
||||
if (model_snap != nullptr) {
|
||||
model.ReleaseSnapshot(model_snap);
|
||||
}
|
||||
if (db_snap != nullptr) {
|
||||
db_->ReleaseSnapshot(db_snap);
|
||||
}
|
||||
if (model_snap != nullptr) model.ReleaseSnapshot(model_snap);
|
||||
if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap);
|
||||
}
|
||||
#endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
|
||||
|
||||
@@ -4261,9 +4249,9 @@ TEST_F(DBTest, DISABLED_RateLimitingTest) {
|
||||
// (e.g, RateLimiter::GetTotalPendingRequests())
|
||||
class MockedRateLimiterWithNoOptionalAPIImpl : public RateLimiter {
|
||||
public:
|
||||
MockedRateLimiterWithNoOptionalAPIImpl() = default;
|
||||
MockedRateLimiterWithNoOptionalAPIImpl() {}
|
||||
|
||||
~MockedRateLimiterWithNoOptionalAPIImpl() override = default;
|
||||
~MockedRateLimiterWithNoOptionalAPIImpl() override {}
|
||||
|
||||
void SetBytesPerSecond(int64_t bytes_per_second) override {
|
||||
(void)bytes_per_second;
|
||||
@@ -4665,7 +4653,7 @@ void VerifyOperationCount(Env* env, ThreadStatus::OperationType op_type,
|
||||
int op_count = 0;
|
||||
std::vector<ThreadStatus> thread_list;
|
||||
ASSERT_OK(env->GetThreadList(&thread_list));
|
||||
for (const auto& thread : thread_list) {
|
||||
for (auto thread : thread_list) {
|
||||
if (thread.operation_type == op_type) {
|
||||
op_count++;
|
||||
}
|
||||
@@ -4705,7 +4693,7 @@ TEST_F(DBTest, GetThreadStatus) {
|
||||
s = env_->GetThreadList(&thread_list);
|
||||
ASSERT_OK(s);
|
||||
memset(thread_type_counts, 0, sizeof(thread_type_counts));
|
||||
for (const auto& thread : thread_list) {
|
||||
for (auto thread : thread_list) {
|
||||
ASSERT_LT(thread.thread_type, ThreadStatus::NUM_THREAD_TYPES);
|
||||
thread_type_counts[thread.thread_type]++;
|
||||
}
|
||||
@@ -4986,7 +4974,7 @@ TEST_P(DBTestWithParam, PreShutdownMultipleCompaction) {
|
||||
}
|
||||
|
||||
ASSERT_OK(env_->GetThreadList(&thread_list));
|
||||
for (const auto& thread : thread_list) {
|
||||
for (auto thread : thread_list) {
|
||||
operation_count[thread.operation_type]++;
|
||||
}
|
||||
|
||||
@@ -5011,7 +4999,7 @@ TEST_P(DBTestWithParam, PreShutdownMultipleCompaction) {
|
||||
operation_count[i] = 0;
|
||||
}
|
||||
ASSERT_OK(env_->GetThreadList(&thread_list));
|
||||
for (const auto& thread : thread_list) {
|
||||
for (auto thread : thread_list) {
|
||||
operation_count[thread.operation_type]++;
|
||||
}
|
||||
ASSERT_EQ(operation_count[ThreadStatus::OP_COMPACTION], 0);
|
||||
@@ -5073,7 +5061,7 @@ TEST_P(DBTestWithParam, PreShutdownCompactionMiddle) {
|
||||
}
|
||||
|
||||
ASSERT_OK(env_->GetThreadList(&thread_list));
|
||||
for (const auto& thread : thread_list) {
|
||||
for (auto thread : thread_list) {
|
||||
operation_count[thread.operation_type]++;
|
||||
}
|
||||
|
||||
@@ -5098,7 +5086,7 @@ TEST_P(DBTestWithParam, PreShutdownCompactionMiddle) {
|
||||
operation_count[i] = 0;
|
||||
}
|
||||
ASSERT_OK(env_->GetThreadList(&thread_list));
|
||||
for (const auto& thread : thread_list) {
|
||||
for (auto thread : thread_list) {
|
||||
operation_count[thread.operation_type]++;
|
||||
}
|
||||
ASSERT_EQ(operation_count[ThreadStatus::OP_COMPACTION], 0);
|
||||
@@ -5183,7 +5171,7 @@ TEST_F(DBTest, DynamicLevelCompressionPerLevel) {
|
||||
}));
|
||||
ColumnFamilyMetaData cf_meta;
|
||||
db_->GetColumnFamilyMetaData(&cf_meta);
|
||||
for (const auto& file : cf_meta.levels[4].files) {
|
||||
for (auto file : cf_meta.levels[4].files) {
|
||||
listener->SetExpectedFileName(dbname_ + file.name);
|
||||
ASSERT_OK(dbfull()->DeleteFile(file.name));
|
||||
}
|
||||
@@ -5681,7 +5669,7 @@ TEST_F(DBTest, FileCreationRandomFailure) {
|
||||
|
||||
std::vector<std::string> values;
|
||||
for (int i = 0; i < kTestSize; ++i) {
|
||||
values.emplace_back("NOT_FOUND");
|
||||
values.push_back("NOT_FOUND");
|
||||
}
|
||||
for (int j = 0; j < kTotalIteration; ++j) {
|
||||
if (j == kRandomFailureTest) {
|
||||
@@ -7127,7 +7115,7 @@ TEST_F(DBTest, ReusePinnableSlice) {
|
||||
|
||||
{
|
||||
std::vector<Slice> multiget_keys;
|
||||
multiget_keys.emplace_back("foo");
|
||||
multiget_keys.push_back("foo");
|
||||
std::vector<PinnableSlice> multiget_values(1);
|
||||
std::vector<Status> statuses({Status::NotFound()});
|
||||
ReadOptions ropt;
|
||||
@@ -7154,7 +7142,7 @@ TEST_F(DBTest, ReusePinnableSlice) {
|
||||
std::vector<ColumnFamilyHandle*> multiget_cfs;
|
||||
multiget_cfs.push_back(dbfull()->DefaultColumnFamily());
|
||||
std::vector<Slice> multiget_keys;
|
||||
multiget_keys.emplace_back("foo");
|
||||
multiget_keys.push_back("foo");
|
||||
std::vector<PinnableSlice> multiget_values(1);
|
||||
std::vector<Status> statuses({Status::NotFound()});
|
||||
ReadOptions ropt;
|
||||
|
||||
+41
-61
@@ -80,8 +80,9 @@ TEST_F(DBTest2, OpenForReadOnlyWithColumnFamilies) {
|
||||
|
||||
ColumnFamilyOptions cf_options(options);
|
||||
std::vector<ColumnFamilyDescriptor> column_families;
|
||||
column_families.emplace_back(kDefaultColumnFamilyName, cf_options);
|
||||
column_families.emplace_back("goku", cf_options);
|
||||
column_families.push_back(
|
||||
ColumnFamilyDescriptor(kDefaultColumnFamilyName, cf_options));
|
||||
column_families.push_back(ColumnFamilyDescriptor("goku", cf_options));
|
||||
std::vector<ColumnFamilyHandle*> handles;
|
||||
// OpenForReadOnly should fail but will create <dbname> in the file system
|
||||
ASSERT_NOK(
|
||||
@@ -747,7 +748,7 @@ TEST_F(DBTest2, WalFilterTest) {
|
||||
// we expect all records to be processed
|
||||
for (size_t i = 0; i < batch_keys.size(); i++) {
|
||||
for (size_t j = 0; j < batch_keys[i].size(); j++) {
|
||||
keys_must_exist.emplace_back(batch_keys[i][j]);
|
||||
keys_must_exist.push_back(Slice(batch_keys[i][j]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -761,9 +762,9 @@ TEST_F(DBTest2, WalFilterTest) {
|
||||
for (size_t i = 0; i < batch_keys.size(); i++) {
|
||||
for (size_t j = 0; j < batch_keys[i].size(); j++) {
|
||||
if (i == apply_option_for_record_index) {
|
||||
keys_must_not_exist.emplace_back(batch_keys[i][j]);
|
||||
keys_must_not_exist.push_back(Slice(batch_keys[i][j]));
|
||||
} else {
|
||||
keys_must_exist.emplace_back(batch_keys[i][j]);
|
||||
keys_must_exist.push_back(Slice(batch_keys[i][j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -779,9 +780,9 @@ TEST_F(DBTest2, WalFilterTest) {
|
||||
for (size_t i = 0; i < batch_keys.size(); i++) {
|
||||
for (size_t j = 0; j < batch_keys[i].size(); j++) {
|
||||
if (i >= apply_option_for_record_index) {
|
||||
keys_must_not_exist.emplace_back(batch_keys[i][j]);
|
||||
keys_must_not_exist.push_back(Slice(batch_keys[i][j]));
|
||||
} else {
|
||||
keys_must_exist.emplace_back(batch_keys[i][j]);
|
||||
keys_must_exist.push_back(Slice(batch_keys[i][j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -921,9 +922,9 @@ TEST_F(DBTest2, WalFilterTestWithChangeBatch) {
|
||||
for (size_t i = 0; i < batch_keys.size(); i++) {
|
||||
for (size_t j = 0; j < batch_keys[i].size(); j++) {
|
||||
if (i >= change_records_from_index && j >= num_keys_to_add_in_new_batch) {
|
||||
keys_must_not_exist.emplace_back(batch_keys[i][j]);
|
||||
keys_must_not_exist.push_back(Slice(batch_keys[i][j]));
|
||||
} else {
|
||||
keys_must_exist.emplace_back(batch_keys[i][j]);
|
||||
keys_must_exist.push_back(Slice(batch_keys[i][j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1011,7 +1012,7 @@ TEST_F(DBTest2, WalFilterTestWithChangeBatchExtraKeys) {
|
||||
|
||||
for (size_t i = 0; i < batch_keys.size(); i++) {
|
||||
for (size_t j = 0; j < batch_keys[i].size(); j++) {
|
||||
keys_must_exist.emplace_back(batch_keys[i][j]);
|
||||
keys_must_exist.push_back(Slice(batch_keys[i][j]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2349,7 +2350,7 @@ class MockPersistentCache : public PersistentCache {
|
||||
"GetUniqueIdFromFile:FS_IOC_GETVERSION", UniqueIdCallback);
|
||||
}
|
||||
|
||||
~MockPersistentCache() override = default;
|
||||
~MockPersistentCache() override {}
|
||||
|
||||
PersistentCache::StatsType Stats() override {
|
||||
return PersistentCache::StatsType();
|
||||
@@ -3035,7 +3036,7 @@ TEST_F(DBTest2, PausingManualCompaction1) {
|
||||
// Remember file name before compaction is triggered
|
||||
std::vector<LiveFileMetaData> files_meta;
|
||||
dbfull()->GetLiveFilesMetaData(&files_meta);
|
||||
for (const auto& file : files_meta) {
|
||||
for (auto file : files_meta) {
|
||||
files_before_compact.push_back(file.name);
|
||||
}
|
||||
|
||||
@@ -3050,7 +3051,7 @@ TEST_F(DBTest2, PausingManualCompaction1) {
|
||||
// Get file names after compaction is stopped
|
||||
files_meta.clear();
|
||||
dbfull()->GetLiveFilesMetaData(&files_meta);
|
||||
for (const auto& file : files_meta) {
|
||||
for (auto file : files_meta) {
|
||||
files_after_compact.push_back(file.name);
|
||||
}
|
||||
|
||||
@@ -3070,7 +3071,7 @@ TEST_F(DBTest2, PausingManualCompaction1) {
|
||||
files_meta.clear();
|
||||
files_after_compact.clear();
|
||||
dbfull()->GetLiveFilesMetaData(&files_meta);
|
||||
for (const auto& file : files_meta) {
|
||||
for (auto file : files_meta) {
|
||||
files_after_compact.push_back(file.name);
|
||||
}
|
||||
|
||||
@@ -3860,17 +3861,6 @@ TEST_F(DBTest2, LowPriWrite) {
|
||||
int64_t* rate_bytes_per_sec = static_cast<int64_t*>(arg);
|
||||
ASSERT_EQ(1024 * 1024, *rate_bytes_per_sec);
|
||||
});
|
||||
|
||||
// Make a trivial L5 for L0 to compact into. L6 will be large so debt ratio
|
||||
// will not cause compaction pressure.
|
||||
Random rnd(301);
|
||||
ASSERT_OK(Put("", rnd.RandomString(102400)));
|
||||
ASSERT_OK(Flush());
|
||||
MoveFilesToLevel(6);
|
||||
ASSERT_OK(Put("", ""));
|
||||
ASSERT_OK(Flush());
|
||||
MoveFilesToLevel(5);
|
||||
|
||||
// Block compaction
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->LoadDependency({
|
||||
{"DBTest.LowPriWrite:0", "DBImpl::BGWorkCompaction"},
|
||||
@@ -3947,15 +3937,6 @@ TEST_F(DBTest2, RateLimitedCompactionReads) {
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(bbto));
|
||||
DestroyAndReopen(options);
|
||||
|
||||
// To precisely control when to start bg compaction for excluding previous
|
||||
// rate-limited bytes of flush read for table verification
|
||||
std::shared_ptr<test::SleepingBackgroundTask> sleeping_task(
|
||||
new test::SleepingBackgroundTask());
|
||||
env_->SetBackgroundThreads(1, Env::LOW);
|
||||
env_->Schedule(&test::SleepingBackgroundTask::DoSleepTask,
|
||||
sleeping_task.get(), Env::Priority::LOW);
|
||||
sleeping_task->WaitUntilSleeping();
|
||||
|
||||
for (int i = 0; i < kNumL0Files; ++i) {
|
||||
for (int j = 0; j <= kNumKeysPerFile; ++j) {
|
||||
ASSERT_OK(Put(Key(j), DummyString(kBytesPerKey)));
|
||||
@@ -3965,20 +3946,13 @@ TEST_F(DBTest2, RateLimitedCompactionReads) {
|
||||
ASSERT_EQ(i + 1, NumTableFilesAtLevel(0));
|
||||
}
|
||||
}
|
||||
|
||||
size_t rate_limited_bytes_start_bytes =
|
||||
options.rate_limiter->GetTotalBytesThrough(Env::IO_TOTAL);
|
||||
|
||||
sleeping_task->WakeUp();
|
||||
sleeping_task->WaitUntilDone();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||
|
||||
// should be slightly above 512KB due to non-data blocks read. Arbitrarily
|
||||
// chose 1MB as the upper bound on the total bytes read.
|
||||
size_t rate_limited_bytes =
|
||||
static_cast<size_t>(
|
||||
options.rate_limiter->GetTotalBytesThrough(Env::IO_TOTAL)) -
|
||||
rate_limited_bytes_start_bytes;
|
||||
size_t rate_limited_bytes = static_cast<size_t>(
|
||||
options.rate_limiter->GetTotalBytesThrough(Env::IO_TOTAL));
|
||||
// The charges can exist for `IO_LOW` and `IO_USER` priorities.
|
||||
size_t rate_limited_bytes_by_pri =
|
||||
options.rate_limiter->GetTotalBytesThrough(Env::IO_LOW) +
|
||||
@@ -4239,8 +4213,8 @@ TEST_F(DBTest2, TestNumPread) {
|
||||
|
||||
class TraceExecutionResultHandler : public TraceRecordResult::Handler {
|
||||
public:
|
||||
TraceExecutionResultHandler() = default;
|
||||
~TraceExecutionResultHandler() override = default;
|
||||
TraceExecutionResultHandler() {}
|
||||
~TraceExecutionResultHandler() override {}
|
||||
|
||||
virtual Status Handle(const StatusOnlyTraceExecutionResult& result) override {
|
||||
if (result.GetStartTimestamp() > result.GetEndTimestamp()) {
|
||||
@@ -4425,8 +4399,9 @@ TEST_F(DBTest2, TraceAndReplay) {
|
||||
std::vector<ColumnFamilyDescriptor> column_families;
|
||||
ColumnFamilyOptions cf_options;
|
||||
cf_options.merge_operator = MergeOperators::CreatePutOperator();
|
||||
column_families.emplace_back("default", cf_options);
|
||||
column_families.emplace_back("pikachu", ColumnFamilyOptions());
|
||||
column_families.push_back(ColumnFamilyDescriptor("default", cf_options));
|
||||
column_families.push_back(
|
||||
ColumnFamilyDescriptor("pikachu", ColumnFamilyOptions()));
|
||||
std::vector<ColumnFamilyHandle*> handles;
|
||||
DBOptions db_opts;
|
||||
db_opts.env = env_;
|
||||
@@ -4616,8 +4591,9 @@ TEST_F(DBTest2, TraceAndManualReplay) {
|
||||
std::vector<ColumnFamilyDescriptor> column_families;
|
||||
ColumnFamilyOptions cf_options;
|
||||
cf_options.merge_operator = MergeOperators::CreatePutOperator();
|
||||
column_families.emplace_back("default", cf_options);
|
||||
column_families.emplace_back("pikachu", ColumnFamilyOptions());
|
||||
column_families.push_back(ColumnFamilyDescriptor("default", cf_options));
|
||||
column_families.push_back(
|
||||
ColumnFamilyDescriptor("pikachu", ColumnFamilyOptions()));
|
||||
std::vector<ColumnFamilyHandle*> handles;
|
||||
DBOptions db_opts;
|
||||
db_opts.env = env_;
|
||||
@@ -4892,8 +4868,9 @@ TEST_F(DBTest2, TraceWithLimit) {
|
||||
std::vector<ColumnFamilyDescriptor> column_families;
|
||||
ColumnFamilyOptions cf_options;
|
||||
cf_options.merge_operator = MergeOperators::CreatePutOperator();
|
||||
column_families.emplace_back("default", cf_options);
|
||||
column_families.emplace_back("pikachu", ColumnFamilyOptions());
|
||||
column_families.push_back(ColumnFamilyDescriptor("default", cf_options));
|
||||
column_families.push_back(
|
||||
ColumnFamilyDescriptor("pikachu", ColumnFamilyOptions()));
|
||||
std::vector<ColumnFamilyHandle*> handles;
|
||||
DBOptions db_opts;
|
||||
db_opts.env = env_;
|
||||
@@ -4965,8 +4942,9 @@ TEST_F(DBTest2, TraceWithSampling) {
|
||||
DB* db2 = nullptr;
|
||||
std::vector<ColumnFamilyDescriptor> column_families;
|
||||
ColumnFamilyOptions cf_options;
|
||||
column_families.emplace_back("default", cf_options);
|
||||
column_families.emplace_back("pikachu", ColumnFamilyOptions());
|
||||
column_families.push_back(ColumnFamilyDescriptor("default", cf_options));
|
||||
column_families.push_back(
|
||||
ColumnFamilyDescriptor("pikachu", ColumnFamilyOptions()));
|
||||
std::vector<ColumnFamilyHandle*> handles;
|
||||
DBOptions db_opts;
|
||||
db_opts.env = env_;
|
||||
@@ -5070,8 +5048,9 @@ TEST_F(DBTest2, TraceWithFilter) {
|
||||
std::vector<ColumnFamilyDescriptor> column_families;
|
||||
ColumnFamilyOptions cf_options;
|
||||
cf_options.merge_operator = MergeOperators::CreatePutOperator();
|
||||
column_families.emplace_back("default", cf_options);
|
||||
column_families.emplace_back("pikachu", ColumnFamilyOptions());
|
||||
column_families.push_back(ColumnFamilyDescriptor("default", cf_options));
|
||||
column_families.push_back(
|
||||
ColumnFamilyDescriptor("pikachu", ColumnFamilyOptions()));
|
||||
std::vector<ColumnFamilyHandle*> handles;
|
||||
DBOptions db_opts;
|
||||
db_opts.env = env_;
|
||||
@@ -5119,8 +5098,9 @@ TEST_F(DBTest2, TraceWithFilter) {
|
||||
delete db3_init;
|
||||
|
||||
column_families.clear();
|
||||
column_families.emplace_back("default", cf_options);
|
||||
column_families.emplace_back("pikachu", ColumnFamilyOptions());
|
||||
column_families.push_back(ColumnFamilyDescriptor("default", cf_options));
|
||||
column_families.push_back(
|
||||
ColumnFamilyDescriptor("pikachu", ColumnFamilyOptions()));
|
||||
handles.clear();
|
||||
|
||||
DB* db3 = nullptr;
|
||||
@@ -5711,7 +5691,7 @@ TEST_F(DBTest2, CrashInRecoveryMultipleCF) {
|
||||
ASSERT_OK(ReadFileToString(env_, fname, &file_content));
|
||||
file_content[400] = 'h';
|
||||
file_content[401] = 'a';
|
||||
ASSERT_OK(WriteStringToFile(env_, file_content, fname, false));
|
||||
ASSERT_OK(WriteStringToFile(env_, file_content, fname));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -6461,7 +6441,7 @@ class RenameCurrentTest : public DBTestBase,
|
||||
: DBTestBase("rename_current_test", /*env_do_fsync=*/true),
|
||||
sync_point_(GetParam()) {}
|
||||
|
||||
~RenameCurrentTest() override = default;
|
||||
~RenameCurrentTest() override {}
|
||||
|
||||
void SetUp() override {
|
||||
env_->no_file_overwrite_.store(true, std::memory_order_release);
|
||||
@@ -7030,7 +7010,7 @@ TEST_F(DBTest2, CheckpointFileTemperature) {
|
||||
std::vector<LiveFileStorageInfo> infos;
|
||||
ASSERT_OK(
|
||||
dbfull()->GetLiveFilesStorageInfo(LiveFilesStorageInfoOptions(), &infos));
|
||||
for (const auto& info : infos) {
|
||||
for (auto info : infos) {
|
||||
temperatures.emplace(info.file_number, info.temperature);
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -73,7 +73,7 @@ DBTestBase::DBTestBase(const std::string path, bool env_do_fsync)
|
||||
if (getenv("ENCRYPTED_ENV")) {
|
||||
std::shared_ptr<EncryptionProvider> provider;
|
||||
std::string provider_id = getenv("ENCRYPTED_ENV");
|
||||
if (provider_id.find('=') == std::string::npos &&
|
||||
if (provider_id.find("=") == std::string::npos &&
|
||||
!EndsWith(provider_id, "://test")) {
|
||||
provider_id = provider_id + "://test";
|
||||
}
|
||||
@@ -588,7 +588,7 @@ void DBTestBase::CreateColumnFamilies(const std::vector<std::string>& cfs,
|
||||
ColumnFamilyOptions cf_opts(options);
|
||||
size_t cfi = handles_.size();
|
||||
handles_.resize(cfi + cfs.size());
|
||||
for (const auto& cf : cfs) {
|
||||
for (auto cf : cfs) {
|
||||
Status s = db_->CreateColumnFamily(cf_opts, cf, &handles_[cfi++]);
|
||||
ASSERT_OK(s);
|
||||
}
|
||||
@@ -651,7 +651,7 @@ Status DBTestBase::TryReopenWithColumnFamilies(
|
||||
EXPECT_EQ(cfs.size(), options.size());
|
||||
std::vector<ColumnFamilyDescriptor> column_families;
|
||||
for (size_t i = 0; i < cfs.size(); ++i) {
|
||||
column_families.emplace_back(cfs[i], options[i]);
|
||||
column_families.push_back(ColumnFamilyDescriptor(cfs[i], options[i]));
|
||||
}
|
||||
DBOptions db_opts = DBOptions(options[0]);
|
||||
last_options_ = options[0];
|
||||
@@ -828,7 +828,7 @@ std::vector<std::string> DBTestBase::MultiGet(std::vector<int> cfs,
|
||||
|
||||
for (unsigned int i = 0; i < cfs.size(); ++i) {
|
||||
handles.push_back(handles_[cfs[i]]);
|
||||
keys.emplace_back(k[i]);
|
||||
keys.push_back(k[i]);
|
||||
}
|
||||
std::vector<Status> s;
|
||||
if (!batched) {
|
||||
@@ -875,7 +875,7 @@ std::vector<std::string> DBTestBase::MultiGet(const std::vector<std::string>& k,
|
||||
std::vector<PinnableSlice> pin_values(k.size());
|
||||
|
||||
for (size_t i = 0; i < k.size(); ++i) {
|
||||
keys.emplace_back(k[i]);
|
||||
keys.push_back(k[i]);
|
||||
}
|
||||
db_->MultiGet(options, dbfull()->DefaultColumnFamily(), keys.size(),
|
||||
keys.data(), pin_values.data(), statuses.data());
|
||||
@@ -1614,7 +1614,7 @@ void DBTestBase::VerifyDBFromMap(std::map<std::string, std::string> true_data,
|
||||
<< iter_cnt << " / " << true_data.size();
|
||||
|
||||
// Verify Iterator::Seek()
|
||||
for (const auto& kv : true_data) {
|
||||
for (auto kv : true_data) {
|
||||
iter->Seek(kv.first);
|
||||
ASSERT_EQ(kv.first, iter->key().ToString());
|
||||
ASSERT_EQ(kv.second, iter->value().ToString());
|
||||
@@ -1644,7 +1644,7 @@ void DBTestBase::VerifyDBFromMap(std::map<std::string, std::string> true_data,
|
||||
<< iter_cnt << " / " << true_data.size();
|
||||
|
||||
// Verify ForwardIterator::Seek()
|
||||
for (const auto& kv : true_data) {
|
||||
for (auto kv : true_data) {
|
||||
iter->Seek(kv.first);
|
||||
ASSERT_EQ(kv.first, iter->key().ToString());
|
||||
ASSERT_EQ(kv.second, iter->value().ToString());
|
||||
@@ -1667,7 +1667,7 @@ void DBTestBase::VerifyDBInternal(
|
||||
auto iter =
|
||||
dbfull()->NewInternalIterator(read_options, &arena, kMaxSequenceNumber);
|
||||
iter->SeekToFirst();
|
||||
for (const auto& p : true_data) {
|
||||
for (auto p : true_data) {
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ParsedInternalKey ikey;
|
||||
ASSERT_OK(ParseInternalKey(iter->key(), &ikey, true /* log_err_key */));
|
||||
|
||||
@@ -558,7 +558,7 @@ TEST_P(DBTestUniversalCompaction, CompactFilesOnUniversalCompaction) {
|
||||
ColumnFamilyMetaData cf_meta;
|
||||
dbfull()->GetColumnFamilyMetaData(handles_[1], &cf_meta);
|
||||
std::vector<std::string> compaction_input_file_names;
|
||||
for (const auto& file : cf_meta.levels[0].files) {
|
||||
for (auto file : cf_meta.levels[0].files) {
|
||||
if (rnd.OneIn(2)) {
|
||||
compaction_input_file_names.push_back(file.name);
|
||||
}
|
||||
|
||||
+8
-7
@@ -107,9 +107,9 @@ class EnrichedSpecialEnv : public SpecialEnv {
|
||||
|
||||
InstrumentedMutex env_mutex_;
|
||||
// the wal whose actual delete was skipped by the env
|
||||
std::string skipped_wal;
|
||||
std::string skipped_wal = "";
|
||||
// the largest WAL that was requested to be deleted
|
||||
std::string largest_deleted_wal;
|
||||
std::string largest_deleted_wal = "";
|
||||
// number of WALs that were successfully deleted
|
||||
std::atomic<size_t> deleted_wal_cnt = {0};
|
||||
// the WAL whose delete from fs was skipped is reopened during recovery
|
||||
@@ -1543,7 +1543,7 @@ class RecoveryTestHelper {
|
||||
/*block_cache_tracer=*/nullptr,
|
||||
/*io_tracer=*/nullptr, /*db_id=*/"", /*db_session_id=*/"",
|
||||
options.daily_offpeak_time_utc,
|
||||
/*error_handler=*/nullptr, /*read_only=*/false));
|
||||
/*error_handler=*/nullptr));
|
||||
|
||||
wal_manager.reset(
|
||||
new WalManager(db_options, file_options, /*io_tracer=*/nullptr));
|
||||
@@ -1561,7 +1561,7 @@ class RecoveryTestHelper {
|
||||
new log::Writer(std::move(file_writer), current_log_number,
|
||||
db_options.recycle_log_file_num > 0, false,
|
||||
db_options.wal_compression);
|
||||
ASSERT_OK(log_writer->AddCompressionTypeRecord(WriteOptions()));
|
||||
ASSERT_OK(log_writer->AddCompressionTypeRecord());
|
||||
current_log_writer.reset(log_writer);
|
||||
|
||||
WriteBatch batch;
|
||||
@@ -1574,7 +1574,7 @@ class RecoveryTestHelper {
|
||||
ASSERT_OK(batch.Put(key, value));
|
||||
WriteBatchInternal::SetSequence(&batch, seq);
|
||||
ASSERT_OK(current_log_writer->AddRecord(
|
||||
WriteOptions(), WriteBatchInternal::Contents(&batch)));
|
||||
WriteBatchInternal::Contents(&batch)));
|
||||
versions->SetLastAllocatedSequence(seq);
|
||||
versions->SetLastPublishedSequence(seq);
|
||||
versions->SetLastSequence(seq);
|
||||
@@ -2227,7 +2227,8 @@ TEST_P(DBWALTestWithParamsVaryingRecoveryMode,
|
||||
ReadOptions ropt;
|
||||
Iterator* iter = dbfull()->NewIterator(ropt);
|
||||
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||
data.emplace_back(iter->key().ToString(), iter->value().ToString());
|
||||
data.push_back(
|
||||
std::make_pair(iter->key().ToString(), iter->value().ToString()));
|
||||
}
|
||||
EXPECT_OK(iter->status());
|
||||
delete iter;
|
||||
@@ -2433,7 +2434,7 @@ TEST_F(DBWALTest, TruncateLastLogAfterRecoverWALEmpty) {
|
||||
std::string last_log;
|
||||
uint64_t last_log_num = 0;
|
||||
ASSERT_OK(env_->GetChildren(dbname_, &filenames));
|
||||
for (const auto& fname : filenames) {
|
||||
for (auto fname : filenames) {
|
||||
uint64_t number;
|
||||
FileType type;
|
||||
if (ParseFileName(fname, &number, &type, nullptr)) {
|
||||
|
||||
@@ -375,7 +375,7 @@ TEST_F(DBBasicTestWithTimestamp, UpdateFullHistoryTsLowWithPublicAPI) {
|
||||
ts_low_str_long);
|
||||
ASSERT_EQ(s, Status::InvalidArgument());
|
||||
// test IncreaseFullHistoryTsLow with a timestamp which is null
|
||||
std::string ts_low_str_null;
|
||||
std::string ts_low_str_null = "";
|
||||
s = db_->IncreaseFullHistoryTsLow(db_->DefaultColumnFamily(),
|
||||
ts_low_str_null);
|
||||
ASSERT_EQ(s, Status::InvalidArgument());
|
||||
@@ -430,8 +430,8 @@ TEST_F(DBBasicTestWithTimestamp, GetApproximateSizes) {
|
||||
std::vector<Range> ranges;
|
||||
std::string start_tmp = Key(10);
|
||||
std::string end_tmp = Key(20);
|
||||
ranges.emplace_back(start_tmp, end_tmp);
|
||||
ranges.emplace_back(start, end);
|
||||
ranges.emplace_back(Range(start_tmp, end_tmp));
|
||||
ranges.emplace_back(Range(start, end));
|
||||
uint64_t range_sizes[2];
|
||||
ASSERT_OK(db_->GetApproximateSizes(size_approx_options, default_cf,
|
||||
ranges.data(), 2, range_sizes));
|
||||
@@ -598,7 +598,8 @@ TEST_F(DBBasicTestWithTimestamp, TrimHistoryTest) {
|
||||
|
||||
ColumnFamilyOptions cf_options(options);
|
||||
std::vector<ColumnFamilyDescriptor> column_families;
|
||||
column_families.emplace_back(kDefaultColumnFamilyName, cf_options);
|
||||
column_families.push_back(
|
||||
ColumnFamilyDescriptor(kDefaultColumnFamilyName, cf_options));
|
||||
DBOptions db_options(options);
|
||||
|
||||
// Trim data whose version > Timestamp(5, 0), read(k1, ts(7)) <- NOT_FOUND.
|
||||
@@ -641,7 +642,8 @@ TEST_F(DBBasicTestWithTimestamp, OpenAndTrimHistoryInvalidOptionTest) {
|
||||
|
||||
ColumnFamilyOptions cf_options(options);
|
||||
std::vector<ColumnFamilyDescriptor> column_families;
|
||||
column_families.emplace_back(kDefaultColumnFamilyName, cf_options);
|
||||
column_families.push_back(
|
||||
ColumnFamilyDescriptor(kDefaultColumnFamilyName, cf_options));
|
||||
DBOptions db_options(options);
|
||||
|
||||
// OpenAndTrimHistory should not work with avoid_flush_during_recovery
|
||||
@@ -1644,88 +1646,35 @@ TEST_F(DBBasicTestWithTimestamp, GetWithRowCache) {
|
||||
|
||||
const Snapshot* snap_with_nothing = db_->GetSnapshot();
|
||||
ASSERT_OK(db_->Put(write_opts, "foo", ts_early, "bar"));
|
||||
ASSERT_OK(db_->Put(write_opts, "foo2", ts_early, "bar2"));
|
||||
ASSERT_OK(db_->Put(write_opts, "foo3", ts_early, "bar3"));
|
||||
|
||||
const Snapshot* snap_with_foo = db_->GetSnapshot();
|
||||
|
||||
// Ensure file has sequence number greater than snapshot_with_foo
|
||||
for (int i = 0; i < 10; i++) {
|
||||
std::string numStr = std::to_string(i);
|
||||
ASSERT_OK(db_->Put(write_opts, numStr, ts_later, numStr));
|
||||
}
|
||||
ASSERT_OK(Flush());
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 0);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 0);
|
||||
|
||||
ReadOptions read_opts;
|
||||
read_opts.timestamp = &ts_later_slice;
|
||||
|
||||
std::string read_value;
|
||||
std::string read_ts;
|
||||
Status s;
|
||||
Status s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 0);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 1);
|
||||
ASSERT_EQ(read_ts, ts_early);
|
||||
|
||||
int expected_hit_count = 0;
|
||||
int expected_miss_count = 0;
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), expected_miss_count);
|
||||
|
||||
{
|
||||
read_opts.timestamp = nullptr;
|
||||
s = db_->Get(read_opts, "foo", &read_value);
|
||||
ASSERT_NOK(s);
|
||||
ASSERT_TRUE(s.IsInvalidArgument());
|
||||
}
|
||||
|
||||
// Mix use of Get
|
||||
{
|
||||
read_opts.timestamp = &ts_later_slice;
|
||||
|
||||
// Use Get without ts first, expect cache entry to store the correct ts
|
||||
s = db_->Get(read_opts, "foo2", &read_value);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS),
|
||||
++expected_miss_count);
|
||||
ASSERT_EQ(read_value, "bar2");
|
||||
|
||||
s = db_->Get(read_opts, "foo2", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), ++expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), expected_miss_count);
|
||||
ASSERT_EQ(read_ts, ts_early);
|
||||
ASSERT_EQ(read_value, "bar2");
|
||||
|
||||
// Use Get with ts first, expect the Get without ts can get correct record
|
||||
s = db_->Get(read_opts, "foo3", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS),
|
||||
++expected_miss_count);
|
||||
ASSERT_EQ(read_ts, ts_early);
|
||||
ASSERT_EQ(read_value, "bar3");
|
||||
|
||||
s = db_->Get(read_opts, "foo3", &read_value);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), ++expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), expected_miss_count);
|
||||
ASSERT_EQ(read_value, "bar3");
|
||||
}
|
||||
|
||||
{
|
||||
// Test with consecutive calls of Get with ts.
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS),
|
||||
++expected_miss_count);
|
||||
ASSERT_EQ(read_ts, ts_early);
|
||||
ASSERT_EQ(read_value, "bar");
|
||||
|
||||
// Test repeated get on cache entry
|
||||
for (int i = 0; i < 3; i++) {
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT),
|
||||
++expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS),
|
||||
expected_miss_count);
|
||||
ASSERT_EQ(read_ts, ts_early);
|
||||
ASSERT_EQ(read_value, "bar");
|
||||
}
|
||||
}
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 1);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 1);
|
||||
// Row cache is not storing the ts when record is inserted/updated.
|
||||
// To be fixed after enabling ROW_CACHE with timestamp.
|
||||
// ASSERT_EQ(read_ts, ts_early);
|
||||
|
||||
{
|
||||
std::string ts_nothing = Timestamp(0, 0);
|
||||
@@ -1733,43 +1682,41 @@ TEST_F(DBBasicTestWithTimestamp, GetWithRowCache) {
|
||||
read_opts.timestamp = &ts_nothing_slice;
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS),
|
||||
++expected_miss_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 1);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 2);
|
||||
|
||||
read_opts.timestamp = &ts_later_slice;
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 2);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 2);
|
||||
}
|
||||
|
||||
{
|
||||
read_opts.snapshot = snap_with_foo;
|
||||
read_opts.timestamp = &ts_later_slice;
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS),
|
||||
++expected_miss_count);
|
||||
ASSERT_EQ(read_ts, ts_early);
|
||||
ASSERT_EQ(read_value, "bar");
|
||||
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), ++expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), expected_miss_count);
|
||||
ASSERT_EQ(read_ts, ts_early);
|
||||
ASSERT_EQ(read_value, "bar");
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 2);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 3);
|
||||
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 3);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 3);
|
||||
}
|
||||
|
||||
{
|
||||
read_opts.snapshot = snap_with_nothing;
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS),
|
||||
++expected_miss_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 3);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 4);
|
||||
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), expected_hit_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS),
|
||||
++expected_miss_count);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 3);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 5);
|
||||
}
|
||||
|
||||
db_->ReleaseSnapshot(snap_with_nothing);
|
||||
@@ -1777,65 +1724,6 @@ TEST_F(DBBasicTestWithTimestamp, GetWithRowCache) {
|
||||
Close();
|
||||
}
|
||||
|
||||
TEST_F(DBBasicTestWithTimestamp, GetWithRowCacheMultiSST) {
|
||||
BlockBasedTableOptions table_options;
|
||||
table_options.block_size = 1;
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.statistics = ROCKSDB_NAMESPACE::CreateDBStatistics();
|
||||
LRUCacheOptions cache_options;
|
||||
cache_options.capacity = 8192;
|
||||
options.row_cache = cache_options.MakeSharedRowCache();
|
||||
|
||||
const size_t kTimestampSize = Timestamp(0, 0).size();
|
||||
TestComparator test_cmp(kTimestampSize);
|
||||
options.comparator = &test_cmp;
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
options.merge_operator = MergeOperators::CreateStringAppendTESTOperator();
|
||||
options.disable_auto_compactions = true;
|
||||
|
||||
DestroyAndReopen(options);
|
||||
|
||||
std::string ts_early = Timestamp(1, 0);
|
||||
std::string ts_later = Timestamp(10, 0);
|
||||
Slice ts_later_slice = ts_later;
|
||||
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo", ts_early, "v1"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
ColumnFamilyHandle* default_cf = db_->DefaultColumnFamily();
|
||||
ASSERT_OK(
|
||||
db_->Merge(WriteOptions(), default_cf, "foo", Timestamp(2, 0), "v2"));
|
||||
ASSERT_OK(
|
||||
db_->Merge(WriteOptions(), default_cf, "foo", Timestamp(3, 0), "v3"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
ReadOptions read_opts;
|
||||
read_opts.timestamp = &ts_later_slice;
|
||||
|
||||
std::string read_value;
|
||||
std::string read_ts;
|
||||
Status s;
|
||||
|
||||
{
|
||||
// Since there are two SST files, will trigger the table lookup twice.
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 0);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 2);
|
||||
ASSERT_EQ(read_ts, Timestamp(3, 0));
|
||||
ASSERT_EQ(read_value, "v1,v2,v3");
|
||||
|
||||
s = db_->Get(read_opts, "foo", &read_value, &read_ts);
|
||||
ASSERT_OK(s);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 2);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 2);
|
||||
ASSERT_EQ(read_ts, Timestamp(3, 0));
|
||||
ASSERT_EQ(read_value, "v1,v2,v3");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(DBBasicTestWithTimestampTableOptions, MultiGetPrefixFilter) {
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
@@ -2632,7 +2520,7 @@ TEST_F(DataVisibilityTest, MultiGetWithoutSnapshot) {
|
||||
auto ss = db_->MultiGet(read_opts, keys, &values);
|
||||
|
||||
writer_thread.join();
|
||||
for (const auto& s : ss) {
|
||||
for (auto s : ss) {
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
}
|
||||
VerifyDefaultCF();
|
||||
@@ -2902,8 +2790,8 @@ TEST_P(DBBasicTestWithTimestampCompressionSettings, PutDeleteGet) {
|
||||
// A class which remembers the name of each flushed file.
|
||||
class FlushedFileCollector : public EventListener {
|
||||
public:
|
||||
FlushedFileCollector() = default;
|
||||
~FlushedFileCollector() override = default;
|
||||
FlushedFileCollector() {}
|
||||
~FlushedFileCollector() override {}
|
||||
|
||||
void OnFlushCompleted(DB* /*db*/, const FlushJobInfo& info) override {
|
||||
InstrumentedMutexLock lock(&mutex_);
|
||||
@@ -3085,7 +2973,7 @@ TEST_F(DBBasicTestWithTimestamp, BatchWriteAndMultiGet) {
|
||||
key_vals.push_back(Key1(j));
|
||||
}
|
||||
for (size_t j = 0; j != kNumKeysPerTimestamp; ++j) {
|
||||
keys.emplace_back(key_vals[j]);
|
||||
keys.push_back(key_vals[j]);
|
||||
}
|
||||
|
||||
ReadOptions ropts;
|
||||
@@ -3791,12 +3679,12 @@ TEST_F(DBBasicTestWithTimestamp, FullHistoryTsLowSanityCheckFail) {
|
||||
std::vector<Slice> keys;
|
||||
std::vector<std::string> values;
|
||||
for (size_t j = 0; j < 2; ++j) {
|
||||
keys.emplace_back(key_vals[j]);
|
||||
keys.push_back(key_vals[j]);
|
||||
}
|
||||
|
||||
std::vector<Status> statuses =
|
||||
db_->MultiGet(read_opts, cfhs, keys, &values);
|
||||
for (const auto& status : statuses) {
|
||||
for (auto status : statuses) {
|
||||
ASSERT_TRUE(status.IsInvalidArgument());
|
||||
}
|
||||
}
|
||||
@@ -3808,12 +3696,12 @@ TEST_F(DBBasicTestWithTimestamp, FullHistoryTsLowSanityCheckFail) {
|
||||
std::vector<Slice> keys;
|
||||
std::vector<std::string> values;
|
||||
for (size_t j = 0; j < 1; ++j) {
|
||||
keys.emplace_back(key_vals[j]);
|
||||
keys.push_back(key_vals[j]);
|
||||
}
|
||||
|
||||
std::vector<Status> statuses =
|
||||
db_->MultiGet(read_opts, one_cfh, keys, &values);
|
||||
for (const auto& status : statuses) {
|
||||
for (auto status : statuses) {
|
||||
ASSERT_TRUE(status.IsInvalidArgument());
|
||||
}
|
||||
}
|
||||
@@ -3826,7 +3714,7 @@ TEST_F(DBBasicTestWithTimestamp, FullHistoryTsLowSanityCheckFail) {
|
||||
Status statuses[] = {Status::OK(), Status::OK()};
|
||||
db_->MultiGet(read_opts, /*num_keys=*/2, &column_families[0], &keys[0],
|
||||
&values[0], &statuses[0], /*sorted_input=*/false);
|
||||
for (const auto& status : statuses) {
|
||||
for (auto status : statuses) {
|
||||
ASSERT_TRUE(status.IsInvalidArgument());
|
||||
}
|
||||
}
|
||||
@@ -3839,7 +3727,7 @@ TEST_F(DBBasicTestWithTimestamp, FullHistoryTsLowSanityCheckFail) {
|
||||
Status statuses[] = {Status::OK()};
|
||||
db_->MultiGet(read_opts, /*num_keys=*/1, &one_column_family[0], &keys[0],
|
||||
&values[0], &statuses[0], /*sorted_input=*/false);
|
||||
for (const auto& status : statuses) {
|
||||
for (auto status : statuses) {
|
||||
ASSERT_TRUE(status.IsInvalidArgument());
|
||||
}
|
||||
}
|
||||
@@ -4554,8 +4442,8 @@ TEST_F(DBBasicTestWithTimestamp, TimestampFilterTableReadOnGet) {
|
||||
Slice read_ts_slice = Slice(read_ts_str);
|
||||
ReadOptions read_opts;
|
||||
read_opts.timestamp = &read_ts_slice;
|
||||
std::string value_from_get;
|
||||
std::string timestamp_from_get;
|
||||
std::string value_from_get = "";
|
||||
std::string timestamp_from_get = "";
|
||||
auto status =
|
||||
db_->Get(read_opts, Key1(3), &value_from_get, ×tamp_from_get);
|
||||
ASSERT_TRUE(status.IsNotFound());
|
||||
|
||||
@@ -172,8 +172,8 @@ TEST_F(TimestampCompatibleCompactionTest, MultipleSubCompactions) {
|
||||
|
||||
class TestFilePartitioner : public SstPartitioner {
|
||||
public:
|
||||
explicit TestFilePartitioner() = default;
|
||||
~TestFilePartitioner() override = default;
|
||||
explicit TestFilePartitioner() {}
|
||||
~TestFilePartitioner() override {}
|
||||
|
||||
const char* Name() const override { return "TestFilePartitioner"; }
|
||||
PartitionerResult ShouldPartition(
|
||||
@@ -188,7 +188,7 @@ class TestFilePartitioner : public SstPartitioner {
|
||||
|
||||
class TestFilePartitionerFactory : public SstPartitionerFactory {
|
||||
public:
|
||||
explicit TestFilePartitionerFactory() = default;
|
||||
explicit TestFilePartitionerFactory() {}
|
||||
std::unique_ptr<SstPartitioner> CreatePartitioner(
|
||||
const SstPartitioner::Context& /*context*/) const override {
|
||||
std::unique_ptr<SstPartitioner> ret =
|
||||
|
||||
+2
-2
@@ -296,7 +296,7 @@ TEST_P(DBWriteTest, IOErrorOnWALWritePropagateToWriteThreadFollower) {
|
||||
});
|
||||
SyncPoint::GetInstance()->EnableProcessing();
|
||||
for (int i = 0; i < kNumThreads; i++) {
|
||||
threads.emplace_back(
|
||||
threads.push_back(port::Thread(
|
||||
[&](int index) {
|
||||
// All threads should fail.
|
||||
auto res = Put("key" + std::to_string(index), "value");
|
||||
@@ -313,7 +313,7 @@ TEST_P(DBWriteTest, IOErrorOnWALWritePropagateToWriteThreadFollower) {
|
||||
ASSERT_FALSE(res.ok());
|
||||
}
|
||||
},
|
||||
i);
|
||||
i));
|
||||
}
|
||||
for (int i = 0; i < kNumThreads; i++) {
|
||||
threads[i].join();
|
||||
|
||||
+3
-2
@@ -8,8 +8,9 @@
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
#include "db/dbformat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
|
||||
#include "db/lookup_key.h"
|
||||
#include "monitoring/perf_context_imp.h"
|
||||
@@ -27,7 +28,7 @@ namespace ROCKSDB_NAMESPACE {
|
||||
// ValueType, not the lowest).
|
||||
const ValueType kValueTypeForSeek = kTypeWideColumnEntity;
|
||||
const ValueType kValueTypeForSeekForPrev = kTypeDeletion;
|
||||
const std::string kDisableUserTimestamp;
|
||||
const std::string kDisableUserTimestamp("");
|
||||
|
||||
EntryType GetEntryType(ValueType value_type) {
|
||||
switch (value_type) {
|
||||
|
||||
+3
-6
@@ -67,9 +67,7 @@ enum ValueType : unsigned char {
|
||||
kTypeDeletionWithTimestamp = 0x14,
|
||||
kTypeCommitXIDAndTimestamp = 0x15, // WAL only
|
||||
kTypeWideColumnEntity = 0x16,
|
||||
kTypeColumnFamilyWideColumnEntity = 0x17, // WAL only
|
||||
kTypeValuePreferredSeqno = 0x18, // Value with a unix write time
|
||||
kTypeColumnFamilyValuePreferredSeqno = 0x19, // WAL only
|
||||
kTypeColumnFamilyWideColumnEntity = 0x17, // WAL only
|
||||
kTypeMaxValid, // Should be after the last valid type, only used for
|
||||
// validation
|
||||
kMaxValue = 0x7F // Not used for storing records.
|
||||
@@ -83,8 +81,7 @@ extern const ValueType kValueTypeForSeekForPrev;
|
||||
// (i.e. a type used in memtable skiplist and sst file datablock).
|
||||
inline bool IsValueType(ValueType t) {
|
||||
return t <= kTypeMerge || kTypeSingleDeletion == t || kTypeBlobIndex == t ||
|
||||
kTypeDeletionWithTimestamp == t || kTypeWideColumnEntity == t ||
|
||||
kTypeValuePreferredSeqno == t;
|
||||
kTypeDeletionWithTimestamp == t || kTypeWideColumnEntity == t;
|
||||
}
|
||||
|
||||
// Checks whether a type is from user operation
|
||||
@@ -426,7 +423,7 @@ class InternalKey {
|
||||
|
||||
void Set(const Slice& _user_key_with_ts, SequenceNumber s, ValueType t,
|
||||
const Slice& ts) {
|
||||
ParsedInternalKey pik(_user_key_with_ts, s, t);
|
||||
ParsedInternalKey pik = ParsedInternalKey(_user_key_with_ts, s, t);
|
||||
// Should not call pik.SetTimestamp() directly as it overwrites the buffer
|
||||
// containing _user_key.
|
||||
SetFrom(pik, ts);
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -104,7 +106,7 @@ class DeleteFileTest : public DBTestBase {
|
||||
ASSERT_OK(env_->GetChildren(dir, &filenames));
|
||||
|
||||
int log_cnt = 0, sst_cnt = 0, manifest_cnt = 0;
|
||||
for (const auto& file : filenames) {
|
||||
for (auto file : filenames) {
|
||||
uint64_t number;
|
||||
FileType type;
|
||||
if (ParseFileName(file, &number, &type)) {
|
||||
@@ -146,9 +148,9 @@ TEST_F(DeleteFileTest, AddKeysAndQueryLevels) {
|
||||
std::vector<LiveFileMetaData> metadata;
|
||||
db_->GetLiveFilesMetaData(&metadata);
|
||||
|
||||
std::string level1file;
|
||||
std::string level1file = "";
|
||||
int level1keycount = 0;
|
||||
std::string level2file;
|
||||
std::string level2file = "";
|
||||
int level2keycount = 0;
|
||||
int level1index = 0;
|
||||
int level2index = 1;
|
||||
|
||||
@@ -796,6 +796,7 @@ void ErrorHandler::RecoverFromRetryableBGIOError() {
|
||||
RecordInHistogram(bg_error_stats_.get(),
|
||||
ERROR_HANDLER_AUTORESUME_RETRY_COUNT, retry_count);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void ErrorHandler::CheckAndSetRecoveryAndBGError(const Status& bg_err) {
|
||||
@@ -808,6 +809,7 @@ void ErrorHandler::CheckAndSetRecoveryAndBGError(const Status& bg_err) {
|
||||
if (bg_error_.severity() >= Status::Severity::kHardError) {
|
||||
is_db_stopped_.store(true, std::memory_order_release);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void ErrorHandler::EndAutoRecovery() {
|
||||
@@ -825,6 +827,7 @@ void ErrorHandler::EndAutoRecovery() {
|
||||
db_mutex_->Lock();
|
||||
}
|
||||
TEST_SYNC_POINT("PostEndAutoRecovery");
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
+1
-1
@@ -145,7 +145,7 @@ void EventHelpers::LogAndNotifyTableFileCreationFinished(
|
||||
jwriter << "N/A";
|
||||
} else {
|
||||
SeqnoToTimeMapping tmp;
|
||||
Status status = tmp.DecodeFrom(table_properties.seqno_to_time_mapping);
|
||||
Status status = tmp.Add(table_properties.seqno_to_time_mapping);
|
||||
if (status.ok()) {
|
||||
jwriter << tmp.ToHumanString();
|
||||
} else {
|
||||
|
||||
+2
-4
@@ -38,9 +38,8 @@ Status UpdateManifestForFilesState(
|
||||
const DBOptions& db_opts, const std::string& db_name,
|
||||
const std::vector<ColumnFamilyDescriptor>& column_families,
|
||||
const UpdateManifestForFilesStateOptions& opts) {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
// TODO: plumb Env::IOActivity
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
OfflineManifestWriter w(db_opts, db_name);
|
||||
Status s = w.Recover(column_families);
|
||||
|
||||
@@ -118,8 +117,7 @@ Status UpdateManifestForFilesState(
|
||||
std::unique_ptr<FSDirectory> db_dir;
|
||||
s = fs->NewDirectory(db_name, IOOptions(), &db_dir, nullptr);
|
||||
if (s.ok()) {
|
||||
s = w.LogAndApply(read_options, write_options, cfd, &edit,
|
||||
db_dir.get());
|
||||
s = w.LogAndApply(read_options, cfd, &edit, db_dir.get());
|
||||
}
|
||||
if (s.ok()) {
|
||||
++cfs_updated;
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include "db/version_edit.h"
|
||||
#include "port/port.h"
|
||||
#include "port/stack_trace.h"
|
||||
#include "rocksdb/advanced_options.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "rocksdb/sst_file_writer.h"
|
||||
#include "test_util/testharness.h"
|
||||
#include "test_util/testutil.h"
|
||||
@@ -246,7 +244,7 @@ class ChecksumVerifyHelper {
|
||||
|
||||
public:
|
||||
ChecksumVerifyHelper(Options& options) : options_(options) {}
|
||||
~ChecksumVerifyHelper() = default;
|
||||
~ChecksumVerifyHelper() {}
|
||||
|
||||
Status GetSingleFileChecksumAndFuncName(
|
||||
const std::string& file_path, std::string* file_checksum,
|
||||
@@ -474,7 +472,7 @@ TEST_F(ExternalSSTFileBasicTest, IngestFileWithFileChecksum) {
|
||||
std::vector<LiveFileMetaData> live_files;
|
||||
dbfull()->GetLiveFilesMetaData(&live_files);
|
||||
std::set<std::string> set1;
|
||||
for (const auto& f : live_files) {
|
||||
for (auto f : live_files) {
|
||||
set1.insert(f.name);
|
||||
ASSERT_EQ(f.file_checksum, kUnknownFileChecksum);
|
||||
ASSERT_EQ(f.file_checksum_func_name, kUnknownFileChecksumFuncName);
|
||||
@@ -523,7 +521,7 @@ TEST_F(ExternalSSTFileBasicTest, IngestFileWithFileChecksum) {
|
||||
ASSERT_OK(s) << s.ToString();
|
||||
std::vector<LiveFileMetaData> live_files1;
|
||||
dbfull()->GetLiveFilesMetaData(&live_files1);
|
||||
for (const auto& f : live_files1) {
|
||||
for (auto f : live_files1) {
|
||||
if (set1.find(f.name) == set1.end()) {
|
||||
ASSERT_EQ(f.file_checksum, file_checksum2);
|
||||
ASSERT_EQ(f.file_checksum_func_name, file_checksum_func_name2);
|
||||
@@ -540,7 +538,7 @@ TEST_F(ExternalSSTFileBasicTest, IngestFileWithFileChecksum) {
|
||||
ASSERT_OK(s) << s.ToString();
|
||||
std::vector<LiveFileMetaData> live_files2;
|
||||
dbfull()->GetLiveFilesMetaData(&live_files2);
|
||||
for (const auto& f : live_files2) {
|
||||
for (auto f : live_files2) {
|
||||
if (set1.find(f.name) == set1.end()) {
|
||||
ASSERT_EQ(f.file_checksum, file_checksum3);
|
||||
ASSERT_EQ(f.file_checksum_func_name, file_checksum_func_name3);
|
||||
@@ -563,7 +561,7 @@ TEST_F(ExternalSSTFileBasicTest, IngestFileWithFileChecksum) {
|
||||
ASSERT_OK(s) << s.ToString();
|
||||
std::vector<LiveFileMetaData> live_files3;
|
||||
dbfull()->GetLiveFilesMetaData(&live_files3);
|
||||
for (const auto& f : live_files3) {
|
||||
for (auto f : live_files3) {
|
||||
if (set1.find(f.name) == set1.end()) {
|
||||
ASSERT_FALSE(f.file_checksum == file_checksum4);
|
||||
ASSERT_EQ(f.file_checksum, "asd");
|
||||
@@ -583,7 +581,7 @@ TEST_F(ExternalSSTFileBasicTest, IngestFileWithFileChecksum) {
|
||||
ASSERT_OK(s) << s.ToString();
|
||||
std::vector<LiveFileMetaData> live_files4;
|
||||
dbfull()->GetLiveFilesMetaData(&live_files4);
|
||||
for (const auto& f : live_files4) {
|
||||
for (auto f : live_files4) {
|
||||
if (set1.find(f.name) == set1.end()) {
|
||||
std::string cur_checksum5, cur_checksum_func_name5;
|
||||
ASSERT_OK(checksum_helper.GetSingleFileChecksumAndFuncName(
|
||||
@@ -605,7 +603,7 @@ TEST_F(ExternalSSTFileBasicTest, IngestFileWithFileChecksum) {
|
||||
ASSERT_OK(s) << s.ToString();
|
||||
std::vector<LiveFileMetaData> live_files6;
|
||||
dbfull()->GetLiveFilesMetaData(&live_files6);
|
||||
for (const auto& f : live_files6) {
|
||||
for (auto f : live_files6) {
|
||||
if (set1.find(f.name) == set1.end()) {
|
||||
ASSERT_EQ(f.file_checksum, file_checksum6);
|
||||
ASSERT_EQ(f.file_checksum_func_name, file_checksum_func_name6);
|
||||
@@ -1294,80 +1292,6 @@ TEST_F(ExternalSSTFileBasicTest, VerifyChecksumReadahead) {
|
||||
Destroy(options);
|
||||
}
|
||||
|
||||
TEST_F(ExternalSSTFileBasicTest, ReadOldValueOfIngestedKeyBug) {
|
||||
Options options = CurrentOptions();
|
||||
options.compaction_style = kCompactionStyleUniversal;
|
||||
options.disable_auto_compactions = true;
|
||||
options.num_levels = 3;
|
||||
options.preserve_internal_time_seconds = 36000;
|
||||
DestroyAndReopen(options);
|
||||
|
||||
// To create the following LSM tree to trigger the bug:
|
||||
// L0
|
||||
// L1 with seqno [1, 2]
|
||||
// L2 with seqno [3, 4]
|
||||
|
||||
// To create L1 shape
|
||||
ASSERT_OK(
|
||||
db_->Put(WriteOptions(), db_->DefaultColumnFamily(), "k1", "seqno1"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
ASSERT_OK(
|
||||
db_->Put(WriteOptions(), db_->DefaultColumnFamily(), "k1", "seqno2"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
ColumnFamilyMetaData meta_1;
|
||||
db_->GetColumnFamilyMetaData(&meta_1);
|
||||
auto& files_1 = meta_1.levels[0].files;
|
||||
ASSERT_EQ(files_1.size(), 2);
|
||||
std::string file1 = files_1[0].db_path + files_1[0].name;
|
||||
std::string file2 = files_1[1].db_path + files_1[1].name;
|
||||
ASSERT_OK(db_->CompactFiles(CompactionOptions(), {file1, file2}, 1));
|
||||
// To confirm L1 shape
|
||||
ColumnFamilyMetaData meta_2;
|
||||
db_->GetColumnFamilyMetaData(&meta_2);
|
||||
ASSERT_EQ(meta_2.levels[0].files.size(), 0);
|
||||
ASSERT_EQ(meta_2.levels[1].files.size(), 1);
|
||||
// Seqno starts from non-zero due to seqno reservation for
|
||||
// preserve_internal_time_seconds greater than 0;
|
||||
ASSERT_EQ(meta_2.levels[1].files[0].largest_seqno, 102);
|
||||
ASSERT_EQ(meta_2.levels[2].files.size(), 0);
|
||||
// To create L2 shape
|
||||
ASSERT_OK(db_->Put(WriteOptions(), db_->DefaultColumnFamily(), "k2overlap",
|
||||
"old_value"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
ASSERT_OK(db_->Put(WriteOptions(), db_->DefaultColumnFamily(), "k2overlap",
|
||||
"old_value"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
ColumnFamilyMetaData meta_3;
|
||||
db_->GetColumnFamilyMetaData(&meta_3);
|
||||
auto& files_3 = meta_3.levels[0].files;
|
||||
std::string file3 = files_3[0].db_path + files_3[0].name;
|
||||
std::string file4 = files_3[1].db_path + files_3[1].name;
|
||||
ASSERT_OK(db_->CompactFiles(CompactionOptions(), {file3, file4}, 2));
|
||||
// To confirm L2 shape
|
||||
ColumnFamilyMetaData meta_4;
|
||||
db_->GetColumnFamilyMetaData(&meta_4);
|
||||
ASSERT_EQ(meta_4.levels[0].files.size(), 0);
|
||||
ASSERT_EQ(meta_4.levels[1].files.size(), 1);
|
||||
ASSERT_EQ(meta_4.levels[2].files.size(), 1);
|
||||
ASSERT_EQ(meta_4.levels[2].files[0].largest_seqno, 104);
|
||||
|
||||
// Ingest a file with new value of the key "k2overlap"
|
||||
SstFileWriter sst_file_writer(EnvOptions(), options);
|
||||
std::string f = sst_files_dir_ + "f.sst";
|
||||
ASSERT_OK(sst_file_writer.Open(f));
|
||||
ASSERT_OK(sst_file_writer.Put("k2overlap", "new_value"));
|
||||
ExternalSstFileInfo f_info;
|
||||
ASSERT_OK(sst_file_writer.Finish(&f_info));
|
||||
ASSERT_OK(db_->IngestExternalFile({f}, IngestExternalFileOptions()));
|
||||
|
||||
// To verify new value of the key "k2overlap" is correctly returned
|
||||
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||
std::string value;
|
||||
ASSERT_OK(db_->Get(ReadOptions(), "k2overlap", &value));
|
||||
// Before the fix, the value would be "old_value" and assertion failed
|
||||
ASSERT_EQ(value, "new_value");
|
||||
}
|
||||
|
||||
TEST_F(ExternalSSTFileBasicTest, IngestRangeDeletionTombstoneWithGlobalSeqno) {
|
||||
for (int i = 5; i < 25; i++) {
|
||||
ASSERT_OK(db_->Put(WriteOptions(), db_->DefaultColumnFamily(), Key(i),
|
||||
|
||||
Loaded 100 of 410 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user