mirror of
https://github.com/facebook/rocksdb.git
synced 2026-11-06 19:12:36 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36540d4355 | ||
|
|
fd68cc09a4 | ||
|
|
fc05af3b43 | ||
|
|
814ba4bfc1 | ||
|
|
7575389a25 | ||
|
|
63e7f124b4 | ||
|
|
f444196659 | ||
|
|
9ded0f791c | ||
|
|
b64bc23b63 | ||
|
|
3c9956ef40 | ||
|
|
659fc7c7a7 | ||
|
|
f2732d0586 | ||
|
|
055b21ab11 | ||
|
|
d227276147 | ||
|
|
956f1dfde3 | ||
|
|
28c1c15c29 | ||
|
|
12018136d8 | ||
|
|
bfd00bba9c | ||
|
|
6e57135a65 | ||
|
|
d201e59941 | ||
|
|
f405e55cfa | ||
|
|
4bea83aa44 | ||
|
|
8c7c0a38f1 | ||
|
|
10d02456b6 | ||
|
|
45668a05f5 | ||
|
|
de1e3ff6ea | ||
|
|
395d24f0fa | ||
|
|
daf06f1361 | ||
|
|
b46f5707c4 | ||
|
|
58d55b7f4e | ||
|
|
42a8e583c9 | ||
|
|
9a2d7485f0 | ||
|
|
54cb9c77d9 | ||
|
|
e3e8fbb497 | ||
|
|
0088f77788 | ||
|
|
1a885fe730 | ||
|
|
3a287796e3 | ||
|
|
6e88126dd3 | ||
|
|
4eaa771c01 | ||
|
|
5620efc794 | ||
|
|
ace1721b28 | ||
|
|
1d6dbfb8b7 | ||
|
|
95b41eec6d | ||
|
|
046ac91a7f | ||
|
|
c6b1f6d182 | ||
|
|
f9d45358ca | ||
|
|
76c834e441 | ||
|
|
95d582e0cc | ||
|
|
d11584e42e | ||
|
|
acf77e1bfe | ||
|
|
377eee77f8 | ||
|
|
2b4245559c | ||
|
|
b10c171e58 | ||
|
|
aacf60dda2 | ||
|
|
61ed0de600 | ||
|
|
1d8c54aeaa | ||
|
|
17042a3fb7 | ||
|
|
b9cb7b9644 | ||
|
|
0d68aff3a1 | ||
|
|
fc48af33f5 | ||
|
|
071a146fa0 | ||
|
|
8829ba9fe1 | ||
|
|
4e60663b31 | ||
|
|
36704e9227 | ||
|
|
f2ddb92750 | ||
|
|
2233a2f4c0 | ||
|
|
a31fded253 | ||
|
|
f046a8f617 | ||
|
|
c3bff1c02d | ||
|
|
0bf9079d44 | ||
|
|
46e8c445e7 | ||
|
|
054c00e92d | ||
|
|
96fb7de3bc | ||
|
|
d895eb08b3 | ||
|
|
11d4ac87ea | ||
|
|
3812a77771 | ||
|
|
438fc3d9b7 | ||
|
|
928aca835f | ||
|
|
d82d179a5e | ||
|
|
59f4cbef8c | ||
|
|
1b2b16b38e | ||
|
|
9243f1b668 | ||
|
|
b31f3245f1 | ||
|
|
fc25ac0f3b | ||
|
|
14633148a7 | ||
|
|
28ba896f19 | ||
|
|
f099032131 | ||
|
|
502a1754c4 | ||
|
|
0797616de0 | ||
|
|
1f3e3ead3f | ||
|
|
532c940b79 | ||
|
|
8c01cb79da | ||
|
|
3079a7e7c2 | ||
|
|
5eebfaaa09 | ||
|
|
3ef9092487 | ||
|
|
dee46863ba | ||
|
|
7fe93162c5 | ||
|
|
84711e2f6a | ||
|
|
c057c2e81d | ||
|
|
186344196b | ||
|
|
b60cb55889 | ||
|
|
24e7e7be04 | ||
|
|
51ecdd3e8f | ||
|
|
ef342246dc | ||
|
|
bc95cdd242 | ||
|
|
a29db3048f | ||
|
|
e572ae9f57 | ||
|
|
4b684e96b7 | ||
|
|
800cfae987 | ||
|
|
cb08a682d4 | ||
|
|
d982260b63 | ||
|
|
d69628e6ce | ||
|
|
ec5b1be18d | ||
|
|
5a26f392ca | ||
|
|
b5bb553d5e | ||
|
|
4835c11cce | ||
|
|
59ba1d200d | ||
|
|
65e162bf09 | ||
|
|
c4228abdc0 | ||
|
|
7e4406a171 | ||
|
|
b49f9cdd3c | ||
|
|
cad76a2e1e | ||
|
|
e28251ca72 | ||
|
|
2dda7a0dd2 | ||
|
|
21d5a8f54f | ||
|
|
8d0c09d7e6 | ||
|
|
fdfd044bb2 | ||
|
|
9d58e3f63a | ||
|
|
0758271d51 | ||
|
|
513aae1a31 | ||
|
|
1a1f9f1660 | ||
|
|
fa0190f885 | ||
|
|
7f2c59e316 | ||
|
|
491e3d4342 | ||
|
|
c5fbfd7ad8 | ||
|
|
cd15331711 | ||
|
|
1de6940980 | ||
|
|
5a9ecf6614 | ||
|
|
5da900f28a | ||
|
|
5cb2d09d47 | ||
|
|
ed46981bea | ||
|
|
f11a0237b6 | ||
|
|
ea6ed0d56e | ||
|
|
81b6296c7e | ||
|
|
09411e199d | ||
|
|
d411fc4dd6 | ||
|
|
906c6683ed | ||
|
|
06e593376c | ||
|
|
a036525809 | ||
|
|
5a1fb5ccd6 | ||
|
|
b7ecbe309d | ||
|
|
3d81f175b4 | ||
|
|
01f2edd145 | ||
|
|
f799c73d28 | ||
|
|
4fefe1fed9 | ||
|
|
2a8b2df383 | ||
|
|
83e38c0a58 | ||
|
|
5b073a7daa | ||
|
|
a771a47a1b | ||
|
|
106058c076 | ||
|
|
ad0362ac92 | ||
|
|
15487b84e4 | ||
|
|
8d50a7c9df | ||
|
|
d8c1ab8b2d | ||
|
|
7b24dec25d | ||
|
|
f7486ff6a3 | ||
|
|
66ef68bec8 | ||
|
|
8c568bac61 | ||
|
|
5b981b64f4 | ||
|
|
81765866c4 |
No files matched your search
+16
-77
@@ -146,9 +146,12 @@ commands:
|
||||
install-maven:
|
||||
steps:
|
||||
- run:
|
||||
name: Install maven
|
||||
name: Install Maven
|
||||
command: |
|
||||
sudo apt-get update -y && sudo apt-get install -y maven
|
||||
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
|
||||
|
||||
setup-folly:
|
||||
steps:
|
||||
@@ -231,6 +234,7 @@ 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:
|
||||
@@ -244,7 +248,7 @@ jobs:
|
||||
- increase-max-open-files-on-macos
|
||||
- install-gflags-on-macos
|
||||
- pre-steps-macos
|
||||
- run: ulimit -S -n `ulimit -H -n` && OPT=-DCIRCLECI make V=1 J=16 -j16 all
|
||||
- run: ulimit -S -n `ulimit -H -n` && make V=1 J=16 -j16 all
|
||||
- post-steps
|
||||
|
||||
build-macos-cmake:
|
||||
@@ -543,7 +547,7 @@ jobs:
|
||||
resource_class: large
|
||||
steps:
|
||||
- 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
|
||||
- run: ulimit -S -n `ulimit -H -n` && make V=1 -j8 CRASH_TEST_EXT_ARGS='--duration=960 --max_key=2500000' blackbox_crash_test_with_atomic_flush
|
||||
- post-steps
|
||||
|
||||
build-linux-crashtest-tiered-storage-bb:
|
||||
@@ -553,7 +557,7 @@ jobs:
|
||||
- pre-steps
|
||||
- run:
|
||||
name: "run crashtest"
|
||||
command: ulimit -S -n `ulimit -H -n` && make V=1 -j32 CRASH_TEST_EXT_ARGS='--duration=10800 --use_io_uring=0' blackbox_crash_test_with_tiered_storage
|
||||
command: ulimit -S -n `ulimit -H -n` && make V=1 -j32 CRASH_TEST_EXT_ARGS='--duration=10800' blackbox_crash_test_with_tiered_storage
|
||||
no_output_timeout: 100m
|
||||
- post-steps
|
||||
|
||||
@@ -564,7 +568,7 @@ jobs:
|
||||
- pre-steps
|
||||
- run:
|
||||
name: "run crashtest"
|
||||
command: ulimit -S -n `ulimit -H -n` && make V=1 -j32 CRASH_TEST_EXT_ARGS='--duration=10800 --use_io_uring=0' whitebox_crash_test_with_tiered_storage
|
||||
command: ulimit -S -n `ulimit -H -n` && make V=1 -j32 CRASH_TEST_EXT_ARGS='--duration=10800' whitebox_crash_test_with_tiered_storage
|
||||
no_output_timeout: 100m
|
||||
- post-steps
|
||||
|
||||
@@ -623,7 +627,7 @@ jobs:
|
||||
- windows-build-steps
|
||||
|
||||
build-linux-java:
|
||||
executor: linux-docker
|
||||
executor: linux-java-docker
|
||||
resource_class: large
|
||||
steps:
|
||||
- pre-steps
|
||||
@@ -636,17 +640,13 @@ jobs:
|
||||
which javac && javac -version
|
||||
- run:
|
||||
name: "Test RocksDBJava"
|
||||
command: make V=1 J=8 -j8 jtest
|
||||
command: scl enable devtoolset-7 'make V=1 J=8 -j8 jtest'
|
||||
- post-steps
|
||||
|
||||
build-linux-java-pmd:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
executor: linux-java-docker
|
||||
resource_class: large
|
||||
environment:
|
||||
JAVA_HOME: /usr/lib/jvm/java-8-openjdk-amd64
|
||||
steps:
|
||||
- install-maven
|
||||
- pre-steps
|
||||
- run:
|
||||
name: "Set Java Environment"
|
||||
@@ -655,9 +655,10 @@ 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: make V=1 J=8 -j8 jpmd
|
||||
command: scl enable devtoolset-7 'make V=1 J=8 -j8 jpmd'
|
||||
- post-pmd-steps
|
||||
|
||||
build-linux-java-static:
|
||||
@@ -877,66 +878,11 @@ jobs:
|
||||
- perform-benchmarks
|
||||
- post-benchmarks
|
||||
|
||||
workflows:
|
||||
workflows: # Only jobs that haven't been successfully migrated to GitHub Actions
|
||||
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-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:
|
||||
@@ -956,11 +902,4 @@ workflows:
|
||||
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
|
||||
- build-windows-vs2022-avx2
|
||||
- build-windows-vs2022
|
||||
@@ -0,0 +1,7 @@
|
||||
name: build-folly
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Build folly and dependencies
|
||||
run: make build_folly
|
||||
shell: bash
|
||||
@@ -0,0 +1,8 @@
|
||||
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
|
||||
@@ -0,0 +1,10 @@
|
||||
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
|
||||
@@ -0,0 +1,7 @@
|
||||
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
|
||||
@@ -0,0 +1,7 @@
|
||||
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
|
||||
@@ -0,0 +1,9 @@
|
||||
name: install-jdk8-on-macos
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install JDK 8 on macos
|
||||
run: |-
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew tap bell-sw/liberica
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install --cask liberica-jdk8
|
||||
shell: bash
|
||||
@@ -0,0 +1,11 @@
|
||||
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
|
||||
@@ -0,0 +1,22 @@
|
||||
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
|
||||
@@ -0,0 +1,17 @@
|
||||
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
|
||||
@@ -0,0 +1,38 @@
|
||||
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
|
||||
@@ -0,0 +1,5 @@
|
||||
name: pre-steps-macos
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
@@ -0,0 +1,18 @@
|
||||
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
|
||||
@@ -0,0 +1,7 @@
|
||||
name: setup-folly
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Checkout folly sources
|
||||
run: make checkout_folly
|
||||
shell: bash
|
||||
@@ -0,0 +1,20 @@
|
||||
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
|
||||
@@ -0,0 +1,54 @@
|
||||
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
|
||||
@@ -0,0 +1,15 @@
|
||||
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"
|
||||
@@ -0,0 +1,18 @@
|
||||
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"
|
||||
@@ -0,0 +1,98 @@
|
||||
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"
|
||||
@@ -0,0 +1,46 @@
|
||||
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"
|
||||
@@ -0,0 +1,609 @@
|
||||
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' 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 build only ======================== #
|
||||
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: Build
|
||||
run: ulimit -S -n `ulimit -H -n` && make V=1 J=16 -j16 all
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ========================= MacOS with Tests ======================== #
|
||||
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"
|
||||
@@ -1,45 +0,0 @@
|
||||
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
|
||||
+6
-10
@@ -76,11 +76,6 @@ 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()
|
||||
@@ -171,7 +166,7 @@ else()
|
||||
if(WITH_ZSTD)
|
||||
find_package(zstd REQUIRED)
|
||||
add_definitions(-DZSTD)
|
||||
include_directories(${ZSTD_INCLUDE_DIR})
|
||||
include_directories(${ZSTD_INCLUDE_DIRS})
|
||||
list(APPEND THIRDPARTY_LIBS zstd::zstd)
|
||||
endif()
|
||||
endif()
|
||||
@@ -376,7 +371,7 @@ option(WITH_NUMA "build with NUMA policy support" OFF)
|
||||
if(WITH_NUMA)
|
||||
find_package(NUMA REQUIRED)
|
||||
add_definitions(-DNUMA)
|
||||
include_directories(${NUMA_INCLUDE_DIR})
|
||||
include_directories(${NUMA_INCLUDE_DIRS})
|
||||
list(APPEND THIRDPARTY_LIBS NUMA::NUMA)
|
||||
endif()
|
||||
|
||||
@@ -1428,6 +1423,7 @@ 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
|
||||
@@ -1477,7 +1473,7 @@ if(WITH_TESTS)
|
||||
utilities/cassandra/test_utils.cc
|
||||
)
|
||||
enable_testing()
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
add_custom_target(rocksdb_check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
set(TESTUTILLIB testutillib${ARTIFACT_SUFFIX})
|
||||
add_library(${TESTUTILLIB} STATIC ${TESTUTIL_SOURCE})
|
||||
target_link_libraries(${TESTUTILLIB} ${ROCKSDB_LIB} ${FOLLY_LIBS})
|
||||
@@ -1502,7 +1498,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(check ${exename}${ARTIFACT_SUFFIX})
|
||||
add_dependencies(rocksdb_check ${exename}${ARTIFACT_SUFFIX})
|
||||
endif()
|
||||
endforeach(sourcefile ${TESTS})
|
||||
|
||||
@@ -1522,7 +1518,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(check c_test)
|
||||
add_dependencies(rocksdb_check c_test)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
+99
@@ -1,6 +1,105 @@
|
||||
# Rocksdb Change Log
|
||||
> NOTE: Entries for next release do not go here. Follow instructions in `unreleased_history/README.txt`
|
||||
|
||||
## 9.0.1 (04/11/2024)
|
||||
### Bug Fixes
|
||||
* Fixed CMake Javadoc and source jar builds
|
||||
* Fixed Java `SstFileMetaData` to prevent throwing `java.lang.NoSuchMethodError`
|
||||
|
||||
## 9.0.0 (02/16/2024)
|
||||
### New Features
|
||||
* Provide support for FSBuffer for point lookups. Also added support for scans and compactions that don't go through prefetching.
|
||||
* *Make `SstFileWriter` create SST files without persisting user defined timestamps when the `Option.persist_user_defined_timestamps` flag is set to false.
|
||||
* Add support for user-defined timestamps in APIs `DeleteFilesInRanges` and `GetPropertiesOfTablesInRange`.
|
||||
* Mark wal\_compression feature as production-ready. Currently only compatible with ZSTD compression.
|
||||
|
||||
### Public API Changes
|
||||
* Allow setting Stderr logger via C API
|
||||
* Declare one Get and one MultiGet variant as pure virtual, and make all the other variants non-overridable. The methods required to be implemented by derived classes of DB allow returning timestamps. It is up to the implementation to check and return an error if timestamps are not supported. The non-batched MultiGet APIs are reimplemented in terms of batched MultiGet, so callers might see a performance improvement.
|
||||
* Exposed mode option to Rate Limiter via c api.
|
||||
* Removed deprecated option `access_hint_on_compaction_start`
|
||||
* Removed deprecated option `ColumnFamilyOptions::check_flush_compaction_key_order`
|
||||
* *Remove the default `WritableFile::GetFileSize` and `FSWritableFile::GetFileSize` implementation that returns 0 and make it pure virtual, so that subclasses are enforced to explicitly provide an implementation.
|
||||
* Removed deprecated option `ColumnFamilyOptions::level_compaction_dynamic_file_size`
|
||||
* *Removed tickers with typos "rocksdb.error.handler.bg.errro.count", "rocksdb.error.handler.bg.io.errro.count", "rocksdb.error.handler.bg.retryable.io.errro.count".
|
||||
* Remove the force mode for `EnableFileDeletions` API because it is unsafe with no known legitimate use.
|
||||
* Removed deprecated option `ColumnFamilyOptions::ignore_max_compaction_bytes_for_input`
|
||||
* `sst_dump --command=check` now compares the number of records in a table with `num_entries` in table property, and reports corruption if there is a mismatch. API `SstFileDumper::ReadSequential()` is updated to optionally do this verification. (#12322)
|
||||
|
||||
### Behavior Changes
|
||||
* format\_version=6 is the new default setting in BlockBasedTableOptions, for more robust data integrity checking. DBs and SST files written with this setting cannot be read by RocksDB versions before 8.6.0.
|
||||
* Compactions can be scheduled in parallel in an additional scenario: multiple files are marked for compaction within a single column family
|
||||
* For leveled compaction, RocksDB will try to do intra-L0 compaction if the total L0 size is small compared to Lbase (#12214). Users with atomic_flush=true are more likely to see the impact of this change.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixed a data race in `DBImpl::RenameTempFileToOptionsFile`.
|
||||
* Fix some perf context statistics error in write steps. which include missing write_memtable_time in unordered_write. missing write_memtable_time in PipelineWrite when Writer stat is STATE_PARALLEL_MEMTABLE_WRITER. missing write_delay_time when calling DelayWrite in WriteImplWALOnly function.
|
||||
* Fixed a bug that can, under rare circumstances, cause MultiGet to return an incorrect result for a duplicate key in a MultiGet batch.
|
||||
* Fix a bug where older data of an ingested key can be returned for read when universal compaction is used
|
||||
|
||||
## 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.
|
||||
|
||||
### 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.0 (11/17/2023)
|
||||
### New Features
|
||||
* Add GetEntity() and PutEntity() API implementation for Attribute Group support. Through the use of Column Families, AttributeGroup enables users to logically group wide-column entities.
|
||||
|
||||
+8
-3
@@ -169,21 +169,26 @@ most processors made since roughly 2013.
|
||||
|
||||
* Install the dependencies for RocksDB:
|
||||
|
||||
pkg_add gmake gflags snappy bzip2 lz4 zstd git jdk bash findutils gnuwatch
|
||||
`pkg_add gmake gflags snappy bzip2 lz4 zstd git bash findutils gnuwatch`
|
||||
|
||||
* Build RocksDB from source:
|
||||
|
||||
```bash
|
||||
cd ~
|
||||
git clone https://github.com/facebook/rocksdb.git
|
||||
cd rocksdb
|
||||
gmake static_lib
|
||||
```
|
||||
|
||||
* Build RocksJava from source (optional):
|
||||
|
||||
* In OpenBSD, JDK depends on XWindows system, so please check that you installed OpenBSD with `xbase` package.
|
||||
* Install dependencies : `pkg_add -v jdk%1.8`
|
||||
```bash
|
||||
cd rocksdb
|
||||
export JAVA_HOME=/usr/local/jdk-1.8.0
|
||||
export PATH=$PATH:/usr/local/jdk-1.8.0/bin
|
||||
gmake rocksdbjava
|
||||
gmake rocksdbjava SHA256_CMD='sha256 -q'
|
||||
```
|
||||
|
||||
* **iOS**:
|
||||
* Run: `TARGET_OS=IOS make static_lib`. When building the project which uses rocksdb iOS library, make sure to define an important pre-processing macros: `IOS_CROSS_COMPILE`.
|
||||
|
||||
@@ -539,7 +539,8 @@ endif
|
||||
|
||||
ifdef USE_CLANG
|
||||
# Used by some teams in Facebook
|
||||
WARNING_FLAGS += -Wshift-sign-overflow -Wambiguous-reversed-operator -Wimplicit-fallthrough
|
||||
WARNING_FLAGS += -Wshift-sign-overflow -Wambiguous-reversed-operator \
|
||||
-Wimplicit-fallthrough -Wreinterpret-base-class -Wundefined-reinterpret-cast
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), OS_OPENBSD)
|
||||
@@ -1768,6 +1769,9 @@ 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)
|
||||
|
||||
@@ -2094,8 +2098,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
|
||||
ZLIB_SHA256 ?= ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e
|
||||
ZLIB_VER ?= 1.3.1
|
||||
ZLIB_SHA256 ?= 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23
|
||||
ZLIB_DOWNLOAD_BASE ?= http://zlib.net
|
||||
BZIP2_VER ?= 1.0.8
|
||||
BZIP2_SHA256 ?= ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269
|
||||
|
||||
@@ -163,24 +163,6 @@ case "$TARGET_OS" in
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -latomic"
|
||||
fi
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread -lrt -ldl"
|
||||
if test -z "$ROCKSDB_USE_IO_URING"; then
|
||||
ROCKSDB_USE_IO_URING=1
|
||||
fi
|
||||
if test "$ROCKSDB_USE_IO_URING" -ne 0; then
|
||||
# check for liburing
|
||||
$CXX $PLATFORM_CXXFLAGS -x c++ - -luring -o test.o 2>/dev/null <<EOF
|
||||
#include <liburing.h>
|
||||
int main() {
|
||||
struct io_uring ring;
|
||||
io_uring_queue_init(1, &ring, 0);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if [ "$?" = 0 ]; then
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -luring"
|
||||
COMMON_FLAGS="$COMMON_FLAGS -DROCKSDB_IOURING_PRESENT"
|
||||
fi
|
||||
fi
|
||||
# PORT_FILES=port/linux/linux_specific.cc
|
||||
;;
|
||||
SunOS)
|
||||
@@ -614,11 +596,29 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$ROCKSDB_USE_IO_URING"; then
|
||||
ROCKSDB_USE_IO_URING=1
|
||||
fi
|
||||
if [ "$ROCKSDB_USE_IO_URING" -ne 0 -a "$PLATFORM" = OS_LINUX ]; then
|
||||
# check for liburing
|
||||
$CXX $PLATFORM_CXXFLAGS -x c++ - -luring -o test.o 2>/dev/null <<EOF
|
||||
#include <liburing.h>
|
||||
int main() {
|
||||
struct io_uring ring;
|
||||
io_uring_queue_init(1, &ring, 0);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if [ "$?" = 0 ]; then
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -luring"
|
||||
COMMON_FLAGS="$COMMON_FLAGS -DROCKSDB_IOURING_PRESENT"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# TODO(tec): Fix -Wshorten-64-to-32 errors on FreeBSD and enable the warning.
|
||||
# -Wshorten-64-to-32 breaks compilation on FreeBSD aarch64 and i386
|
||||
if ! { [ "$TARGET_OS" = FreeBSD ] && [ "$TARGET_ARCHITECTURE" = arm64 -o "$TARGET_ARCHITECTURE" = i386 ]; }; then
|
||||
if ! { [ "$TARGET_OS" = FreeBSD -o "$TARGET_OS" = OpenBSD ] && [ "$TARGET_ARCHITECTURE" = arm64 -o "$TARGET_ARCHITECTURE" = i386 ]; }; then
|
||||
# Test whether -Wshorten-64-to-32 is available
|
||||
$CXX $PLATFORM_CXXFLAGS -x c++ - -o test.o -Wshorten-64-to-32 2>/dev/null <<EOF
|
||||
int main() {}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||
# The file is generated using update_dependencies.sh.
|
||||
GCC_BASE=/mnt/gvfs/third-party2/gcc/e40bde78650fa91b8405a857e3f10bf336633fb0/11.x/centos7-native/886b5eb
|
||||
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/2043340983c032915adbb6f78903dc855b65aee8/12/platform010/9520e0f
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/c00dcc6a3e4125c7e8b248e9a79c14b78ac9e0ca/11.x/platform010/5684a5a
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/0b9c8e4b060eda62f3bc1c6127bbe1256697569b/2.34/platform010/f259413
|
||||
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/bc9647f7912b131315827d65cb6189c21f381d05/1.1.3/platform010/76ebdda
|
||||
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/a6f5f3f1d063d2d00cd02fc12f0f05fc3ab3a994/1.2.11/platform010/76ebdda
|
||||
GCC_BASE=/mnt/gvfs/third-party2/gcc/62de5a92e5f23c661c3d4b9f322e04eb14e7a5bd/11.x/centos8-native/886b5eb
|
||||
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/1f6edd1ff15c99c861afc8f3cd69054cd974dd64/15/platform010/72a2ff8
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/d1129753c8361ac8e9453c0f4291337a4507ebe6/11.x/platform010/5684a5a
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/fed6e93d87571fb162734c86636119d45a398963/2.34/platform010/f259413
|
||||
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/31a346126a1f3b64812c362511cb04cc1bd40855/1.1.8/platform010/76ebdda
|
||||
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/0c65c05468b5a38cef1a106a1f526463e120c8dd/1.2.8/platform010/76ebdda
|
||||
BZIP2_BASE=/mnt/gvfs/third-party2/bzip2/09703139cfc376bd8a82642385a0e97726b28287/1.0.6/platform010/76ebdda
|
||||
LZ4_BASE=/mnt/gvfs/third-party2/lz4/60220d6a5bf7722b9cc239a1368c596619b12060/1.9.1/platform010/76ebdda
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/50eace8143eaaea9473deae1f3283e0049e05633/1.4.x/platform010/64091f4
|
||||
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/5d27e5919771603da06000a027b12f799e58a4f7/2.2.0/platform010/76ebdda
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/b62912d333ef33f9760efa6219dbe3fe6abb3b0e/master/platform010/f57cc4a
|
||||
NUMA_BASE=/mnt/gvfs/third-party2/numa/6b412770957aa3c8a87e5e0dcd8cc2f45f393bc0/2.0.11/platform010/76ebdda
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/52f69816e936e147664ad717eb71a1a0e9dc973a/1.4/platform010/5074a48
|
||||
TBB_BASE=/mnt/gvfs/third-party2/tbb/c9cc192099fa84c0dcd0ffeedd44a373ad6e4925/2018_U5/platform010/76ebdda
|
||||
LZ4_BASE=/mnt/gvfs/third-party2/lz4/ff23d17b932725cc1734a14896a8b67c518ba169/1.9.4/platform010/76ebdda
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/576397d8b1d9cea7306ad1e454d5e55caaa2ff1c/1.4.x/platform010/64091f4
|
||||
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/fecac07861cb829f5e60dbeff0503d3272db73c0/2.2.0/platform010/76ebdda
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/0bb3f5756788ce26e2e16a1cb2f2af2c59b51abe/master/platform010/f57cc4a
|
||||
NUMA_BASE=/mnt/gvfs/third-party2/numa/5b602edd46fda54cdd7ea45f77dbe4061206e174/2.0.11/platform010/76ebdda
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/97cac22a149c2e202917e05d44e87e516b68216f/1.4/platform010/5074a48
|
||||
TBB_BASE=/mnt/gvfs/third-party2/tbb/53953ebc4e3eda85ad6fc3e429ba146035e97b90/2018_U5/platform010/76ebdda
|
||||
LIBURING_BASE=/mnt/gvfs/third-party2/liburing/a98e2d137007e3ebf7f33bd6f99c2c56bdaf8488/20210212/platform010/76ebdda
|
||||
BENCHMARK_BASE=/mnt/gvfs/third-party2/benchmark/780c7a0f9cf0967961e69ad08e61cddd85d61821/trunk/platform010/76ebdda
|
||||
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/02d9f76aaaba580611cf75e741753c800c7fdc12/fb/platform010/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/938dc3f064ef3a48c0446f5b11d788d50b3eb5ee/2.37/centos7-native/da39a3e
|
||||
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/429a6b3203eb415f1599bd15183659153129188e/3.15.0/platform010/76ebdda
|
||||
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/624a2f8f6c93c3c1df8aa4a6255d8202631a6c80/fb/platform010/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/39579e8603b48b3540f8b0633f43adf29acccb8b/2.37/centos8-native/da39a3e
|
||||
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/cd9cc656d49ecb53797ce4d055e49fde29fd57ff/3.19.0/platform010/76ebdda
|
||||
LUA_BASE=/mnt/gvfs/third-party2/lua/363787fa5cac2a8aa20638909210443278fa138e/5.3.4/platform010/9079c97
|
||||
@@ -137,11 +137,11 @@ then
|
||||
# should be relevant for formatting fixes.
|
||||
FORMAT_UPSTREAM_MERGE_BASE="$(git merge-base "$FORMAT_UPSTREAM" HEAD)"
|
||||
# Get the differences
|
||||
diffs=$(git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" | $CLANG_FORMAT_DIFF -p 1)
|
||||
diffs=$(git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" | $CLANG_FORMAT_DIFF -p 1) || true
|
||||
echo "Checking format of changes not yet in $FORMAT_UPSTREAM..."
|
||||
else
|
||||
# Check the format of uncommitted lines,
|
||||
diffs=$(git diff -U0 HEAD | $CLANG_FORMAT_DIFF -p 1)
|
||||
diffs=$(git diff -U0 HEAD | $CLANG_FORMAT_DIFF -p 1) || true
|
||||
echo "Checking format of uncommitted changes..."
|
||||
fi
|
||||
|
||||
@@ -149,6 +149,9 @@ if [ -z "$diffs" ]
|
||||
then
|
||||
echo "Nothing needs to be reformatted!"
|
||||
exit 0
|
||||
elif [ $? -ne 1 ]; then
|
||||
# CLANG_FORMAT_DIFF will exit on 1 while there is suggested changes.
|
||||
exit $?
|
||||
elif [ $CHECK_ONLY ]
|
||||
then
|
||||
echo "Your change has unformatted code. Please run make format!"
|
||||
|
||||
@@ -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{'TRAVIS'};
|
||||
$Global::is_terminal = (-t $Global::original_stderr) && !$ENV{'CIRCLECI'}&& !$ENV{'GITHUB_ACTIONS'} && !$ENV{'TRAVIS'};
|
||||
}
|
||||
|
||||
sub enough_file_handles {
|
||||
|
||||
@@ -75,8 +75,8 @@ touch "$OUTPUT"
|
||||
echo "Writing dependencies to $OUTPUT"
|
||||
|
||||
# Compilers locations
|
||||
GCC_BASE=`readlink -f $TP2_LATEST/gcc/11.x/centos7-native/*/`
|
||||
CLANG_BASE=`readlink -f $TP2_LATEST/llvm-fb/12/platform010/*/`
|
||||
GCC_BASE=`readlink -f $TP2_LATEST/gcc/11.x/centos8-native/*/`
|
||||
CLANG_BASE=`readlink -f $TP2_LATEST/llvm-fb/15/platform010/*/`
|
||||
|
||||
log_header
|
||||
log_variable GCC_BASE
|
||||
@@ -86,7 +86,7 @@ log_variable CLANG_BASE
|
||||
get_lib_base libgcc 11.x platform010
|
||||
get_lib_base glibc 2.34 platform010
|
||||
get_lib_base snappy LATEST platform010
|
||||
get_lib_base zlib LATEST platform010
|
||||
get_lib_base zlib 1.2.8 platform010
|
||||
get_lib_base bzip2 LATEST platform010
|
||||
get_lib_base lz4 LATEST platform010
|
||||
get_lib_base zstd LATEST platform010
|
||||
@@ -99,7 +99,7 @@ get_lib_base liburing LATEST platform010
|
||||
get_lib_base benchmark LATEST platform010
|
||||
|
||||
get_lib_base kernel-headers fb platform010
|
||||
get_lib_base binutils LATEST centos7-native
|
||||
get_lib_base binutils LATEST centos8-native
|
||||
get_lib_base valgrind LATEST platform010
|
||||
get_lib_base lua 5.3.4 platform010
|
||||
|
||||
|
||||
Vendored
+4
-4
@@ -560,7 +560,7 @@ void BaseClockTable::TrackAndReleaseEvictedEntry(ClockHandle* h) {
|
||||
took_value_ownership =
|
||||
eviction_callback_(ClockCacheShard<FixedHyperClockTable>::ReverseHash(
|
||||
h->GetHash(), &unhashed, hash_seed_),
|
||||
reinterpret_cast<Cache::Handle*>(h),
|
||||
static_cast<Cache::Handle*>(h),
|
||||
h->meta.LoadRelaxed() & ClockHandle::kHitBitMask);
|
||||
}
|
||||
if (!took_value_ownership) {
|
||||
@@ -1428,19 +1428,19 @@ BaseHyperClockCache<Table>::BaseHyperClockCache(
|
||||
|
||||
template <class Table>
|
||||
Cache::ObjectPtr BaseHyperClockCache<Table>::Value(Handle* handle) {
|
||||
return reinterpret_cast<const typename Table::HandleImpl*>(handle)->value;
|
||||
return static_cast<const typename Table::HandleImpl*>(handle)->value;
|
||||
}
|
||||
|
||||
template <class Table>
|
||||
size_t BaseHyperClockCache<Table>::GetCharge(Handle* handle) const {
|
||||
return reinterpret_cast<const typename Table::HandleImpl*>(handle)
|
||||
return static_cast<const typename Table::HandleImpl*>(handle)
|
||||
->GetTotalCharge();
|
||||
}
|
||||
|
||||
template <class Table>
|
||||
const Cache::CacheItemHelper* BaseHyperClockCache<Table>::GetCacheItemHelper(
|
||||
Handle* handle) const {
|
||||
auto h = reinterpret_cast<const typename Table::HandleImpl*>(handle);
|
||||
auto h = static_cast<const typename Table::HandleImpl*>(handle);
|
||||
return h->helper;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -298,7 +298,7 @@ class ClockCacheTest;
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
struct ClockHandleBasicData {
|
||||
struct ClockHandleBasicData : public Cache::Handle {
|
||||
Cache::ObjectPtr value = nullptr;
|
||||
const Cache::CacheItemHelper* helper = nullptr;
|
||||
// A lossless, reversible hash of the fixed-size (16 byte) cache key. This
|
||||
|
||||
Vendored
+9
-4
@@ -192,13 +192,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,
|
||||
compression_opts);
|
||||
cache_options_.compression_opts);
|
||||
uint64_t sample_for_compression{0};
|
||||
CompressionInfo compression_info(
|
||||
compression_opts, compression_context, CompressionDict::GetEmptyDict(),
|
||||
cache_options_.compression_type, sample_for_compression);
|
||||
cache_options_.compression_opts, compression_context,
|
||||
CompressionDict::GetEmptyDict(), cache_options_.compression_type,
|
||||
sample_for_compression);
|
||||
|
||||
bool success =
|
||||
CompressData(val, compression_info,
|
||||
@@ -291,6 +291,11 @@ 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);
|
||||
|
||||
+5
-5
@@ -1062,7 +1062,7 @@ bool CacheUsageWithinBounds(size_t val1, size_t val2, size_t error) {
|
||||
|
||||
TEST_P(CompressedSecCacheTestWithTiered, CacheReservationManager) {
|
||||
CompressedSecondaryCache* sec_cache =
|
||||
reinterpret_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
static_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
|
||||
// Use EXPECT_PRED3 instead of EXPECT_NEAR to void too many size_t to
|
||||
// double explicit casts
|
||||
@@ -1085,7 +1085,7 @@ TEST_P(CompressedSecCacheTestWithTiered, CacheReservationManager) {
|
||||
TEST_P(CompressedSecCacheTestWithTiered,
|
||||
CacheReservationManagerMultipleUpdate) {
|
||||
CompressedSecondaryCache* sec_cache =
|
||||
reinterpret_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
static_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
|
||||
EXPECT_PRED3(CacheUsageWithinBounds, GetCache()->GetUsage(), (30 << 20),
|
||||
GetPercent(30 << 20, 1));
|
||||
@@ -1171,7 +1171,7 @@ TEST_P(CompressedSecCacheTestWithTiered, AdmissionPolicy) {
|
||||
|
||||
TEST_P(CompressedSecCacheTestWithTiered, DynamicUpdate) {
|
||||
CompressedSecondaryCache* sec_cache =
|
||||
reinterpret_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
static_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
std::shared_ptr<Cache> tiered_cache = GetTieredCache();
|
||||
|
||||
// Use EXPECT_PRED3 instead of EXPECT_NEAR to void too many size_t to
|
||||
@@ -1235,7 +1235,7 @@ TEST_P(CompressedSecCacheTestWithTiered, DynamicUpdate) {
|
||||
|
||||
TEST_P(CompressedSecCacheTestWithTiered, DynamicUpdateWithReservation) {
|
||||
CompressedSecondaryCache* sec_cache =
|
||||
reinterpret_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
static_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
std::shared_ptr<Cache> tiered_cache = GetTieredCache();
|
||||
|
||||
ASSERT_OK(cache_res_mgr()->UpdateCacheReservation(10 << 20));
|
||||
@@ -1329,7 +1329,7 @@ TEST_P(CompressedSecCacheTestWithTiered, DynamicUpdateWithReservation) {
|
||||
|
||||
TEST_P(CompressedSecCacheTestWithTiered, ReservationOverCapacity) {
|
||||
CompressedSecondaryCache* sec_cache =
|
||||
reinterpret_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
static_cast<CompressedSecondaryCache*>(GetSecondaryCache());
|
||||
std::shared_ptr<Cache> tiered_cache = GetTieredCache();
|
||||
|
||||
ASSERT_OK(cache_res_mgr()->UpdateCacheReservation(110 << 20));
|
||||
|
||||
Vendored
+5
-6
@@ -339,8 +339,7 @@ void LRUCacheShard::NotifyEvicted(
|
||||
MemoryAllocator* alloc = table_.GetAllocator();
|
||||
for (LRUHandle* entry : evicted_handles) {
|
||||
if (eviction_callback_ &&
|
||||
eviction_callback_(entry->key(),
|
||||
reinterpret_cast<Cache::Handle*>(entry),
|
||||
eviction_callback_(entry->key(), static_cast<Cache::Handle*>(entry),
|
||||
entry->HasHit())) {
|
||||
// Callback took ownership of obj; just free handle
|
||||
free(entry);
|
||||
@@ -506,7 +505,7 @@ bool LRUCacheShard::Release(LRUHandle* e, bool /*useful*/,
|
||||
// Only call eviction callback if we're sure no one requested erasure
|
||||
// FIXME: disabled because of test churn
|
||||
if (false && was_in_cache && !erase_if_last_ref && eviction_callback_ &&
|
||||
eviction_callback_(e->key(), reinterpret_cast<Cache::Handle*>(e),
|
||||
eviction_callback_(e->key(), static_cast<Cache::Handle*>(e),
|
||||
e->HasHit())) {
|
||||
// Callback took ownership of obj; just free handle
|
||||
free(e);
|
||||
@@ -661,18 +660,18 @@ LRUCache::LRUCache(const LRUCacheOptions& opts) : ShardedCache(opts) {
|
||||
}
|
||||
|
||||
Cache::ObjectPtr LRUCache::Value(Handle* handle) {
|
||||
auto h = reinterpret_cast<const LRUHandle*>(handle);
|
||||
auto h = static_cast<const LRUHandle*>(handle);
|
||||
return h->value;
|
||||
}
|
||||
|
||||
size_t LRUCache::GetCharge(Handle* handle) const {
|
||||
return reinterpret_cast<const LRUHandle*>(handle)->GetCharge(
|
||||
return static_cast<const LRUHandle*>(handle)->GetCharge(
|
||||
GetShard(0).metadata_charge_policy_);
|
||||
}
|
||||
|
||||
const Cache::CacheItemHelper* LRUCache::GetCacheItemHelper(
|
||||
Handle* handle) const {
|
||||
auto h = reinterpret_cast<const LRUHandle*>(handle);
|
||||
auto h = static_cast<const LRUHandle*>(handle);
|
||||
return h->helper;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -47,7 +47,7 @@ namespace lru_cache {
|
||||
// LRUCacheShard::Lookup.
|
||||
// While refs > 0, public properties like value and deleter must not change.
|
||||
|
||||
struct LRUHandle {
|
||||
struct LRUHandle : public Cache::Handle {
|
||||
Cache::ObjectPtr value;
|
||||
const Cache::CacheItemHelper* helper;
|
||||
LRUHandle* next_hash;
|
||||
|
||||
Vendored
+2
-3
@@ -47,7 +47,7 @@ class LRUCacheTest : public testing::Test {
|
||||
double low_pri_pool_ratio = 1.0,
|
||||
bool use_adaptive_mutex = kDefaultToAdaptiveMutex) {
|
||||
DeleteCache();
|
||||
cache_ = reinterpret_cast<LRUCacheShard*>(
|
||||
cache_ = static_cast<LRUCacheShard*>(
|
||||
port::cacheline_aligned_alloc(sizeof(LRUCacheShard)));
|
||||
new (cache_) LRUCacheShard(capacity, /*strict_capacity_limit=*/false,
|
||||
high_pri_pool_ratio, low_pri_pool_ratio,
|
||||
@@ -392,8 +392,7 @@ class ClockCacheTest : public testing::Test {
|
||||
void NewShard(size_t capacity, bool strict_capacity_limit = true,
|
||||
int eviction_effort_cap = 30) {
|
||||
DeleteShard();
|
||||
shard_ =
|
||||
reinterpret_cast<Shard*>(port::cacheline_aligned_alloc(sizeof(Shard)));
|
||||
shard_ = static_cast<Shard*>(port::cacheline_aligned_alloc(sizeof(Shard)));
|
||||
|
||||
TableOpts opts{1 /*value_size*/, eviction_effort_cap};
|
||||
new (shard_)
|
||||
|
||||
Vendored
+6
-6
@@ -139,7 +139,7 @@ class ShardedCache : public ShardedCacheBase {
|
||||
|
||||
explicit ShardedCache(const ShardedCacheOptions& opts)
|
||||
: ShardedCacheBase(opts),
|
||||
shards_(reinterpret_cast<CacheShard*>(port::cacheline_aligned_alloc(
|
||||
shards_(static_cast<CacheShard*>(port::cacheline_aligned_alloc(
|
||||
sizeof(CacheShard) * GetNumShards()))),
|
||||
destroy_shards_in_dtor_(false) {}
|
||||
|
||||
@@ -192,7 +192,7 @@ class ShardedCache : public ShardedCacheBase {
|
||||
HashVal hash = CacheShard::ComputeHash(key, hash_seed_);
|
||||
HandleImpl* result = GetShard(hash).CreateStandalone(
|
||||
key, hash, obj, helper, charge, allow_uncharged);
|
||||
return reinterpret_cast<Handle*>(result);
|
||||
return static_cast<Handle*>(result);
|
||||
}
|
||||
|
||||
Handle* Lookup(const Slice& key, const CacheItemHelper* helper = nullptr,
|
||||
@@ -202,7 +202,7 @@ class ShardedCache : public ShardedCacheBase {
|
||||
HashVal hash = CacheShard::ComputeHash(key, hash_seed_);
|
||||
HandleImpl* result = GetShard(hash).Lookup(key, hash, helper,
|
||||
create_context, priority, stats);
|
||||
return reinterpret_cast<Handle*>(result);
|
||||
return static_cast<Handle*>(result);
|
||||
}
|
||||
|
||||
void Erase(const Slice& key) override {
|
||||
@@ -212,11 +212,11 @@ class ShardedCache : public ShardedCacheBase {
|
||||
|
||||
bool Release(Handle* handle, bool useful,
|
||||
bool erase_if_last_ref = false) override {
|
||||
auto h = reinterpret_cast<HandleImpl*>(handle);
|
||||
auto h = static_cast<HandleImpl*>(handle);
|
||||
return GetShard(h->GetHash()).Release(h, useful, erase_if_last_ref);
|
||||
}
|
||||
bool Ref(Handle* handle) override {
|
||||
auto h = reinterpret_cast<HandleImpl*>(handle);
|
||||
auto h = static_cast<HandleImpl*>(handle);
|
||||
return GetShard(h->GetHash()).Ref(h);
|
||||
}
|
||||
bool Release(Handle* handle, bool erase_if_last_ref = false) override {
|
||||
@@ -259,7 +259,7 @@ class ShardedCache : public ShardedCacheBase {
|
||||
} while (remaining_work);
|
||||
}
|
||||
|
||||
virtual void EraseUnRefEntries() override {
|
||||
void EraseUnRefEntries() override {
|
||||
ForEachShard([](CacheShard* cs) { cs->EraseUnRefEntries(); });
|
||||
}
|
||||
|
||||
|
||||
Vendored
+8
-10
@@ -42,27 +42,25 @@ class TieredSecondaryCache : public SecondaryCacheWrapper {
|
||||
|
||||
// This is a no-op as we currently don't allow demotion (i.e
|
||||
// insertion by the upper layer) of evicted blocks.
|
||||
virtual Status Insert(const Slice& /*key*/, Cache::ObjectPtr /*obj*/,
|
||||
const Cache::CacheItemHelper* /*helper*/,
|
||||
bool /*force_insert*/) override {
|
||||
Status Insert(const Slice& /*key*/, Cache::ObjectPtr /*obj*/,
|
||||
const Cache::CacheItemHelper* /*helper*/,
|
||||
bool /*force_insert*/) override {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Warm up the nvm tier directly
|
||||
virtual Status InsertSaved(
|
||||
const Slice& key, const Slice& saved,
|
||||
CompressionType type = CompressionType::kNoCompression,
|
||||
CacheTier source = CacheTier::kVolatileTier) override {
|
||||
Status InsertSaved(const Slice& key, const Slice& saved,
|
||||
CompressionType type = CompressionType::kNoCompression,
|
||||
CacheTier source = CacheTier::kVolatileTier) override {
|
||||
return nvm_sec_cache_->InsertSaved(key, saved, type, source);
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<SecondaryCacheResultHandle> Lookup(
|
||||
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;
|
||||
|
||||
virtual void WaitAll(
|
||||
std::vector<SecondaryCacheResultHandle*> handles) override;
|
||||
void WaitAll(std::vector<SecondaryCacheResultHandle*> handles) override;
|
||||
|
||||
private:
|
||||
struct CreateContext : public Cache::CreateContext {
|
||||
|
||||
Vendored
+3
-4
@@ -155,7 +155,7 @@ class BasicTypedCacheInterface : public BaseCacheInterface<CachePtr>,
|
||||
using BaseCacheInterface<CachePtr>::BaseCacheInterface;
|
||||
struct TypedAsyncLookupHandle : public Cache::AsyncLookupHandle {
|
||||
TypedHandle* Result() {
|
||||
return reinterpret_cast<TypedHandle*>(Cache::AsyncLookupHandle::Result());
|
||||
return static_cast<TypedHandle*>(Cache::AsyncLookupHandle::Result());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -169,8 +169,7 @@ class BasicTypedCacheInterface : public BaseCacheInterface<CachePtr>,
|
||||
}
|
||||
|
||||
inline TypedHandle* Lookup(const Slice& key, Statistics* stats = nullptr) {
|
||||
return reinterpret_cast<TypedHandle*>(
|
||||
this->cache_->BasicLookup(key, stats));
|
||||
return static_cast<TypedHandle*>(this->cache_->BasicLookup(key, stats));
|
||||
}
|
||||
|
||||
inline void StartAsyncLookup(TypedAsyncLookupHandle& async_handle) {
|
||||
@@ -347,7 +346,7 @@ class FullTypedCacheInterface
|
||||
Priority priority = Priority::LOW, Statistics* stats = nullptr,
|
||||
CacheTier lowest_used_cache_tier = CacheTier::kNonVolatileBlockTier) {
|
||||
if (lowest_used_cache_tier > CacheTier::kVolatileTier) {
|
||||
return reinterpret_cast<TypedHandle*>(this->cache_->Lookup(
|
||||
return static_cast<TypedHandle*>(this->cache_->Lookup(
|
||||
key, GetFullHelper(), create_context, priority, stats));
|
||||
} else {
|
||||
return BasicTypedCacheInterface<TValue, kRole, CachePtr>::Lookup(key,
|
||||
|
||||
@@ -14,7 +14,7 @@ find_library(zstd_LIBRARIES
|
||||
HINTS ${zstd_ROOT_DIR}/lib)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(zstd DEFAULT_MSG zstd_LIBRARIES zstd_INCLUDE_DIRS)
|
||||
find_package_handle_standard_args(zstd DEFAULT_MSG zstd_LIBRARIES ZSTD_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(
|
||||
zstd_LIBRARIES
|
||||
|
||||
@@ -118,7 +118,7 @@ class ArenaWrappedDBIter : public Iterator {
|
||||
// Generate the arena wrapped iterator class.
|
||||
// `db_impl` and `cfd` are used for reneweal. If left null, renewal will not
|
||||
// be supported.
|
||||
extern ArenaWrappedDBIter* NewArenaWrappedDbIterator(
|
||||
ArenaWrappedDBIter* NewArenaWrappedDbIterator(
|
||||
Env* env, const ReadOptions& read_options, const ImmutableOptions& ioptions,
|
||||
const MutableCFOptions& mutable_cf_options, const Version* version,
|
||||
const SequenceNumber& sequence, uint64_t max_sequential_skip_in_iterations,
|
||||
|
||||
@@ -34,9 +34,9 @@ BlobFileBuilder::BlobFileBuilder(
|
||||
VersionSet* versions, FileSystem* fs,
|
||||
const ImmutableOptions* immutable_options,
|
||||
const MutableCFOptions* mutable_cf_options, 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 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,
|
||||
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,
|
||||
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) {}
|
||||
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) {}
|
||||
|
||||
BlobFileBuilder::BlobFileBuilder(
|
||||
std::function<uint64_t()> file_number_generator, FileSystem* fs,
|
||||
const ImmutableOptions* immutable_options,
|
||||
const MutableCFOptions* mutable_cf_options, 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 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,
|
||||
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,6 +87,7 @@ 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_);
|
||||
@@ -207,14 +208,14 @@ Status BlobFileBuilder::OpenBlobFileIfNeeded() {
|
||||
blob_file_paths_->emplace_back(std::move(blob_file_path));
|
||||
|
||||
assert(file);
|
||||
file->SetIOPriority(io_priority_);
|
||||
file->SetIOPriority(write_options_->rate_limiter_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,
|
||||
immutable_options_->listeners,
|
||||
Histograms::BLOB_DB_BLOB_FILE_WRITE_MICROS, immutable_options_->listeners,
|
||||
immutable_options_->file_checksum_gen_factory.get(),
|
||||
tmp_set.Contains(FileType::kBlobFile), false));
|
||||
|
||||
@@ -231,7 +232,7 @@ Status BlobFileBuilder::OpenBlobFileIfNeeded() {
|
||||
expiration_range);
|
||||
|
||||
{
|
||||
Status s = blob_log_writer->WriteHeader(header);
|
||||
Status s = blob_log_writer->WriteHeader(*write_options_, header);
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"BlobFileBuilder::OpenBlobFileIfNeeded:WriteHeader", &s);
|
||||
@@ -296,7 +297,8 @@ Status BlobFileBuilder::WriteBlobToFile(const Slice& key, const Slice& blob,
|
||||
|
||||
uint64_t key_offset = 0;
|
||||
|
||||
Status s = writer_->AddRecord(key, blob, &key_offset, blob_offset);
|
||||
Status s =
|
||||
writer_->AddRecord(*write_options_, key, blob, &key_offset, blob_offset);
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("BlobFileBuilder::WriteBlobToFile:AddRecord", &s);
|
||||
|
||||
@@ -321,7 +323,8 @@ Status BlobFileBuilder::CloseBlobFile() {
|
||||
std::string checksum_method;
|
||||
std::string checksum_value;
|
||||
|
||||
Status s = writer_->AppendFooter(footer, &checksum_method, &checksum_value);
|
||||
Status s = writer_->AppendFooter(*write_options_, footer, &checksum_method,
|
||||
&checksum_value);
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("BlobFileBuilder::WriteBlobToFile:AppendFooter", &s);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#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"
|
||||
|
||||
@@ -36,11 +37,11 @@ class BlobFileBuilder {
|
||||
BlobFileBuilder(VersionSet* versions, FileSystem* fs,
|
||||
const ImmutableOptions* immutable_options,
|
||||
const MutableCFOptions* mutable_cf_options,
|
||||
const FileOptions* file_options, std::string db_id,
|
||||
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::IOPriority io_priority,
|
||||
Env::WriteLifeTimeHint write_hint,
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
BlobFileCompletionCallback* blob_callback,
|
||||
@@ -51,11 +52,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, std::string db_id,
|
||||
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::IOPriority io_priority,
|
||||
Env::WriteLifeTimeHint write_hint,
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
BlobFileCompletionCallback* blob_callback,
|
||||
@@ -92,12 +93,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,6 +43,7 @@ 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,
|
||||
@@ -113,6 +114,7 @@ class BlobFileBuilderTest : public testing::Test {
|
||||
FileSystem* fs_;
|
||||
SystemClock* clock_;
|
||||
FileOptions file_options_;
|
||||
WriteOptions write_options_;
|
||||
};
|
||||
|
||||
TEST_F(BlobFileBuilderTest, BuildAndCheckOneFile) {
|
||||
@@ -136,7 +138,6 @@ 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;
|
||||
@@ -144,8 +145,8 @@ TEST_F(BlobFileBuilderTest, BuildAndCheckOneFile) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -221,7 +222,6 @@ 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_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -309,7 +309,6 @@ 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;
|
||||
@@ -317,8 +316,8 @@ TEST_F(BlobFileBuilderTest, InlinedValues) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -364,7 +363,6 @@ 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;
|
||||
@@ -372,8 +370,8 @@ TEST_F(BlobFileBuilderTest, Compression) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -448,7 +446,6 @@ 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;
|
||||
@@ -456,8 +453,8 @@ TEST_F(BlobFileBuilderTest, CompressionError) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -528,7 +525,6 @@ 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;
|
||||
@@ -536,8 +532,8 @@ TEST_F(BlobFileBuilderTest, Checksum) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, write_hint,
|
||||
nullptr /*IOTracer*/, nullptr /*BlobFileCompletionCallback*/,
|
||||
BlobFileCreationReason::kFlush, &blob_file_paths, &blob_file_additions);
|
||||
|
||||
@@ -589,11 +585,13 @@ 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_;
|
||||
};
|
||||
|
||||
@@ -626,7 +624,6 @@ 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;
|
||||
@@ -634,8 +631,8 @@ TEST_P(BlobFileBuilderIOErrorTest, IOError) {
|
||||
|
||||
BlobFileBuilder builder(
|
||||
TestFileNumberGenerator(), fs_, &immutable_options, &mutable_cf_options,
|
||||
&file_options_, "" /*db_id*/, "" /*db_session_id*/, job_id,
|
||||
column_family_id, column_family_name, io_priority, write_hint,
|
||||
&file_options_, &write_options_, "" /*db_id*/, "" /*db_session_id*/,
|
||||
job_id, column_family_id, column_family_name, 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(header));
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(WriteOptions(), header));
|
||||
|
||||
constexpr char key[] = "key";
|
||||
constexpr char blob[] = "blob";
|
||||
@@ -67,7 +67,8 @@ void WriteBlobFile(uint32_t column_family_id,
|
||||
uint64_t key_offset = 0;
|
||||
uint64_t blob_offset = 0;
|
||||
|
||||
ASSERT_OK(blob_log_writer.AddRecord(key, blob, &key_offset, &blob_offset));
|
||||
ASSERT_OK(blob_log_writer.AddRecord(WriteOptions(), key, blob, &key_offset,
|
||||
&blob_offset));
|
||||
|
||||
BlobLogFooter footer;
|
||||
footer.blob_count = 1;
|
||||
@@ -76,8 +77,8 @@ void WriteBlobFile(uint32_t column_family_id,
|
||||
std::string checksum_method;
|
||||
std::string checksum_value;
|
||||
|
||||
ASSERT_OK(
|
||||
blob_log_writer.AppendFooter(footer, &checksum_method, &checksum_value));
|
||||
ASSERT_OK(blob_log_writer.AppendFooter(WriteOptions(), 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(header));
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(WriteOptions(), header));
|
||||
|
||||
std::vector<std::string> compressed_blobs(num);
|
||||
std::vector<Slice> blobs_to_write(num);
|
||||
@@ -91,7 +91,8 @@ 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(keys[i], blobs_to_write[i], &key_offset,
|
||||
ASSERT_OK(blob_log_writer.AddRecord(WriteOptions(), keys[i],
|
||||
blobs_to_write[i], &key_offset,
|
||||
&blob_offsets[i]));
|
||||
}
|
||||
|
||||
@@ -101,8 +102,8 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
|
||||
std::string checksum_method;
|
||||
std::string checksum_value;
|
||||
ASSERT_OK(
|
||||
blob_log_writer.AppendFooter(footer, &checksum_method, &checksum_value));
|
||||
ASSERT_OK(blob_log_writer.AppendFooter(WriteOptions(), footer,
|
||||
&checksum_method, &checksum_value));
|
||||
}
|
||||
|
||||
// Creates a test blob file with a single blob in it. Note: this method
|
||||
@@ -473,7 +474,7 @@ TEST_F(BlobFileReaderTest, Malformed) {
|
||||
BlobLogHeader header(column_family_id, kNoCompression, has_ttl,
|
||||
expiration_range);
|
||||
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(header));
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(WriteOptions(), header));
|
||||
}
|
||||
|
||||
constexpr HistogramImpl* blob_file_read_hist = nullptr;
|
||||
|
||||
+56
-27
@@ -33,35 +33,49 @@ BlobLogWriter::BlobLogWriter(std::unique_ptr<WritableFileWriter>&& dest,
|
||||
|
||||
BlobLogWriter::~BlobLogWriter() = default;
|
||||
|
||||
Status BlobLogWriter::Sync() {
|
||||
Status BlobLogWriter::Sync(const WriteOptions& write_options) {
|
||||
TEST_SYNC_POINT("BlobLogWriter::Sync");
|
||||
|
||||
StopWatch sync_sw(clock_, statistics_, BLOB_DB_BLOB_FILE_SYNC_MICROS);
|
||||
Status s = dest_->Sync(use_fsync_);
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_SYNCED);
|
||||
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);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Status BlobLogWriter::WriteHeader(BlobLogHeader& header) {
|
||||
Status BlobLogWriter::WriteHeader(const WriteOptions& write_options,
|
||||
BlobLogHeader& header) {
|
||||
assert(block_offset_ == 0);
|
||||
assert(last_elem_type_ == kEtNone);
|
||||
std::string str;
|
||||
header.EncodeTo(&str);
|
||||
|
||||
Status s = dest_->Append(Slice(str));
|
||||
IOOptions opts;
|
||||
Status s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(opts, Slice(str));
|
||||
}
|
||||
if (s.ok()) {
|
||||
block_offset_ += str.size();
|
||||
if (do_flush_) {
|
||||
s = dest_->Flush();
|
||||
s = dest_->Flush(opts);
|
||||
}
|
||||
}
|
||||
last_elem_type_ = kEtFileHdr;
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogHeader::kSize);
|
||||
if (s.ok()) {
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogHeader::kSize);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Status BlobLogWriter::AppendFooter(BlobLogFooter& footer,
|
||||
Status BlobLogWriter::AppendFooter(const WriteOptions& write_options,
|
||||
BlobLogFooter& footer,
|
||||
std::string* checksum_method,
|
||||
std::string* checksum_value) {
|
||||
assert(block_offset_ != 0);
|
||||
@@ -75,14 +89,17 @@ Status BlobLogWriter::AppendFooter(BlobLogFooter& footer,
|
||||
s.PermitUncheckedError();
|
||||
return Status::IOError("Seen Error. Skip closing.");
|
||||
} else {
|
||||
s = dest_->Append(Slice(str));
|
||||
IOOptions opts;
|
||||
s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(opts, Slice(str));
|
||||
}
|
||||
if (s.ok()) {
|
||||
block_offset_ += str.size();
|
||||
|
||||
s = Sync();
|
||||
s = Sync(write_options);
|
||||
|
||||
if (s.ok()) {
|
||||
s = dest_->Close();
|
||||
s = dest_->Close(opts);
|
||||
|
||||
if (s.ok()) {
|
||||
assert(!!checksum_method == !!checksum_value);
|
||||
@@ -111,12 +128,15 @@ Status BlobLogWriter::AppendFooter(BlobLogFooter& footer,
|
||||
}
|
||||
|
||||
last_elem_type_ = kEtFileFooter;
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogFooter::kSize);
|
||||
if (s.ok()) {
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogFooter::kSize);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Status BlobLogWriter::AddRecord(const Slice& key, const Slice& val,
|
||||
Status BlobLogWriter::AddRecord(const WriteOptions& write_options,
|
||||
const Slice& key, const Slice& val,
|
||||
uint64_t expiration, uint64_t* key_offset,
|
||||
uint64_t* blob_offset) {
|
||||
assert(block_offset_ != 0);
|
||||
@@ -125,11 +145,13 @@ Status BlobLogWriter::AddRecord(const Slice& key, const Slice& val,
|
||||
std::string buf;
|
||||
ConstructBlobHeader(&buf, key, val, expiration);
|
||||
|
||||
Status s = EmitPhysicalRecord(buf, key, val, key_offset, blob_offset);
|
||||
Status s =
|
||||
EmitPhysicalRecord(write_options, buf, key, val, key_offset, blob_offset);
|
||||
return s;
|
||||
}
|
||||
|
||||
Status BlobLogWriter::AddRecord(const Slice& key, const Slice& val,
|
||||
Status BlobLogWriter::AddRecord(const WriteOptions& write_options,
|
||||
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);
|
||||
@@ -137,7 +159,8 @@ Status BlobLogWriter::AddRecord(const Slice& key, const Slice& val,
|
||||
std::string buf;
|
||||
ConstructBlobHeader(&buf, key, val, 0);
|
||||
|
||||
Status s = EmitPhysicalRecord(buf, key, val, key_offset, blob_offset);
|
||||
Status s =
|
||||
EmitPhysicalRecord(write_options, buf, key, val, key_offset, blob_offset);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -150,28 +173,34 @@ void BlobLogWriter::ConstructBlobHeader(std::string* buf, const Slice& key,
|
||||
record.EncodeHeaderTo(buf);
|
||||
}
|
||||
|
||||
Status BlobLogWriter::EmitPhysicalRecord(const std::string& headerbuf,
|
||||
Status BlobLogWriter::EmitPhysicalRecord(const WriteOptions& write_options,
|
||||
const std::string& headerbuf,
|
||||
const Slice& key, const Slice& val,
|
||||
uint64_t* key_offset,
|
||||
uint64_t* blob_offset) {
|
||||
StopWatch write_sw(clock_, statistics_, BLOB_DB_BLOB_FILE_WRITE_MICROS);
|
||||
Status s = dest_->Append(Slice(headerbuf));
|
||||
IOOptions opts;
|
||||
Status s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(key);
|
||||
s = dest_->Append(opts, Slice(headerbuf));
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(val);
|
||||
s = dest_->Append(opts, key);
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(opts, val);
|
||||
}
|
||||
if (do_flush_ && s.ok()) {
|
||||
s = dest_->Flush();
|
||||
s = dest_->Flush(opts);
|
||||
}
|
||||
|
||||
*key_offset = block_offset_ + BlobLogRecord::kHeaderSize;
|
||||
*blob_offset = *key_offset + key.size();
|
||||
block_offset_ = *blob_offset + val.size();
|
||||
last_elem_type_ = kEtRecord;
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogRecord::kHeaderSize + key.size() + val.size());
|
||||
if (s.ok()) {
|
||||
RecordTick(statistics_, BLOB_DB_BLOB_FILE_BYTES_WRITTEN,
|
||||
BlobLogRecord::kHeaderSize + key.size() + val.size());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,20 +43,24 @@ class BlobLogWriter {
|
||||
static void ConstructBlobHeader(std::string* buf, const Slice& key,
|
||||
const Slice& val, uint64_t expiration);
|
||||
|
||||
Status AddRecord(const Slice& key, const Slice& val, uint64_t* key_offset,
|
||||
Status AddRecord(const WriteOptions& write_options, const Slice& key,
|
||||
const Slice& val, 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 AddRecord(const WriteOptions& write_options, const Slice& key,
|
||||
const Slice& val, uint64_t expiration, uint64_t* key_offset,
|
||||
uint64_t* blob_offset);
|
||||
|
||||
Status EmitPhysicalRecord(const std::string& headerbuf, const Slice& key,
|
||||
Status EmitPhysicalRecord(const WriteOptions& write_options,
|
||||
const std::string& headerbuf, const Slice& key,
|
||||
const Slice& val, uint64_t* key_offset,
|
||||
uint64_t* blob_offset);
|
||||
|
||||
Status AppendFooter(BlobLogFooter& footer, std::string* checksum_method,
|
||||
Status AppendFooter(const WriteOptions& write_options, BlobLogFooter& footer,
|
||||
std::string* checksum_method,
|
||||
std::string* checksum_value);
|
||||
|
||||
Status WriteHeader(BlobLogHeader& header);
|
||||
Status WriteHeader(const WriteOptions& write_options, BlobLogHeader& header);
|
||||
|
||||
WritableFileWriter* file() { return dest_.get(); }
|
||||
|
||||
@@ -64,7 +68,7 @@ class BlobLogWriter {
|
||||
|
||||
uint64_t get_log_number() const { return log_number_; }
|
||||
|
||||
Status Sync();
|
||||
Status Sync(const WriteOptions& write_options);
|
||||
|
||||
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(header));
|
||||
ASSERT_OK(blob_log_writer.WriteHeader(WriteOptions(), header));
|
||||
|
||||
std::vector<std::string> compressed_blobs(num);
|
||||
std::vector<Slice> blobs_to_write(num);
|
||||
@@ -93,7 +93,8 @@ 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(keys[i], blobs_to_write[i], &key_offset,
|
||||
ASSERT_OK(blob_log_writer.AddRecord(WriteOptions(), keys[i],
|
||||
blobs_to_write[i], &key_offset,
|
||||
&blob_offsets[i]));
|
||||
}
|
||||
|
||||
@@ -103,8 +104,8 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
|
||||
std::string checksum_method;
|
||||
std::string checksum_value;
|
||||
ASSERT_OK(
|
||||
blob_log_writer.AppendFooter(footer, &checksum_method, &checksum_value));
|
||||
ASSERT_OK(blob_log_writer.AppendFooter(WriteOptions(), footer,
|
||||
&checksum_method, &checksum_value));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -325,8 +325,7 @@ TEST_F(DBBlobIndexTest, Iterate) {
|
||||
|
||||
auto check_is_blob = [&](bool is_blob) {
|
||||
return [is_blob](Iterator* iterator) {
|
||||
ASSERT_EQ(is_blob,
|
||||
reinterpret_cast<ArenaWrappedDBIter*>(iterator)->IsBlob());
|
||||
ASSERT_EQ(is_blob, static_cast<ArenaWrappedDBIter*>(iterator)->IsBlob());
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@ FilePrefetchBuffer* PrefetchBufferCollection::GetOrCreatePrefetchBuffer(
|
||||
uint64_t file_number) {
|
||||
auto& prefetch_buffer = prefetch_buffers_[file_number];
|
||||
if (!prefetch_buffer) {
|
||||
prefetch_buffer.reset(
|
||||
new FilePrefetchBuffer(readahead_size_, readahead_size_));
|
||||
ReadaheadParams readahead_params;
|
||||
readahead_params.initial_readahead_size = readahead_size_;
|
||||
readahead_params.max_readahead_size = readahead_size_;
|
||||
prefetch_buffer.reset(new FilePrefetchBuffer(readahead_params));
|
||||
}
|
||||
|
||||
return prefetch_buffer.get();
|
||||
|
||||
+52
-37
@@ -32,9 +32,11 @@
|
||||
#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"
|
||||
@@ -57,8 +59,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, const ReadOptions& read_options,
|
||||
TableCache* table_cache, InternalIterator* iter,
|
||||
const FileOptions& file_options, TableCache* table_cache,
|
||||
InternalIterator* iter,
|
||||
std::vector<std::unique_ptr<FragmentedRangeTombstoneIterator>>
|
||||
range_del_iters,
|
||||
FileMetaData* meta, std::vector<BlobFileAddition>* blob_file_additions,
|
||||
@@ -69,9 +71,8 @@ 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, const Env::IOPriority io_priority,
|
||||
TableProperties* table_properties, Env::WriteLifeTimeHint write_hint,
|
||||
const std::string* full_history_ts_low,
|
||||
int job_id, 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) {
|
||||
@@ -82,11 +83,8 @@ Status BuildTable(
|
||||
auto& ioptions = tboptions.ioptions;
|
||||
// Reports the IOStats for flush for every following bytes.
|
||||
const size_t kReportFlushIOStatsEvery = 1048576;
|
||||
OutputValidator output_validator(
|
||||
tboptions.internal_comparator,
|
||||
/*enable_order_check=*/
|
||||
mutable_cf_options.check_flush_compaction_key_order,
|
||||
/*enable_hash=*/paranoid_file_checks);
|
||||
OutputValidator output_validator(tboptions.internal_comparator,
|
||||
/*enable_hash=*/paranoid_file_checks);
|
||||
Status s;
|
||||
meta->fd.file_size = 0;
|
||||
iter->SeekToFirst();
|
||||
@@ -164,11 +162,11 @@ Status BuildTable(
|
||||
|
||||
table_file_created = true;
|
||||
FileTypeSet tmp_set = ioptions.checksum_handoff_file_types;
|
||||
file->SetIOPriority(io_priority);
|
||||
file->SetIOPriority(tboptions.write_options.rate_limiter_priority);
|
||||
file->SetWriteLifeTimeHint(write_hint);
|
||||
file_writer.reset(new WritableFileWriter(
|
||||
std::move(file), fname, file_options, ioptions.clock, io_tracer,
|
||||
ioptions.stats, ioptions.listeners,
|
||||
ioptions.stats, Histograms::SST_WRITE_MICROS, ioptions.listeners,
|
||||
ioptions.file_checksum_gen_factory.get(),
|
||||
tmp_set.Contains(FileType::kTableFile), false));
|
||||
|
||||
@@ -188,10 +186,11 @@ Status BuildTable(
|
||||
blob_file_additions)
|
||||
? new BlobFileBuilder(
|
||||
versions, fs, &ioptions, &mutable_cf_options, &file_options,
|
||||
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)
|
||||
&(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)
|
||||
: nullptr);
|
||||
|
||||
const std::atomic<bool> kManualCompactionCanceledFalse{false};
|
||||
@@ -208,7 +207,7 @@ Status BuildTable(
|
||||
/*shutting_down=*/nullptr, db_options.info_log, full_history_ts_low);
|
||||
|
||||
const size_t ts_sz = ucmp->timestamp_size();
|
||||
const bool strip_timestamp =
|
||||
const bool logical_strip_timestamp =
|
||||
ts_sz > 0 && !ioptions.persist_user_defined_timestamps;
|
||||
|
||||
std::string key_after_flush_buf;
|
||||
@@ -222,7 +221,7 @@ Status BuildTable(
|
||||
// the in memory version of the key act logically the same as one with a
|
||||
// minimum timestamp. We update the timestamp here so file boundary and
|
||||
// output validator, block builder all see the effect of the stripping.
|
||||
if (strip_timestamp) {
|
||||
if (logical_strip_timestamp) {
|
||||
key_after_flush_buf.clear();
|
||||
ReplaceInternalKeyWithMinTimestamp(&key_after_flush_buf, key, ts_sz);
|
||||
key_after_flush = key_after_flush_buf;
|
||||
@@ -244,7 +243,11 @@ Status BuildTable(
|
||||
}
|
||||
|
||||
// TODO(noetzli): Update stats after flush, too.
|
||||
if (io_priority == Env::IO_HIGH &&
|
||||
// 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) &&
|
||||
IOSTATS(bytes_written) >= kReportFlushIOStatsEvery) {
|
||||
ThreadStatusUtil::SetThreadOperationProperty(
|
||||
ThreadStatus::FLUSH_BYTES_WRITTEN, IOSTATS(bytes_written));
|
||||
@@ -261,9 +264,12 @@ Status BuildTable(
|
||||
Slice last_tombstone_start_user_key{};
|
||||
for (range_del_it->SeekToFirst(); range_del_it->Valid();
|
||||
range_del_it->Next()) {
|
||||
auto tombstone = range_del_it->Tombstone();
|
||||
auto kv = tombstone.Serialize();
|
||||
// TODO(yuzhangyu): handle range deletion for UDT in memtables only.
|
||||
// When user timestamp should not be persisted, we logically strip a
|
||||
// range tombstone's start and end key's timestamp (replace it with min
|
||||
// timestamp) before passing them along to table builder and to update
|
||||
// file boundaries.
|
||||
auto tombstone = range_del_it->Tombstone(logical_strip_timestamp);
|
||||
std::pair<InternalKey, Slice> kv = tombstone.Serialize();
|
||||
builder->Add(kv.first.Encode(), kv.second);
|
||||
InternalKey tombstone_end = tombstone.SerializeEndKey();
|
||||
meta->UpdateBoundariesForRange(kv.first, tombstone_end, tombstone.seq_,
|
||||
@@ -275,7 +281,7 @@ Status BuildTable(
|
||||
SizeApproximationOptions approx_opts;
|
||||
approx_opts.files_size_error_margin = 0.1;
|
||||
meta->compensated_range_deletion_size += versions->ApproximateSize(
|
||||
approx_opts, read_options, version, kv.first.Encode(),
|
||||
approx_opts, tboptions.read_options, version, kv.first.Encode(),
|
||||
tombstone_end.Encode(), 0 /* start_level */, -1 /* end_level */,
|
||||
TableReaderCaller::kFlush);
|
||||
}
|
||||
@@ -294,12 +300,14 @@ Status BuildTable(
|
||||
if (!s.ok() || empty) {
|
||||
builder->Abandon();
|
||||
} else {
|
||||
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);
|
||||
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);
|
||||
builder->SetSeqnoTimeTableProperties(
|
||||
seqno_to_time_mapping_str,
|
||||
relevant_mapping,
|
||||
ioptions.compaction_style == CompactionStyle::kCompactionStyleFIFO
|
||||
? meta->file_creation_time
|
||||
: meta->oldest_ancester_time);
|
||||
@@ -346,13 +354,16 @@ Status BuildTable(
|
||||
|
||||
// Finish and check for file errors
|
||||
TEST_SYNC_POINT("BuildTable:BeforeSyncTable");
|
||||
if (s.ok() && !empty) {
|
||||
IOOptions opts;
|
||||
*io_status =
|
||||
WritableFileWriter::PrepareIOOptions(tboptions.write_options, opts);
|
||||
if (s.ok() && io_status->ok() && !empty) {
|
||||
StopWatch sw(ioptions.clock, ioptions.stats, TABLE_SYNC_MICROS);
|
||||
*io_status = file_writer->Sync(ioptions.use_fsync);
|
||||
*io_status = file_writer->Sync(opts, ioptions.use_fsync);
|
||||
}
|
||||
TEST_SYNC_POINT("BuildTable:BeforeCloseTableFile");
|
||||
if (s.ok() && io_status->ok() && !empty) {
|
||||
*io_status = file_writer->Close();
|
||||
*io_status = file_writer->Close(opts);
|
||||
}
|
||||
if (s.ok() && io_status->ok() && !empty) {
|
||||
// Add the checksum information to file metadata.
|
||||
@@ -396,9 +407,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(
|
||||
read_options, file_options, tboptions.internal_comparator, *meta,
|
||||
nullptr /* range_del_agg */, mutable_cf_options.prefix_extractor,
|
||||
nullptr,
|
||||
tboptions.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,
|
||||
@@ -411,7 +422,6 @@ Status BuildTable(
|
||||
s = it->status();
|
||||
if (s.ok() && paranoid_file_checks) {
|
||||
OutputValidator file_validator(tboptions.internal_comparator,
|
||||
/*enable_order_check=*/true,
|
||||
/*enable_hash=*/true);
|
||||
for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
||||
// Generate a rolling 64-bit hash of the key and values
|
||||
@@ -436,8 +446,13 @@ Status BuildTable(
|
||||
constexpr IODebugContext* dbg = nullptr;
|
||||
|
||||
if (table_file_created) {
|
||||
Status ignored = fs->DeleteFile(fname, IOOptions(), dbg);
|
||||
ignored.PermitUncheckedError();
|
||||
IOOptions opts;
|
||||
Status prepare =
|
||||
WritableFileWriter::PrepareIOOptions(tboptions.write_options, opts);
|
||||
if (prepare.ok()) {
|
||||
Status ignored = fs->DeleteFile(fname, opts, dbg);
|
||||
ignored.PermitUncheckedError();
|
||||
}
|
||||
}
|
||||
|
||||
assert(blob_file_additions || blob_file_paths.empty());
|
||||
|
||||
+3
-4
@@ -50,11 +50,11 @@ TableBuilder* NewTableBuilder(const TableBuilderOptions& tboptions,
|
||||
//
|
||||
// @param column_family_name Name of the column family that is also identified
|
||||
// by column_family_id, or empty string if unknown.
|
||||
extern Status BuildTable(
|
||||
Status BuildTable(
|
||||
const std::string& dbname, VersionSet* versions,
|
||||
const ImmutableDBOptions& db_options, const TableBuilderOptions& tboptions,
|
||||
const FileOptions& file_options, const ReadOptions& read_options,
|
||||
TableCache* table_cache, InternalIterator* iter,
|
||||
const FileOptions& file_options, TableCache* table_cache,
|
||||
InternalIterator* iter,
|
||||
std::vector<std::unique_ptr<FragmentedRangeTombstoneIterator>>
|
||||
range_del_iters,
|
||||
FileMetaData* meta, std::vector<BlobFileAddition>* blob_file_additions,
|
||||
@@ -66,7 +66,6 @@ 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,
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "rocksdb/utilities/write_batch_with_index.h"
|
||||
#include "rocksdb/write_batch.h"
|
||||
#include "rocksdb/write_buffer_manager.h"
|
||||
#include "util/stderr_logger.h"
|
||||
#include "utilities/merge_operators.h"
|
||||
|
||||
using ROCKSDB_NAMESPACE::BackupEngine;
|
||||
@@ -115,6 +116,7 @@ using ROCKSDB_NAMESPACE::Snapshot;
|
||||
using ROCKSDB_NAMESPACE::SstFileMetaData;
|
||||
using ROCKSDB_NAMESPACE::SstFileWriter;
|
||||
using ROCKSDB_NAMESPACE::Status;
|
||||
using ROCKSDB_NAMESPACE::StderrLogger;
|
||||
using ROCKSDB_NAMESPACE::TablePropertiesCollectorFactory;
|
||||
using ROCKSDB_NAMESPACE::Transaction;
|
||||
using ROCKSDB_NAMESPACE::TransactionDB;
|
||||
@@ -1685,6 +1687,11 @@ void rocksdb_release_snapshot(rocksdb_t* db,
|
||||
delete snapshot;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_snapshot_get_sequence_number(
|
||||
const rocksdb_snapshot_t* snapshot) {
|
||||
return snapshot->rep->GetSequenceNumber();
|
||||
}
|
||||
|
||||
char* rocksdb_property_value(rocksdb_t* db, const char* propname) {
|
||||
std::string tmp;
|
||||
if (db->rep->GetProperty(Slice(propname), &tmp)) {
|
||||
@@ -1872,9 +1879,8 @@ void rocksdb_disable_file_deletions(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->DisableFileDeletions());
|
||||
}
|
||||
|
||||
void rocksdb_enable_file_deletions(rocksdb_t* db, unsigned char force,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->EnableFileDeletions(force));
|
||||
void rocksdb_enable_file_deletions(rocksdb_t* db, char** errptr) {
|
||||
SaveError(errptr, db->rep->EnableFileDeletions());
|
||||
}
|
||||
|
||||
void rocksdb_destroy_db(const rocksdb_options_t* options, const char* name,
|
||||
@@ -2919,6 +2925,23 @@ void rocksdb_options_set_cf_paths(rocksdb_options_t* opt,
|
||||
opt->rep.cf_paths = cf_paths;
|
||||
}
|
||||
|
||||
rocksdb_logger_t* rocksdb_logger_create_stderr_logger(int log_level,
|
||||
const char* prefix) {
|
||||
rocksdb_logger_t* logger = new rocksdb_logger_t;
|
||||
|
||||
if (prefix) {
|
||||
logger->rep = std::make_shared<StderrLogger>(
|
||||
static_cast<InfoLogLevel>(log_level), prefix);
|
||||
} else {
|
||||
logger->rep =
|
||||
std::make_shared<StderrLogger>(static_cast<InfoLogLevel>(log_level));
|
||||
}
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
void rocksdb_logger_destroy(rocksdb_logger_t* logger) { delete logger; }
|
||||
|
||||
void rocksdb_options_set_env(rocksdb_options_t* opt, rocksdb_env_t* env) {
|
||||
opt->rep.env = (env ? env->rep : nullptr);
|
||||
}
|
||||
@@ -2929,6 +2952,12 @@ void rocksdb_options_set_info_log(rocksdb_options_t* opt, rocksdb_logger_t* l) {
|
||||
}
|
||||
}
|
||||
|
||||
rocksdb_logger_t* rocksdb_options_get_info_log(rocksdb_options_t* opt) {
|
||||
rocksdb_logger_t* info_log = new rocksdb_logger_t;
|
||||
info_log->rep = opt->rep.info_log;
|
||||
return info_log;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_info_log_level(rocksdb_options_t* opt, int v) {
|
||||
opt->rep.info_log_level = static_cast<InfoLogLevel>(v);
|
||||
}
|
||||
@@ -3049,6 +3078,14 @@ 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;
|
||||
@@ -3111,7 +3148,7 @@ void rocksdb_options_set_enable_blob_files(rocksdb_options_t* opt,
|
||||
unsigned char val) {
|
||||
opt->rep.enable_blob_files = val;
|
||||
}
|
||||
extern ROCKSDB_LIBRARY_API unsigned char rocksdb_options_get_enable_blob_files(
|
||||
ROCKSDB_LIBRARY_API unsigned char rocksdb_options_get_enable_blob_files(
|
||||
rocksdb_options_t* opt) {
|
||||
return opt->rep.enable_blob_files;
|
||||
}
|
||||
@@ -3483,35 +3520,6 @@ unsigned char rocksdb_options_get_advise_random_on_open(
|
||||
return opt->rep.advise_random_on_open;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_access_hint_on_compaction_start(rocksdb_options_t* opt,
|
||||
int v) {
|
||||
switch (v) {
|
||||
case 0:
|
||||
opt->rep.access_hint_on_compaction_start =
|
||||
ROCKSDB_NAMESPACE::Options::NONE;
|
||||
break;
|
||||
case 1:
|
||||
opt->rep.access_hint_on_compaction_start =
|
||||
ROCKSDB_NAMESPACE::Options::NORMAL;
|
||||
break;
|
||||
case 2:
|
||||
opt->rep.access_hint_on_compaction_start =
|
||||
ROCKSDB_NAMESPACE::Options::SEQUENTIAL;
|
||||
break;
|
||||
case 3:
|
||||
opt->rep.access_hint_on_compaction_start =
|
||||
ROCKSDB_NAMESPACE::Options::WILLNEED;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
int rocksdb_options_get_access_hint_on_compaction_start(
|
||||
rocksdb_options_t* opt) {
|
||||
return opt->rep.access_hint_on_compaction_start;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_use_adaptive_mutex(rocksdb_options_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.use_adaptive_mutex = v;
|
||||
@@ -3997,6 +4005,16 @@ rocksdb_ratelimiter_t* rocksdb_ratelimiter_create_auto_tuned(
|
||||
return rate_limiter;
|
||||
}
|
||||
|
||||
rocksdb_ratelimiter_t* rocksdb_ratelimiter_create_with_mode(
|
||||
int64_t rate_bytes_per_sec, int64_t refill_period_us, int32_t fairness,
|
||||
int mode, bool auto_tuned) {
|
||||
rocksdb_ratelimiter_t* rate_limiter = new rocksdb_ratelimiter_t;
|
||||
rate_limiter->rep.reset(
|
||||
NewGenericRateLimiter(rate_bytes_per_sec, refill_period_us, fairness,
|
||||
static_cast<RateLimiter::Mode>(mode), auto_tuned));
|
||||
return rate_limiter;
|
||||
}
|
||||
|
||||
void rocksdb_ratelimiter_destroy(rocksdb_ratelimiter_t* limiter) {
|
||||
delete limiter;
|
||||
}
|
||||
@@ -4593,7 +4611,7 @@ void rocksdb_readoptions_set_io_timeout(rocksdb_readoptions_t* opt,
|
||||
opt->rep.io_timeout = std::chrono::microseconds(microseconds);
|
||||
}
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_readoptions_get_io_timeout(rocksdb_readoptions_t* opt) {
|
||||
return opt->rep.io_timeout.count();
|
||||
}
|
||||
@@ -5426,9 +5444,7 @@ uint64_t rocksdb_livefiles_deletions(const rocksdb_livefiles_t* lf, int index) {
|
||||
return lf->rep[index].num_deletions;
|
||||
}
|
||||
|
||||
extern void rocksdb_livefiles_destroy(const rocksdb_livefiles_t* lf) {
|
||||
delete lf;
|
||||
}
|
||||
void rocksdb_livefiles_destroy(const rocksdb_livefiles_t* lf) { delete lf; }
|
||||
|
||||
void rocksdb_get_options_from_string(const rocksdb_options_t* base_options,
|
||||
const char* opts_str,
|
||||
|
||||
+37
-10
@@ -718,6 +718,11 @@ int main(int argc, char** argv) {
|
||||
rocksdb_options_set_ratelimiter(options, rate_limiter);
|
||||
rocksdb_ratelimiter_destroy(rate_limiter);
|
||||
|
||||
rate_limiter = rocksdb_ratelimiter_create_with_mode(1000 * 1024 * 1024,
|
||||
100 * 1000, 10, 0, true);
|
||||
rocksdb_options_set_ratelimiter(options, rate_limiter);
|
||||
rocksdb_ratelimiter_destroy(rate_limiter);
|
||||
|
||||
roptions = rocksdb_readoptions_create();
|
||||
rocksdb_readoptions_set_verify_checksums(roptions, 1);
|
||||
rocksdb_readoptions_set_fill_cache(roptions, 1);
|
||||
@@ -1925,6 +1930,9 @@ 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));
|
||||
|
||||
@@ -2031,8 +2039,6 @@ int main(int argc, char** argv) {
|
||||
rocksdb_options_set_advise_random_on_open(o, 1);
|
||||
CheckCondition(1 == rocksdb_options_get_advise_random_on_open(o));
|
||||
|
||||
rocksdb_options_set_access_hint_on_compaction_start(o, 3);
|
||||
CheckCondition(3 == rocksdb_options_get_access_hint_on_compaction_start(o));
|
||||
|
||||
rocksdb_options_set_use_adaptive_mutex(o, 1);
|
||||
CheckCondition(1 == rocksdb_options_get_use_adaptive_mutex(o));
|
||||
@@ -2228,8 +2234,6 @@ int main(int argc, char** argv) {
|
||||
CheckCondition(18 == rocksdb_options_get_stats_dump_period_sec(copy));
|
||||
CheckCondition(5 == rocksdb_options_get_stats_persist_period_sec(copy));
|
||||
CheckCondition(1 == rocksdb_options_get_advise_random_on_open(copy));
|
||||
CheckCondition(3 ==
|
||||
rocksdb_options_get_access_hint_on_compaction_start(copy));
|
||||
CheckCondition(1 == rocksdb_options_get_use_adaptive_mutex(copy));
|
||||
CheckCondition(19 == rocksdb_options_get_bytes_per_sync(copy));
|
||||
CheckCondition(20 == rocksdb_options_get_wal_bytes_per_sync(copy));
|
||||
@@ -2361,6 +2365,10 @@ 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));
|
||||
@@ -2508,11 +2516,6 @@ int main(int argc, char** argv) {
|
||||
CheckCondition(0 == rocksdb_options_get_advise_random_on_open(copy));
|
||||
CheckCondition(1 == rocksdb_options_get_advise_random_on_open(o));
|
||||
|
||||
rocksdb_options_set_access_hint_on_compaction_start(copy, 2);
|
||||
CheckCondition(2 ==
|
||||
rocksdb_options_get_access_hint_on_compaction_start(copy));
|
||||
CheckCondition(3 == rocksdb_options_get_access_hint_on_compaction_start(o));
|
||||
|
||||
rocksdb_options_set_use_adaptive_mutex(copy, 0);
|
||||
CheckCondition(0 == rocksdb_options_get_use_adaptive_mutex(copy));
|
||||
CheckCondition(1 == rocksdb_options_get_use_adaptive_mutex(o));
|
||||
@@ -2781,6 +2784,30 @@ int main(int argc, char** argv) {
|
||||
rocksdb_memory_allocator_destroy(allocator);
|
||||
}
|
||||
|
||||
StartPhase("stderr_logger");
|
||||
{
|
||||
rocksdb_options_t* o_no_prefix = rocksdb_options_create();
|
||||
rocksdb_logger_t* no_prefix_logger =
|
||||
rocksdb_logger_create_stderr_logger(3, NULL);
|
||||
rocksdb_options_set_info_log(o_no_prefix, no_prefix_logger);
|
||||
rocksdb_logger_t* no_prefix_info_log =
|
||||
rocksdb_options_get_info_log(o_no_prefix);
|
||||
CheckCondition(no_prefix_info_log != NULL);
|
||||
rocksdb_logger_destroy(no_prefix_logger);
|
||||
rocksdb_logger_destroy(no_prefix_info_log);
|
||||
rocksdb_options_destroy(o_no_prefix);
|
||||
|
||||
rocksdb_options_t* o_prefix = rocksdb_options_create();
|
||||
rocksdb_logger_t* prefix_logger =
|
||||
rocksdb_logger_create_stderr_logger(3, "some prefix");
|
||||
rocksdb_options_set_info_log(o_prefix, prefix_logger);
|
||||
rocksdb_logger_t* prefix_info_log = rocksdb_options_get_info_log(o_prefix);
|
||||
CheckCondition(prefix_info_log != NULL);
|
||||
rocksdb_logger_destroy(prefix_logger);
|
||||
rocksdb_logger_destroy(prefix_info_log);
|
||||
rocksdb_options_destroy(o_prefix);
|
||||
}
|
||||
|
||||
StartPhase("env");
|
||||
{
|
||||
rocksdb_env_t* e;
|
||||
@@ -3687,7 +3714,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
StartPhase("statistics");
|
||||
{
|
||||
const uint32_t BYTES_WRITTEN_TICKER = 40;
|
||||
const uint32_t BYTES_WRITTEN_TICKER = 60;
|
||||
const uint32_t DB_WRITE_HIST = 1;
|
||||
|
||||
rocksdb_statistics_histogram_data_t* hist =
|
||||
|
||||
+35
-17
@@ -96,16 +96,16 @@ const Comparator* ColumnFamilyHandleImpl::GetComparator() const {
|
||||
return cfd()->user_comparator();
|
||||
}
|
||||
|
||||
void GetIntTblPropCollectorFactory(
|
||||
void GetInternalTblPropCollFactory(
|
||||
const ImmutableCFOptions& ioptions,
|
||||
IntTblPropCollectorFactories* int_tbl_prop_collector_factories) {
|
||||
assert(int_tbl_prop_collector_factories);
|
||||
InternalTblPropCollFactories* internal_tbl_prop_coll_factories) {
|
||||
assert(internal_tbl_prop_coll_factories);
|
||||
|
||||
auto& collector_factories = ioptions.table_properties_collector_factories;
|
||||
for (size_t i = 0; i < ioptions.table_properties_collector_factories.size();
|
||||
++i) {
|
||||
assert(collector_factories[i]);
|
||||
int_tbl_prop_collector_factories->emplace_back(
|
||||
internal_tbl_prop_coll_factories->emplace_back(
|
||||
new UserKeyTablePropertiesCollectorFactory(collector_factories[i]));
|
||||
}
|
||||
}
|
||||
@@ -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_WARN(db_options.info_log.get(),
|
||||
"level_compaction_dynamic_level_bytes only makes sense"
|
||||
ROCKS_LOG_INFO(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;
|
||||
}
|
||||
@@ -572,7 +572,7 @@ ColumnFamilyData::ColumnFamilyData(
|
||||
Ref();
|
||||
|
||||
// Convert user defined table properties collector factories to internal ones.
|
||||
GetIntTblPropCollectorFactory(ioptions_, &int_tbl_prop_collector_factories_);
|
||||
GetInternalTblPropCollFactory(ioptions_, &internal_tbl_prop_coll_factories_);
|
||||
|
||||
// if _dummy_versions is nullptr, then this is a dummy column family.
|
||||
if (_dummy_versions != nullptr) {
|
||||
@@ -870,7 +870,7 @@ uint64_t GetPendingCompactionBytesForCompactionSpeedup(
|
||||
const VersionStorageInfo* vstorage) {
|
||||
// Compaction debt relatively large compared to the stable (bottommost) data
|
||||
// size indicates compaction fell behind.
|
||||
const uint64_t kBottommostSizeMultiplier = 8;
|
||||
const uint64_t kBottommostSizeDivisor = 8;
|
||||
// Meaningful progress toward the slowdown trigger is another good indication.
|
||||
const uint64_t kSlowdownTriggerDivisor = 4;
|
||||
|
||||
@@ -890,10 +890,17 @@ uint64_t GetPendingCompactionBytesForCompactionSpeedup(
|
||||
return slowdown_threshold;
|
||||
}
|
||||
|
||||
uint64_t size_threshold =
|
||||
MultiplyCheckOverflow(bottommost_files_size, kBottommostSizeMultiplier);
|
||||
uint64_t size_threshold = bottommost_files_size / kBottommostSizeDivisor;
|
||||
return std::min(size_threshold, slowdown_threshold);
|
||||
}
|
||||
|
||||
uint64_t GetMarkedFileCountForCompactionSpeedup() {
|
||||
// When just one file is marked, it is not clear that parallel compaction will
|
||||
// help the compaction that the user nicely requested to happen sooner. When
|
||||
// multiple files are marked, however, it is pretty clearly helpful, except
|
||||
// for the rare case in which a single compaction grabs all the marked files.
|
||||
return 2;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
std::pair<WriteStallCondition, WriteStallCause>
|
||||
@@ -1075,6 +1082,16 @@ WriteStallCondition ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
"compaction "
|
||||
"bytes %" PRIu64,
|
||||
name_.c_str(), vstorage->estimated_compaction_needed_bytes());
|
||||
} else if (uint64_t(vstorage->FilesMarkedForCompaction().size()) >=
|
||||
GetMarkedFileCountForCompactionSpeedup()) {
|
||||
write_controller_token_ =
|
||||
write_controller->GetCompactionPressureToken();
|
||||
ROCKS_LOG_INFO(
|
||||
ioptions_.logger,
|
||||
"[%s] Increasing compaction threads because we have %" PRIu64
|
||||
" files marked for compaction",
|
||||
name_.c_str(),
|
||||
uint64_t(vstorage->FilesMarkedForCompaction().size()));
|
||||
} else {
|
||||
write_controller_token_.reset();
|
||||
}
|
||||
@@ -1162,13 +1179,13 @@ bool ColumnFamilyData::RangeOverlapWithCompaction(
|
||||
}
|
||||
|
||||
Status ColumnFamilyData::RangesOverlapWithMemtables(
|
||||
const autovector<Range>& ranges, SuperVersion* super_version,
|
||||
const autovector<UserKeyRange>& ranges, SuperVersion* super_version,
|
||||
bool allow_data_in_errors, bool* overlap) {
|
||||
assert(overlap != nullptr);
|
||||
*overlap = false;
|
||||
// Create an InternalIterator over all unflushed memtables
|
||||
Arena arena;
|
||||
// TODO: plumb Env::IOActivity
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
ReadOptions read_opts;
|
||||
read_opts.total_order_seek = true;
|
||||
MergeIteratorBuilder merge_iter_builder(&internal_comparator_, &arena);
|
||||
@@ -1206,7 +1223,8 @@ Status ColumnFamilyData::RangesOverlapWithMemtables(
|
||||
|
||||
if (status.ok()) {
|
||||
if (memtable_iter->Valid() &&
|
||||
ucmp->Compare(seek_result.user_key, ranges[i].limit) <= 0) {
|
||||
ucmp->CompareWithoutTimestamp(seek_result.user_key,
|
||||
ranges[i].limit) <= 0) {
|
||||
*overlap = true;
|
||||
} else if (range_del_agg.IsRangeOverlapped(ranges[i].start,
|
||||
ranges[i].limit)) {
|
||||
|
||||
+24
-26
@@ -169,10 +169,10 @@ class ColumnFamilyHandleImpl : public ColumnFamilyHandle {
|
||||
virtual ~ColumnFamilyHandleImpl();
|
||||
virtual ColumnFamilyData* cfd() const { return cfd_; }
|
||||
|
||||
virtual uint32_t GetID() const override;
|
||||
virtual const std::string& GetName() const override;
|
||||
virtual Status GetDescriptor(ColumnFamilyDescriptor* desc) override;
|
||||
virtual const Comparator* GetComparator() const override;
|
||||
uint32_t GetID() const override;
|
||||
const std::string& GetName() const override;
|
||||
Status GetDescriptor(ColumnFamilyDescriptor* desc) override;
|
||||
const Comparator* GetComparator() const override;
|
||||
|
||||
private:
|
||||
ColumnFamilyData* cfd_;
|
||||
@@ -193,7 +193,7 @@ class ColumnFamilyHandleInternal : public ColumnFamilyHandleImpl {
|
||||
internal_cfd_(nullptr) {}
|
||||
|
||||
void SetCFD(ColumnFamilyData* _cfd) { internal_cfd_ = _cfd; }
|
||||
virtual ColumnFamilyData* cfd() const override { return internal_cfd_; }
|
||||
ColumnFamilyData* cfd() const override { return internal_cfd_; }
|
||||
|
||||
private:
|
||||
ColumnFamilyData* internal_cfd_;
|
||||
@@ -251,22 +251,21 @@ struct SuperVersion {
|
||||
autovector<MemTable*> to_delete;
|
||||
};
|
||||
|
||||
extern Status CheckCompressionSupported(const ColumnFamilyOptions& cf_options);
|
||||
Status CheckCompressionSupported(const ColumnFamilyOptions& cf_options);
|
||||
|
||||
extern Status CheckConcurrentWritesSupported(
|
||||
const ColumnFamilyOptions& cf_options);
|
||||
Status CheckConcurrentWritesSupported(const ColumnFamilyOptions& cf_options);
|
||||
|
||||
extern Status CheckCFPathsSupported(const DBOptions& db_options,
|
||||
const ColumnFamilyOptions& cf_options);
|
||||
Status CheckCFPathsSupported(const DBOptions& db_options,
|
||||
const ColumnFamilyOptions& cf_options);
|
||||
|
||||
extern ColumnFamilyOptions SanitizeOptions(const ImmutableDBOptions& db_options,
|
||||
const ColumnFamilyOptions& src);
|
||||
ColumnFamilyOptions SanitizeOptions(const ImmutableDBOptions& db_options,
|
||||
const ColumnFamilyOptions& src);
|
||||
// Wrap user defined table properties collector factories `from cf_options`
|
||||
// into internal ones in int_tbl_prop_collector_factories. Add a system internal
|
||||
// into internal ones in internal_tbl_prop_coll_factories. Add a system internal
|
||||
// one too.
|
||||
extern void GetIntTblPropCollectorFactory(
|
||||
void GetInternalTblPropCollFactory(
|
||||
const ImmutableCFOptions& ioptions,
|
||||
IntTblPropCollectorFactories* int_tbl_prop_collector_factories);
|
||||
InternalTblPropCollFactories* internal_tbl_prop_coll_factories);
|
||||
|
||||
class ColumnFamilySet;
|
||||
|
||||
@@ -401,7 +400,7 @@ class ColumnFamilyData {
|
||||
// duration of this function.
|
||||
//
|
||||
// Thread-safe
|
||||
Status RangesOverlapWithMemtables(const autovector<Range>& ranges,
|
||||
Status RangesOverlapWithMemtables(const autovector<UserKeyRange>& ranges,
|
||||
SuperVersion* super_version,
|
||||
bool allow_data_in_errors, bool* overlap);
|
||||
|
||||
@@ -430,8 +429,8 @@ class ColumnFamilyData {
|
||||
return internal_comparator_;
|
||||
}
|
||||
|
||||
const IntTblPropCollectorFactories* int_tbl_prop_collector_factories() const {
|
||||
return &int_tbl_prop_collector_factories_;
|
||||
const InternalTblPropCollFactories* internal_tbl_prop_coll_factories() const {
|
||||
return &internal_tbl_prop_coll_factories_;
|
||||
}
|
||||
|
||||
SuperVersion* GetSuperVersion() { return super_version_; }
|
||||
@@ -574,7 +573,7 @@ class ColumnFamilyData {
|
||||
std::atomic<bool> dropped_; // true if client dropped it
|
||||
|
||||
const InternalKeyComparator internal_comparator_;
|
||||
IntTblPropCollectorFactories int_tbl_prop_collector_factories_;
|
||||
InternalTblPropCollFactories internal_tbl_prop_coll_factories_;
|
||||
|
||||
const ColumnFamilyOptions initial_cf_options_;
|
||||
const ImmutableOptions ioptions_;
|
||||
@@ -854,17 +853,17 @@ class ColumnFamilyMemTablesImpl : public ColumnFamilyMemTables {
|
||||
// REQUIRES: Seek() called first
|
||||
// REQUIRES: use this function of DBImpl::column_family_memtables_ should be
|
||||
// under a DB mutex OR from a write thread
|
||||
virtual MemTable* GetMemTable() const override;
|
||||
MemTable* GetMemTable() const override;
|
||||
|
||||
// Returns column family handle for the selected column family
|
||||
// REQUIRES: use this function of DBImpl::column_family_memtables_ should be
|
||||
// under a DB mutex OR from a write thread
|
||||
virtual ColumnFamilyHandle* GetColumnFamilyHandle() override;
|
||||
ColumnFamilyHandle* GetColumnFamilyHandle() override;
|
||||
|
||||
// Cannot be called while another thread is calling Seek().
|
||||
// REQUIRES: use this function of DBImpl::column_family_memtables_ should be
|
||||
// under a DB mutex OR from a write thread
|
||||
virtual ColumnFamilyData* current() override { return current_; }
|
||||
ColumnFamilyData* current() override { return current_; }
|
||||
|
||||
private:
|
||||
ColumnFamilySet* column_family_set_;
|
||||
@@ -872,12 +871,11 @@ class ColumnFamilyMemTablesImpl : public ColumnFamilyMemTables {
|
||||
ColumnFamilyHandleInternal handle_;
|
||||
};
|
||||
|
||||
extern uint32_t GetColumnFamilyID(ColumnFamilyHandle* column_family);
|
||||
uint32_t GetColumnFamilyID(ColumnFamilyHandle* column_family);
|
||||
|
||||
extern const Comparator* GetColumnFamilyUserComparator(
|
||||
const Comparator* GetColumnFamilyUserComparator(
|
||||
ColumnFamilyHandle* column_family);
|
||||
|
||||
extern const ImmutableOptions& GetImmutableOptions(
|
||||
ColumnFamilyHandle* column_family);
|
||||
const ImmutableOptions& GetImmutableOptions(ColumnFamilyHandle* column_family);
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
+124
-43
@@ -2604,90 +2604,92 @@ TEST_P(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
mutable_cf_options.hard_pending_compaction_bytes_limit = 2000;
|
||||
mutable_cf_options.disable_auto_compactions = false;
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(50);
|
||||
auto dbmu = dbfull()->TEST_Mutex();
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(50, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(201);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(201, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate, GetDbDelayedWriteRate());
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(400);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(400, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25, GetDbDelayedWriteRate());
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(500);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(500, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25 / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(450);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(450, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(205);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(205, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(202);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(202, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(201);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(201, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(198);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(198, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(399);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(399, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(599);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(599, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(2001);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(2001, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(IsDbWriteStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(3001);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(3001, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(IsDbWriteStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(390);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(390, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(100);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(100, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
@@ -2706,7 +2708,7 @@ TEST_P(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
ASSERT_EQ(kBaseRate / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(0);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(300);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(300, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
@@ -2718,14 +2720,14 @@ TEST_P(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25 / 1.25 / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(200);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(200, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25 / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(0);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(0);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(0, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
@@ -2744,7 +2746,7 @@ TEST_P(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
ASSERT_EQ(kBaseRate, dbfull()->TEST_write_controler().delayed_write_rate());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(60);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(300);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(300, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
@@ -2753,14 +2755,14 @@ TEST_P(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
|
||||
mutable_cf_options.disable_auto_compactions = false;
|
||||
vstorage->set_l0_delay_trigger_count(70);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(500);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(500, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(71);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(501);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(501, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
@@ -2785,19 +2787,21 @@ TEST_P(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
|
||||
mutable_cf_options.soft_pending_compaction_bytes_limit = 200;
|
||||
mutable_cf_options.hard_pending_compaction_bytes_limit = 2000;
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(40);
|
||||
auto dbmu = dbfull()->TEST_Mutex();
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(40, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(50);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(50, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(300);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(300, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(45);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(45, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
@@ -2853,53 +2857,55 @@ TEST_P(ColumnFamilyTest, WriteStallTwoColumnFamilies) {
|
||||
MutableCFOptions mutable_cf_options1 = mutable_cf_options;
|
||||
mutable_cf_options1.soft_pending_compaction_bytes_limit = 500;
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(50);
|
||||
auto dbmu = dbfull()->TEST_Mutex();
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(50, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(201);
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(201, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(600);
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(600, dbmu);
|
||||
RecalculateWriteStallConditions(cfd1, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(70);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(70, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(800);
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(800, dbmu);
|
||||
RecalculateWriteStallConditions(cfd1, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(300);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(300, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25 / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(700);
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(700, dbmu);
|
||||
RecalculateWriteStallConditions(cfd1, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(500);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(500, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.25 / 1.25, GetDbDelayedWriteRate());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(600);
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(600, dbmu);
|
||||
RecalculateWriteStallConditions(cfd1, mutable_cf_options);
|
||||
ASSERT_TRUE(!IsDbWriteStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
@@ -2932,29 +2938,31 @@ TEST_P(ColumnFamilyTest, CompactionSpeedupTwoColumnFamilies) {
|
||||
MutableCFOptions mutable_cf_options1 = mutable_cf_options;
|
||||
mutable_cf_options1.level0_slowdown_writes_trigger = 16;
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(40);
|
||||
auto dbmu = dbfull()->TEST_Mutex();
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(40, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(60);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(60, dbmu);
|
||||
RecalculateWriteStallConditions(cfd1, mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(30);
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(30, dbmu);
|
||||
RecalculateWriteStallConditions(cfd1, mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(70);
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(70, dbmu);
|
||||
RecalculateWriteStallConditions(cfd1, mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(20);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(20, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(3);
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(3, dbmu);
|
||||
RecalculateWriteStallConditions(cfd1, mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
@@ -2980,10 +2988,13 @@ TEST_P(ColumnFamilyTest, CompactionSpeedupForCompactionDebt) {
|
||||
mutable_cf_options.soft_pending_compaction_bytes_limit =
|
||||
std::numeric_limits<uint64_t>::max();
|
||||
|
||||
auto dbmu = dbfull()->TEST_Mutex();
|
||||
|
||||
{
|
||||
// No bottommost data, so debt ratio cannot trigger speedup.
|
||||
VersionStorageInfo* vstorage = cfd->current()->storage_info();
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(1048576 /* 1MB */);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(1048576 /* 1MB */,
|
||||
dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
@@ -2996,18 +3007,88 @@ TEST_P(ColumnFamilyTest, CompactionSpeedupForCompactionDebt) {
|
||||
// 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 */);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(1048576 /* 1MB */,
|
||||
dbmu);
|
||||
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);
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(8, dbmu);
|
||||
RecalculateWriteStallConditions(cfd, mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(ColumnFamilyTest, CompactionSpeedupForMarkedFiles) {
|
||||
const int kParallelismLimit = 3;
|
||||
class AlwaysCompactTpc : public TablePropertiesCollector {
|
||||
public:
|
||||
Status Finish(UserCollectedProperties* /* properties */) override {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
UserCollectedProperties GetReadableProperties() const override {
|
||||
return UserCollectedProperties{};
|
||||
}
|
||||
|
||||
const char* Name() const override { return "AlwaysCompactTpc"; }
|
||||
|
||||
bool NeedCompact() const override { return true; }
|
||||
};
|
||||
|
||||
class AlwaysCompactTpcf : public TablePropertiesCollectorFactory {
|
||||
public:
|
||||
TablePropertiesCollector* CreateTablePropertiesCollector(
|
||||
TablePropertiesCollectorFactory::Context /* context */) override {
|
||||
return new AlwaysCompactTpc();
|
||||
}
|
||||
|
||||
const char* Name() const override { return "AlwaysCompactTpcf"; }
|
||||
};
|
||||
|
||||
column_family_options_.num_levels = 2;
|
||||
column_family_options_.table_properties_collector_factories.emplace_back(
|
||||
std::make_shared<AlwaysCompactTpcf>());
|
||||
db_options_.max_background_compactions = kParallelismLimit;
|
||||
Open();
|
||||
|
||||
// Make a nonempty last level. Only marked files in upper levels count.
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo", "bar"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
WaitForCompaction();
|
||||
AssertFilesPerLevel("0,1", 0 /* cf */);
|
||||
|
||||
// Block the compaction thread pool so marked files accumulate in L0.
|
||||
test::SleepingBackgroundTask sleeping_tasks[kParallelismLimit];
|
||||
for (int i = 0; i < kParallelismLimit; i++) {
|
||||
env_->Schedule(&test::SleepingBackgroundTask::DoSleepTask,
|
||||
&sleeping_tasks[i], Env::Priority::LOW);
|
||||
sleeping_tasks[i].WaitUntilSleeping();
|
||||
}
|
||||
|
||||
// Zero marked upper-level files. No speedup.
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
AssertFilesPerLevel("0,1", 0 /* cf */);
|
||||
|
||||
// One marked upper-level file. No speedup.
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo", "bar"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
AssertFilesPerLevel("1,1", 0 /* cf */);
|
||||
|
||||
// Two marked upper-level files. Speedup.
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo", "bar"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
ASSERT_EQ(kParallelismLimit, dbfull()->TEST_BGCompactionsAllowed());
|
||||
AssertFilesPerLevel("2,1", 0 /* cf */);
|
||||
|
||||
for (int i = 0; i < kParallelismLimit; i++) {
|
||||
sleeping_tasks[i].WakeUp();
|
||||
sleeping_tasks[i].WaitUntilDone();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(ColumnFamilyTest, CreateAndDestroyOptions) {
|
||||
std::unique_ptr<ColumnFamilyOptions> cfo(new ColumnFamilyOptions());
|
||||
ColumnFamilyHandle* cfh;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "db/column_family.h"
|
||||
#include "db/dbformat.h"
|
||||
#include "logging/logging.h"
|
||||
#include "rocksdb/compaction_filter.h"
|
||||
#include "rocksdb/sst_partitioner.h"
|
||||
@@ -21,9 +22,6 @@
|
||||
|
||||
namespace ROCKSDB_NAMESPACE {
|
||||
|
||||
const uint64_t kRangeTombstoneSentinel =
|
||||
PackSequenceAndType(kMaxSequenceNumber, kTypeRangeDeletion);
|
||||
|
||||
int sstableKeyCompare(const Comparator* uc, const Slice& a, const Slice& b) {
|
||||
auto c = uc->CompareWithoutTimestamp(ExtractUserKey(a), ExtractUserKey(b));
|
||||
if (c != 0) {
|
||||
@@ -352,11 +350,9 @@ Compaction::Compaction(
|
||||
|
||||
// for the non-bottommost levels, it tries to build files match the target
|
||||
// file size, but not guaranteed. It could be 2x the size of the target size.
|
||||
max_output_file_size_ =
|
||||
bottommost_level_ || grandparents_.empty() ||
|
||||
!_immutable_options.level_compaction_dynamic_file_size
|
||||
? target_output_file_size_
|
||||
: 2 * target_output_file_size_;
|
||||
max_output_file_size_ = bottommost_level_ || grandparents_.empty()
|
||||
? target_output_file_size_
|
||||
: 2 * target_output_file_size_;
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (size_t i = 1; i < inputs_.size(); ++i) {
|
||||
|
||||
@@ -595,6 +595,6 @@ struct PerKeyPlacementContext {
|
||||
#endif /* !NDEBUG */
|
||||
|
||||
// Return sum of sizes of all files in `files`.
|
||||
extern uint64_t TotalFileSize(const std::vector<FileMetaData*>& files);
|
||||
uint64_t TotalFileSize(const std::vector<FileMetaData*>& files);
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
@@ -288,39 +288,37 @@ void CompactionJob::Prepare() {
|
||||
|
||||
if (preserve_time_duration > 0) {
|
||||
const ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
// setup seqno_to_time_mapping_
|
||||
seqno_to_time_mapping_.SetMaxTimeDuration(preserve_time_duration);
|
||||
// Setup seqno_to_time_mapping_ with relevant time range.
|
||||
seqno_to_time_mapping_.SetMaxTimeSpan(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()) {
|
||||
seqno_to_time_mapping_.Add(tp->seqno_to_time_mapping)
|
||||
.PermitUncheckedError();
|
||||
seqno_to_time_mapping_.Add(fmd->fd.smallest_seqno,
|
||||
fmd->oldest_ancester_time);
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = db_options_.clock->GetCurrentTime(&_current_time);
|
||||
if (!status.ok()) {
|
||||
Status s = db_options_.clock->GetCurrentTime(&_current_time);
|
||||
if (!s.ok()) {
|
||||
ROCKS_LOG_WARN(db_options_.info_log,
|
||||
"Failed to get current time in compaction: Status: %s",
|
||||
status.ToString().c_str());
|
||||
s.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_.TruncateOldEntries(_current_time);
|
||||
seqno_to_time_mapping_.Enforce(_current_time);
|
||||
uint64_t preserve_time =
|
||||
static_cast<uint64_t>(_current_time) > preserve_time_duration
|
||||
? _current_time - preserve_time_duration
|
||||
@@ -344,6 +342,16 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,14 +450,6 @@ void CompactionJob::ReleaseSubcompactionResources() {
|
||||
ShrinkSubcompactionResources(extra_num_subcompaction_threads_reserved_);
|
||||
}
|
||||
|
||||
struct RangeWithSize {
|
||||
Range range;
|
||||
uint64_t size;
|
||||
|
||||
RangeWithSize(const Slice& a, const Slice& b, uint64_t s = 0)
|
||||
: range(a, b), size(s) {}
|
||||
};
|
||||
|
||||
void CompactionJob::GenSubcompactionBoundaries() {
|
||||
// The goal is to find some boundary keys so that we can evenly partition
|
||||
// the compaction input data into max_subcompactions ranges.
|
||||
@@ -476,7 +476,8 @@ 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.
|
||||
const ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
ReadOptions read_options(Env::IOActivity::kCompaction);
|
||||
read_options.rate_limiter_priority = GetRateLimiterPriority();
|
||||
auto* c = compact_->compaction;
|
||||
if (c->max_subcompactions() <= 1 &&
|
||||
!(c->immutable_options()->compaction_pri == kRoundRobin &&
|
||||
@@ -728,8 +729,9 @@ 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
|
||||
const ReadOptions verify_table_read_options(
|
||||
Env::IOActivity::kCompaction);
|
||||
ReadOptions verify_table_read_options(Env::IOActivity::kCompaction);
|
||||
verify_table_read_options.rate_limiter_priority =
|
||||
GetRateLimiterPriority();
|
||||
InternalIterator* iter = cfd->table_cache()->NewIterator(
|
||||
verify_table_read_options, file_options_,
|
||||
cfd->internal_comparator(), files_output[file_idx]->meta,
|
||||
@@ -750,7 +752,6 @@ Status CompactionJob::Run() {
|
||||
|
||||
if (s.ok() && paranoid_file_checks_) {
|
||||
OutputValidator validator(cfd->internal_comparator(),
|
||||
/*_enable_order_check=*/true,
|
||||
/*_enable_hash=*/true);
|
||||
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||
s = validator.Add(iter->key(), iter->value());
|
||||
@@ -821,24 +822,27 @@ Status CompactionJob::Run() {
|
||||
// input keys. So the number of keys it processed is not suitable for
|
||||
// verification here.
|
||||
// TODO: support verification when trim_ts_ is non-empty.
|
||||
if (!(ts_sz > 0 && !trim_ts_.empty()) &&
|
||||
db_options_.compaction_verify_record_count) {
|
||||
if (!(ts_sz > 0 && !trim_ts_.empty())) {
|
||||
assert(compaction_stats_.stats.num_input_records > 0);
|
||||
// TODO: verify the number of range deletion entries.
|
||||
uint64_t expected =
|
||||
compaction_stats_.stats.num_input_records - num_input_range_del;
|
||||
uint64_t actual = compaction_job_stats_->num_input_records;
|
||||
if (expected != actual) {
|
||||
char scratch[2345];
|
||||
compact_->compaction->Summary(scratch, sizeof(scratch));
|
||||
std::string msg =
|
||||
"Total number of input records: " + std::to_string(expected) +
|
||||
", but processed " + std::to_string(actual) + " records.";
|
||||
"Compaction number of input keys does not match "
|
||||
"number of keys processed. Expected " +
|
||||
std::to_string(expected) + " but processed " +
|
||||
std::to_string(actual) + ". Compaction summary: " + scratch;
|
||||
ROCKS_LOG_WARN(
|
||||
db_options_.info_log, "[%s] [JOB %d] Compaction %s",
|
||||
db_options_.info_log, "[%s] [JOB %d] Compaction with status: %s",
|
||||
compact_->compaction->column_family_data()->GetName().c_str(),
|
||||
job_context_->job_id, msg.c_str());
|
||||
status = Status::Corruption(
|
||||
"Compaction number of input keys does not match number of keys "
|
||||
"processed.");
|
||||
if (db_options_.compaction_verify_record_count) {
|
||||
status = Status::Corruption(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1130,6 +1134,9 @@ 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();
|
||||
@@ -1264,18 +1271,17 @@ void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
|
||||
? new BlobFileBuilder(
|
||||
versions_, fs_.get(),
|
||||
sub_compact->compaction->immutable_options(),
|
||||
mutable_cf_options, &file_options_, db_id_, db_session_id_,
|
||||
job_id_, cfd->GetID(), cfd->GetName(), Env::IOPriority::IO_LOW,
|
||||
mutable_cf_options, &file_options_, &write_options, db_id_,
|
||||
db_session_id_, job_id_, cfd->GetID(), cfd->GetName(),
|
||||
write_hint_, io_tracer_, blob_callback_,
|
||||
BlobFileCreationReason::kCompaction, &blob_file_paths,
|
||||
sub_compact->Current().GetBlobFileAdditionsPtr())
|
||||
: nullptr);
|
||||
|
||||
TEST_SYNC_POINT("CompactionJob::Run():Inprogress");
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"CompactionJob::Run():PausingManualCompaction:1",
|
||||
reinterpret_cast<void*>(
|
||||
const_cast<std::atomic<bool>*>(&manual_compaction_canceled_)));
|
||||
TEST_SYNC_POINT_CALLBACK("CompactionJob::Run():PausingManualCompaction:1",
|
||||
static_cast<void*>(const_cast<std::atomic<bool>*>(
|
||||
&manual_compaction_canceled_)));
|
||||
|
||||
const std::string* const full_history_ts_low =
|
||||
full_history_ts_low_.empty() ? nullptr : &full_history_ts_low_;
|
||||
@@ -1323,8 +1329,7 @@ void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
|
||||
Status status;
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"CompactionJob::ProcessKeyValueCompaction()::Processing",
|
||||
reinterpret_cast<void*>(
|
||||
const_cast<Compaction*>(sub_compact->compaction)));
|
||||
static_cast<void*>(const_cast<Compaction*>(sub_compact->compaction)));
|
||||
uint64_t last_cpu_micros = prev_cpu_micros;
|
||||
while (status.ok() && !cfd->IsDropped() && c_iter->Valid()) {
|
||||
// Invariant: c_iter.status() is guaranteed to be OK if c_iter->Valid()
|
||||
@@ -1355,10 +1360,9 @@ void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
|
||||
break;
|
||||
}
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"CompactionJob::Run():PausingManualCompaction:2",
|
||||
reinterpret_cast<void*>(
|
||||
const_cast<std::atomic<bool>*>(&manual_compaction_canceled_)));
|
||||
TEST_SYNC_POINT_CALLBACK("CompactionJob::Run():PausingManualCompaction:2",
|
||||
static_cast<void*>(const_cast<std::atomic<bool>*>(
|
||||
&manual_compaction_canceled_)));
|
||||
c_iter->Next();
|
||||
if (c_iter->status().IsManualCompactionPaused()) {
|
||||
break;
|
||||
@@ -1710,6 +1714,8 @@ 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);
|
||||
|
||||
@@ -1792,8 +1798,9 @@ Status CompactionJob::InstallCompactionResults(
|
||||
};
|
||||
|
||||
return versions_->LogAndApply(
|
||||
compaction->column_family_data(), mutable_cf_options, read_options, edit,
|
||||
db_mutex_, db_directory_, /*new_descriptor_log=*/false,
|
||||
compaction->column_family_data(), mutable_cf_options, read_options,
|
||||
write_options, edit, db_mutex_, db_directory_,
|
||||
/*new_descriptor_log=*/false,
|
||||
/*column_family_options=*/nullptr, manifest_wcb);
|
||||
}
|
||||
|
||||
@@ -1929,8 +1936,6 @@ Status CompactionJob::OpenCompactionOutputFile(SubcompactionState* sub_compact,
|
||||
}
|
||||
|
||||
outputs.AddOutput(std::move(meta), cfd->internal_comparator(),
|
||||
sub_compact->compaction->mutable_cf_options()
|
||||
->check_flush_compaction_key_order,
|
||||
paranoid_file_checks_);
|
||||
}
|
||||
|
||||
@@ -1943,13 +1948,17 @@ 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, listeners, db_options_.file_checksum_gen_factory.get(),
|
||||
db_options_.stats, Histograms::SST_WRITE_MICROS, 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()),
|
||||
cfd->internal_comparator(), cfd->int_tbl_prop_collector_factories(),
|
||||
read_options, write_options, cfd->internal_comparator(),
|
||||
cfd->internal_tbl_prop_coll_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)),
|
||||
/*error_handler=*/nullptr, /*read_only=*/false)),
|
||||
shutting_down_(false),
|
||||
mock_table_factory_(new mock::MockTableFactory()),
|
||||
error_handler_(nullptr, db_options_, &mutex_),
|
||||
@@ -295,11 +295,14 @@ 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(),
|
||||
cfd_->internal_tbl_prop_coll_factories(),
|
||||
CompressionType::kNoCompression,
|
||||
CompressionOptions(), 0 /* column_family_id */,
|
||||
kDefaultColumnFamilyName, -1 /* level */),
|
||||
@@ -394,7 +397,7 @@ class CompactionJobTestBase : public testing::Test {
|
||||
mutex_.Lock();
|
||||
EXPECT_OK(versions_->LogAndApply(
|
||||
versions_->GetColumnFamilySet()->GetDefault(), mutable_cf_options_,
|
||||
read_options_, &edit, &mutex_, nullptr));
|
||||
read_options_, write_options_, &edit, &mutex_, nullptr));
|
||||
mutex_.Unlock();
|
||||
}
|
||||
|
||||
@@ -547,9 +550,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));
|
||||
/*error_handler=*/nullptr, /*read_only=*/false));
|
||||
compaction_job_stats_.Reset();
|
||||
ASSERT_OK(SetIdentityFile(env_, dbname_));
|
||||
ASSERT_OK(SetIdentityFile(WriteOptions(), env_, dbname_));
|
||||
|
||||
VersionEdit new_db;
|
||||
new_db.SetLogNumber(0);
|
||||
@@ -568,11 +571,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(record);
|
||||
s = log.AddRecord(WriteOptions(), record);
|
||||
}
|
||||
ASSERT_OK(s);
|
||||
// Make "CURRENT" file that points to the new manifest file.
|
||||
s = SetCurrentFile(fs_.get(), dbname_, 1, nullptr);
|
||||
s = SetCurrentFile(WriteOptions(), fs_.get(), dbname_, 1, nullptr);
|
||||
|
||||
ASSERT_OK(s);
|
||||
|
||||
@@ -736,6 +739,7 @@ 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_;
|
||||
@@ -1748,23 +1752,9 @@ TEST_F(CompactionJobTest, ResultSerialization) {
|
||||
}
|
||||
}
|
||||
|
||||
class CompactionJobDynamicFileSizeTest
|
||||
: public CompactionJobTestBase,
|
||||
public ::testing::WithParamInterface<bool> {
|
||||
public:
|
||||
CompactionJobDynamicFileSizeTest()
|
||||
: CompactionJobTestBase(
|
||||
test::PerThreadDBPath("compaction_job_dynamic_file_size_test"),
|
||||
BytewiseComparator(), [](uint64_t /*ts*/) { return ""; },
|
||||
/*test_io_priority=*/false, TableTypeForTest::kMockTable) {}
|
||||
};
|
||||
|
||||
TEST_P(CompactionJobDynamicFileSizeTest, CutForMaxCompactionBytes) {
|
||||
TEST_F(CompactionJobTest, CutForMaxCompactionBytes) {
|
||||
// dynamic_file_size option should have no impact on cutting for max
|
||||
// compaction bytes.
|
||||
bool enable_dyanmic_file_size = GetParam();
|
||||
cf_options_.level_compaction_dynamic_file_size = enable_dyanmic_file_size;
|
||||
|
||||
NewDB();
|
||||
mutable_cf_options_.target_file_size_base = 80;
|
||||
mutable_cf_options_.max_compaction_bytes = 21;
|
||||
@@ -1838,10 +1828,7 @@ TEST_P(CompactionJobDynamicFileSizeTest, CutForMaxCompactionBytes) {
|
||||
{expected_file1, expected_file2});
|
||||
}
|
||||
|
||||
TEST_P(CompactionJobDynamicFileSizeTest, CutToSkipGrandparentFile) {
|
||||
bool enable_dyanmic_file_size = GetParam();
|
||||
cf_options_.level_compaction_dynamic_file_size = enable_dyanmic_file_size;
|
||||
|
||||
TEST_F(CompactionJobTest, CutToSkipGrandparentFile) {
|
||||
NewDB();
|
||||
// Make sure the grandparent level file size (10) qualifies skipping.
|
||||
// Currently, it has to be > 1/8 of target file size.
|
||||
@@ -1876,28 +1863,15 @@ TEST_P(CompactionJobDynamicFileSizeTest, CutToSkipGrandparentFile) {
|
||||
mock::MakeMockFile({{KeyStr("x", 4U, kTypeValue), "val"},
|
||||
{KeyStr("z", 6U, kTypeValue), "val3"}});
|
||||
|
||||
auto expected_file_disable_dynamic_file_size =
|
||||
mock::MakeMockFile({{KeyStr("a", 5U, kTypeValue), "val2"},
|
||||
{KeyStr("c", 3U, kTypeValue), "val"},
|
||||
{KeyStr("x", 4U, kTypeValue), "val"},
|
||||
{KeyStr("z", 6U, kTypeValue), "val3"}});
|
||||
|
||||
SetLastSequence(6U);
|
||||
const std::vector<int> input_levels = {0, 1};
|
||||
auto lvl0_files = cfd_->current()->storage_info()->LevelFiles(0);
|
||||
auto lvl1_files = cfd_->current()->storage_info()->LevelFiles(1);
|
||||
if (enable_dyanmic_file_size) {
|
||||
RunCompaction({lvl0_files, lvl1_files}, input_levels,
|
||||
{expected_file1, expected_file2});
|
||||
} else {
|
||||
RunCompaction({lvl0_files, lvl1_files}, input_levels,
|
||||
{expected_file_disable_dynamic_file_size});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(CompactionJobDynamicFileSizeTest, CutToAlignGrandparentBoundary) {
|
||||
bool enable_dyanmic_file_size = GetParam();
|
||||
cf_options_.level_compaction_dynamic_file_size = enable_dyanmic_file_size;
|
||||
TEST_F(CompactionJobTest, CutToAlignGrandparentBoundary) {
|
||||
NewDB();
|
||||
|
||||
// MockTable has 1 byte per entry by default and each file is 10 bytes.
|
||||
@@ -1964,40 +1938,15 @@ TEST_P(CompactionJobDynamicFileSizeTest, CutToAlignGrandparentBoundary) {
|
||||
}
|
||||
expected_file2.emplace_back(KeyStr("s", 4U, kTypeValue), "val");
|
||||
|
||||
mock::KVVector expected_file_disable_dynamic_file_size1;
|
||||
for (char i = 0; i < 10; i++) {
|
||||
expected_file_disable_dynamic_file_size1.emplace_back(
|
||||
KeyStr(std::string(1, ch + i), i + 10, kTypeValue),
|
||||
"val" + std::to_string(i));
|
||||
}
|
||||
|
||||
mock::KVVector expected_file_disable_dynamic_file_size2;
|
||||
for (char i = 10; i < 12; i++) {
|
||||
expected_file_disable_dynamic_file_size2.emplace_back(
|
||||
KeyStr(std::string(1, ch + i), i + 10, kTypeValue),
|
||||
"val" + std::to_string(i));
|
||||
}
|
||||
|
||||
expected_file_disable_dynamic_file_size2.emplace_back(
|
||||
KeyStr("s", 4U, kTypeValue), "val");
|
||||
|
||||
SetLastSequence(22U);
|
||||
const std::vector<int> input_levels = {0, 1};
|
||||
auto lvl0_files = cfd_->current()->storage_info()->LevelFiles(0);
|
||||
auto lvl1_files = cfd_->current()->storage_info()->LevelFiles(1);
|
||||
if (enable_dyanmic_file_size) {
|
||||
RunCompaction({lvl0_files, lvl1_files}, input_levels,
|
||||
{expected_file1, expected_file2});
|
||||
} else {
|
||||
RunCompaction({lvl0_files, lvl1_files}, input_levels,
|
||||
{expected_file_disable_dynamic_file_size1,
|
||||
expected_file_disable_dynamic_file_size2});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(CompactionJobDynamicFileSizeTest, CutToAlignGrandparentBoundarySameKey) {
|
||||
bool enable_dyanmic_file_size = GetParam();
|
||||
cf_options_.level_compaction_dynamic_file_size = enable_dyanmic_file_size;
|
||||
TEST_F(CompactionJobTest, CutToAlignGrandparentBoundarySameKey) {
|
||||
NewDB();
|
||||
|
||||
// MockTable has 1 byte per entry by default and each file is 10 bytes.
|
||||
@@ -2034,13 +1983,9 @@ TEST_P(CompactionJobDynamicFileSizeTest, CutToAlignGrandparentBoundarySameKey) {
|
||||
AddMockFile(file5, 2);
|
||||
|
||||
mock::KVVector expected_file1;
|
||||
mock::KVVector expected_file_disable_dynamic_file_size;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
expected_file1.emplace_back(KeyStr("a", 100 - i, kTypeValue),
|
||||
"val" + std::to_string(100 - i));
|
||||
expected_file_disable_dynamic_file_size.emplace_back(
|
||||
KeyStr("a", 100 - i, kTypeValue), "val" + std::to_string(100 - i));
|
||||
}
|
||||
|
||||
// make sure `b` is cut in a separated file (so internally it's not using
|
||||
@@ -2049,9 +1994,6 @@ TEST_P(CompactionJobDynamicFileSizeTest, CutToAlignGrandparentBoundarySameKey) {
|
||||
auto expected_file2 =
|
||||
mock::MakeMockFile({{KeyStr("b", 90U, kTypeValue), "valb"}});
|
||||
|
||||
expected_file_disable_dynamic_file_size.emplace_back(
|
||||
KeyStr("b", 90U, kTypeValue), "valb");
|
||||
|
||||
SetLastSequence(122U);
|
||||
const std::vector<int> input_levels = {0, 1};
|
||||
auto lvl0_files = cfd_->current()->storage_info()->LevelFiles(0);
|
||||
@@ -2062,20 +2004,13 @@ TEST_P(CompactionJobDynamicFileSizeTest, CutToAlignGrandparentBoundarySameKey) {
|
||||
for (int i = 80; i <= 100; i++) {
|
||||
snapshots.emplace_back(i);
|
||||
}
|
||||
if (enable_dyanmic_file_size) {
|
||||
RunCompaction({lvl0_files, lvl1_files}, input_levels,
|
||||
{expected_file1, expected_file2}, snapshots);
|
||||
} else {
|
||||
RunCompaction({lvl0_files, lvl1_files}, input_levels,
|
||||
{expected_file_disable_dynamic_file_size}, snapshots);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(CompactionJobDynamicFileSizeTest, CutForMaxCompactionBytesSameKey) {
|
||||
TEST_F(CompactionJobTest, CutForMaxCompactionBytesSameKey) {
|
||||
// dynamic_file_size option should have no impact on cutting for max
|
||||
// compaction bytes.
|
||||
bool enable_dyanmic_file_size = GetParam();
|
||||
cf_options_.level_compaction_dynamic_file_size = enable_dyanmic_file_size;
|
||||
|
||||
NewDB();
|
||||
mutable_cf_options_.target_file_size_base = 80;
|
||||
@@ -2132,9 +2067,6 @@ TEST_P(CompactionJobDynamicFileSizeTest, CutForMaxCompactionBytesSameKey) {
|
||||
{expected_file1, expected_file2, expected_file3}, snapshots);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CompactionJobDynamicFileSizeTest,
|
||||
CompactionJobDynamicFileSizeTest, testing::Bool());
|
||||
|
||||
class CompactionJobTimestampTest : public CompactionJobTestBase {
|
||||
public:
|
||||
CompactionJobTimestampTest()
|
||||
|
||||
@@ -25,11 +25,11 @@ Status CompactionOutputs::Finish(
|
||||
assert(meta != nullptr);
|
||||
Status s = intput_status;
|
||||
if (s.ok()) {
|
||||
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,
|
||||
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,
|
||||
meta->oldest_ancester_time);
|
||||
s = builder_->Finish();
|
||||
|
||||
@@ -62,12 +62,15 @@ IOStatus CompactionOutputs::WriterSyncClose(const Status& input_status,
|
||||
Statistics* statistics,
|
||||
bool use_fsync) {
|
||||
IOStatus io_s;
|
||||
if (input_status.ok()) {
|
||||
IOOptions opts;
|
||||
io_s = WritableFileWriter::PrepareIOOptions(
|
||||
WriteOptions(Env::IOActivity::kCompaction), opts);
|
||||
if (input_status.ok() && io_s.ok()) {
|
||||
StopWatch sw(clock, statistics, COMPACTION_OUTFILE_SYNC_MICROS);
|
||||
io_s = file_writer_->Sync(use_fsync);
|
||||
io_s = file_writer_->Sync(opts, use_fsync);
|
||||
}
|
||||
if (input_status.ok() && io_s.ok()) {
|
||||
io_s = file_writer_->Close();
|
||||
io_s = file_writer_->Close(opts);
|
||||
}
|
||||
|
||||
if (input_status.ok() && io_s.ok()) {
|
||||
@@ -317,7 +320,6 @@ bool CompactionOutputs::ShouldStopBefore(const CompactionIterator& c_iter) {
|
||||
being_grandparent_gap_ ? 2 : 3;
|
||||
if (compaction_->immutable_options()->compaction_style ==
|
||||
kCompactionStyleLevel &&
|
||||
compaction_->immutable_options()->level_compaction_dynamic_file_size &&
|
||||
num_grandparent_boundaries_crossed >=
|
||||
num_skippable_boundaries_crossed &&
|
||||
grandparent_overlapped_bytes_ - previous_overlapped_bytes >
|
||||
@@ -339,7 +341,6 @@ bool CompactionOutputs::ShouldStopBefore(const CompactionIterator& c_iter) {
|
||||
// improvement.
|
||||
if (compaction_->immutable_options()->compaction_style ==
|
||||
kCompactionStyleLevel &&
|
||||
compaction_->immutable_options()->level_compaction_dynamic_file_size &&
|
||||
current_output_file_size_ >=
|
||||
((compaction_->target_output_file_size() + 99) / 100) *
|
||||
(50 + std::min(grandparent_boundary_switched_num_ * 5,
|
||||
|
||||
@@ -30,11 +30,9 @@ class CompactionOutputs {
|
||||
// compaction output file
|
||||
struct Output {
|
||||
Output(FileMetaData&& _meta, const InternalKeyComparator& _icmp,
|
||||
bool _enable_order_check, bool _enable_hash, bool _finished,
|
||||
uint64_t precalculated_hash)
|
||||
bool _enable_hash, bool _finished, uint64_t precalculated_hash)
|
||||
: meta(std::move(_meta)),
|
||||
validator(_icmp, _enable_order_check, _enable_hash,
|
||||
precalculated_hash),
|
||||
validator(_icmp, _enable_hash, precalculated_hash),
|
||||
finished(_finished) {}
|
||||
FileMetaData meta;
|
||||
OutputValidator validator;
|
||||
@@ -49,10 +47,10 @@ class CompactionOutputs {
|
||||
|
||||
// Add generated output to the list
|
||||
void AddOutput(FileMetaData&& meta, const InternalKeyComparator& icmp,
|
||||
bool enable_order_check, bool enable_hash,
|
||||
bool finished = false, uint64_t precalculated_hash = 0) {
|
||||
outputs_.emplace_back(std::move(meta), icmp, enable_order_check,
|
||||
enable_hash, finished, precalculated_hash);
|
||||
bool enable_hash, bool finished = false,
|
||||
uint64_t precalculated_hash = 0) {
|
||||
outputs_.emplace_back(std::move(meta), icmp, enable_hash, finished,
|
||||
precalculated_hash);
|
||||
}
|
||||
|
||||
// Set new table builder for the current output
|
||||
|
||||
@@ -456,10 +456,9 @@ bool CompactionPicker::IsRangeInCompaction(VersionStorageInfo* vstorage,
|
||||
// Returns false if files on parent level are currently in compaction, which
|
||||
// means that we can't compact them
|
||||
bool CompactionPicker::SetupOtherInputs(
|
||||
const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
|
||||
VersionStorageInfo* vstorage, CompactionInputFiles* inputs,
|
||||
CompactionInputFiles* output_level_inputs, int* parent_index,
|
||||
int base_index, bool only_expand_towards_right) {
|
||||
const std::string& cf_name, VersionStorageInfo* vstorage,
|
||||
CompactionInputFiles* inputs, CompactionInputFiles* output_level_inputs,
|
||||
int* parent_index, int base_index, bool only_expand_towards_right) {
|
||||
assert(!inputs->empty());
|
||||
assert(output_level_inputs->empty());
|
||||
const int input_level = inputs->level;
|
||||
@@ -500,7 +499,6 @@ bool CompactionPicker::SetupOtherInputs(
|
||||
// user key, while excluding other entries for the same user key. This
|
||||
// can happen when one user key spans multiple files.
|
||||
if (!output_level_inputs->empty()) {
|
||||
const uint64_t limit = mutable_cf_options.max_compaction_bytes;
|
||||
const uint64_t output_level_inputs_size =
|
||||
TotalFileSize(output_level_inputs->files);
|
||||
const uint64_t inputs_size = TotalFileSize(inputs->files);
|
||||
@@ -527,8 +525,6 @@ bool CompactionPicker::SetupOtherInputs(
|
||||
try_overlapping_inputs = false;
|
||||
}
|
||||
if (try_overlapping_inputs && expanded_inputs.size() > inputs->size() &&
|
||||
(mutable_cf_options.ignore_max_compaction_bytes_for_input ||
|
||||
output_level_inputs_size + expanded_inputs_size < limit) &&
|
||||
!AreFilesInCompaction(expanded_inputs.files)) {
|
||||
InternalKey new_start, new_limit;
|
||||
GetRange(expanded_inputs, &new_start, &new_limit);
|
||||
@@ -551,8 +547,6 @@ bool CompactionPicker::SetupOtherInputs(
|
||||
base_index, nullptr);
|
||||
expanded_inputs_size = TotalFileSize(expanded_inputs.files);
|
||||
if (expanded_inputs.size() > inputs->size() &&
|
||||
(mutable_cf_options.ignore_max_compaction_bytes_for_input ||
|
||||
output_level_inputs_size + expanded_inputs_size < limit) &&
|
||||
!AreFilesInCompaction(expanded_inputs.files)) {
|
||||
expand_inputs = true;
|
||||
}
|
||||
@@ -812,8 +806,8 @@ Compaction* CompactionPicker::CompactRange(
|
||||
output_level_inputs.level = output_level;
|
||||
if (input_level != output_level) {
|
||||
int parent_index = -1;
|
||||
if (!SetupOtherInputs(cf_name, mutable_cf_options, vstorage, &inputs,
|
||||
&output_level_inputs, &parent_index, -1)) {
|
||||
if (!SetupOtherInputs(cf_name, vstorage, &inputs, &output_level_inputs,
|
||||
&parent_index, -1)) {
|
||||
// manual compaction is now multi-threaded, so it can
|
||||
// happen that SetupOtherInputs fails
|
||||
// we handle it higher in RunManualCompaction
|
||||
|
||||
@@ -186,7 +186,6 @@ class CompactionPicker {
|
||||
int penultimate_level) const;
|
||||
|
||||
bool SetupOtherInputs(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
VersionStorageInfo* vstorage,
|
||||
CompactionInputFiles* inputs,
|
||||
CompactionInputFiles* output_level_inputs,
|
||||
@@ -277,8 +276,7 @@ class NullCompactionPicker : public CompactionPicker {
|
||||
}
|
||||
|
||||
// Always returns false.
|
||||
virtual bool NeedsCompaction(
|
||||
const VersionStorageInfo* /*vstorage*/) const override {
|
||||
bool NeedsCompaction(const VersionStorageInfo* /*vstorage*/) const override {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,26 +18,27 @@ class FIFOCompactionPicker : public CompactionPicker {
|
||||
const InternalKeyComparator* icmp)
|
||||
: CompactionPicker(ioptions, icmp) {}
|
||||
|
||||
virtual Compaction* PickCompaction(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
const MutableDBOptions& mutable_db_options,
|
||||
VersionStorageInfo* version,
|
||||
LogBuffer* log_buffer) override;
|
||||
Compaction* PickCompaction(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
const MutableDBOptions& mutable_db_options,
|
||||
VersionStorageInfo* version,
|
||||
LogBuffer* log_buffer) override;
|
||||
|
||||
virtual Compaction* CompactRange(
|
||||
const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
|
||||
const MutableDBOptions& mutable_db_options, VersionStorageInfo* vstorage,
|
||||
int input_level, int output_level,
|
||||
const CompactRangeOptions& compact_range_options,
|
||||
const InternalKey* begin, const InternalKey* end,
|
||||
InternalKey** compaction_end, bool* manual_conflict,
|
||||
uint64_t max_file_num_to_ignore, const std::string& trim_ts) override;
|
||||
Compaction* CompactRange(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
const MutableDBOptions& mutable_db_options,
|
||||
VersionStorageInfo* vstorage, int input_level,
|
||||
int output_level,
|
||||
const CompactRangeOptions& compact_range_options,
|
||||
const InternalKey* begin, const InternalKey* end,
|
||||
InternalKey** compaction_end, bool* manual_conflict,
|
||||
uint64_t max_file_num_to_ignore,
|
||||
const std::string& trim_ts) override;
|
||||
|
||||
// The maximum allowed output level. Always returns 0.
|
||||
virtual int MaxOutputLevel() const override { return 0; }
|
||||
int MaxOutputLevel() const override { return 0; }
|
||||
|
||||
virtual bool NeedsCompaction(
|
||||
const VersionStorageInfo* vstorage) const override;
|
||||
bool NeedsCompaction(const VersionStorageInfo* vstorage) const override;
|
||||
|
||||
private:
|
||||
Compaction* PickTTLCompaction(const std::string& cf_name,
|
||||
|
||||
@@ -45,6 +45,13 @@ 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:
|
||||
@@ -106,6 +113,15 @@ class LevelCompactionBuilder {
|
||||
// otherwise, returns false.
|
||||
bool PickIntraL0Compaction();
|
||||
|
||||
// When total L0 size is small compared to Lbase, try to pick intra-L0
|
||||
// compaction starting from the newest L0 file. This helps to prevent
|
||||
// L0->Lbase compaction with large write-amp.
|
||||
//
|
||||
// Returns true iff an intra-L0 compaction is picked.
|
||||
// `start_level_inputs_` and `output_level_` will be updated accordingly if
|
||||
// a compaction is picked.
|
||||
bool PickSizeBasedIntraL0Compaction();
|
||||
|
||||
// Return true if TrivialMove is extended. `start_index` is the index of
|
||||
// the initial file picked, which should already be in `start_level_inputs_`.
|
||||
bool TryExtendNonL0TrivialMove(int start_index,
|
||||
@@ -115,9 +131,10 @@ 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,
|
||||
bool compact_to_next_level);
|
||||
CompactToNextLevel compact_to_next_level);
|
||||
|
||||
const std::string& cf_name_;
|
||||
VersionStorageInfo* vstorage_;
|
||||
@@ -149,20 +166,24 @@ class LevelCompactionBuilder {
|
||||
|
||||
void LevelCompactionBuilder::PickFileToCompact(
|
||||
const autovector<std::pair<int, FileMetaData*>>& level_files,
|
||||
bool compact_to_next_level) {
|
||||
CompactToNextLevel 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 &&
|
||||
if ((compact_to_next_level == CompactToNextLevel::kSkipLastLevel &&
|
||||
start_level_ == vstorage_->num_non_empty_levels() - 1) ||
|
||||
(start_level_ == 0 &&
|
||||
!compaction_picker_->level0_compactions_in_progress()->empty())) {
|
||||
continue;
|
||||
}
|
||||
if (compact_to_next_level) {
|
||||
|
||||
// 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)) {
|
||||
output_level_ =
|
||||
(start_level_ == 0) ? vstorage_->base_level() : start_level_ + 1;
|
||||
} else {
|
||||
@@ -248,7 +269,8 @@ void LevelCompactionBuilder::SetupInitialFiles() {
|
||||
}
|
||||
|
||||
// Bottommost Files Compaction on deleting tombstones
|
||||
PickFileToCompact(vstorage_->BottommostFilesMarkedForCompaction(), false);
|
||||
PickFileToCompact(vstorage_->BottommostFilesMarkedForCompaction(),
|
||||
CompactToNextLevel::kNo);
|
||||
if (!start_level_inputs_.empty()) {
|
||||
compaction_reason_ = CompactionReason::kBottommostFiles;
|
||||
return;
|
||||
@@ -274,21 +296,26 @@ void LevelCompactionBuilder::SetupInitialFiles() {
|
||||
}
|
||||
}
|
||||
|
||||
PickFileToCompact(vstorage_->ExpiredTtlFiles(), true);
|
||||
PickFileToCompact(vstorage_->ExpiredTtlFiles(),
|
||||
CompactToNextLevel::kSkipLastLevel);
|
||||
if (!start_level_inputs_.empty()) {
|
||||
compaction_reason_ = CompactionReason::kTtl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Periodic Compaction
|
||||
PickFileToCompact(vstorage_->FilesMarkedForPeriodicCompaction(), false);
|
||||
PickFileToCompact(vstorage_->FilesMarkedForPeriodicCompaction(),
|
||||
ioptions_.level_compaction_dynamic_level_bytes
|
||||
? CompactToNextLevel::kYes
|
||||
: CompactToNextLevel::kNo);
|
||||
if (!start_level_inputs_.empty()) {
|
||||
compaction_reason_ = CompactionReason::kPeriodicCompaction;
|
||||
return;
|
||||
}
|
||||
|
||||
// Forced blob garbage collection
|
||||
PickFileToCompact(vstorage_->FilesMarkedForForcedBlobGC(), false);
|
||||
PickFileToCompact(vstorage_->FilesMarkedForForcedBlobGC(),
|
||||
CompactToNextLevel::kNo);
|
||||
if (!start_level_inputs_.empty()) {
|
||||
compaction_reason_ = CompactionReason::kForcedBlobGC;
|
||||
return;
|
||||
@@ -438,9 +465,8 @@ bool LevelCompactionBuilder::SetupOtherInputsIfNeeded() {
|
||||
}
|
||||
if (!is_l0_trivial_move_ &&
|
||||
!compaction_picker_->SetupOtherInputs(
|
||||
cf_name_, mutable_cf_options_, vstorage_, &start_level_inputs_,
|
||||
&output_level_inputs_, &parent_index_, base_index_,
|
||||
round_robin_expanding)) {
|
||||
cf_name_, vstorage_, &start_level_inputs_, &output_level_inputs_,
|
||||
&parent_index_, base_index_, round_robin_expanding)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -758,6 +784,9 @@ bool LevelCompactionBuilder::PickFileToCompact() {
|
||||
// being compacted at level 0.
|
||||
if (start_level_ == 0 &&
|
||||
!compaction_picker_->level0_compactions_in_progress()->empty()) {
|
||||
if (PickSizeBasedIntraL0Compaction()) {
|
||||
return true;
|
||||
}
|
||||
TEST_SYNC_POINT("LevelCompactionPicker::PickCompactionBySize:0");
|
||||
return false;
|
||||
}
|
||||
@@ -770,6 +799,9 @@ bool LevelCompactionBuilder::PickFileToCompact() {
|
||||
if (TryPickL0TrivialMove()) {
|
||||
return true;
|
||||
}
|
||||
if (start_level_ == 0 && PickSizeBasedIntraL0Compaction()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<FileMetaData*>& level_files =
|
||||
vstorage_->LevelFiles(start_level_);
|
||||
@@ -874,6 +906,56 @@ bool LevelCompactionBuilder::PickIntraL0Compaction() {
|
||||
mutable_cf_options_.max_compaction_bytes,
|
||||
&start_level_inputs_);
|
||||
}
|
||||
|
||||
bool LevelCompactionBuilder::PickSizeBasedIntraL0Compaction() {
|
||||
assert(start_level_ == 0);
|
||||
int base_level = vstorage_->base_level();
|
||||
if (base_level <= 0) {
|
||||
return false;
|
||||
}
|
||||
const std::vector<FileMetaData*>& l0_files =
|
||||
vstorage_->LevelFiles(/*level=*/0);
|
||||
size_t min_num_file =
|
||||
std::max(2, mutable_cf_options_.level0_file_num_compaction_trigger);
|
||||
if (l0_files.size() < min_num_file) {
|
||||
return false;
|
||||
}
|
||||
uint64_t l0_size = 0;
|
||||
for (const auto& file : l0_files) {
|
||||
l0_size += file->fd.GetFileSize();
|
||||
}
|
||||
const uint64_t min_lbase_size =
|
||||
l0_size * static_cast<uint64_t>(std::max(
|
||||
10.0, mutable_cf_options_.max_bytes_for_level_multiplier));
|
||||
assert(min_lbase_size >= l0_size);
|
||||
const std::vector<FileMetaData*>& lbase_files =
|
||||
vstorage_->LevelFiles(/*level=*/base_level);
|
||||
uint64_t lbase_size = 0;
|
||||
for (const auto& file : lbase_files) {
|
||||
lbase_size += file->fd.GetFileSize();
|
||||
if (lbase_size > min_lbase_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lbase_size <= min_lbase_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
start_level_inputs_.clear();
|
||||
start_level_inputs_.level = 0;
|
||||
for (const auto& file : l0_files) {
|
||||
if (file->being_compacted) {
|
||||
break;
|
||||
}
|
||||
start_level_inputs_.files.push_back(file);
|
||||
}
|
||||
if (start_level_inputs_.files.size() < min_num_file) {
|
||||
start_level_inputs_.clear();
|
||||
return false;
|
||||
}
|
||||
output_level_ = 0;
|
||||
return true /* picked an intra-L0 compaction */;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Compaction* LevelCompactionPicker::PickCompaction(
|
||||
|
||||
@@ -20,14 +20,13 @@ class LevelCompactionPicker : public CompactionPicker {
|
||||
LevelCompactionPicker(const ImmutableOptions& ioptions,
|
||||
const InternalKeyComparator* icmp)
|
||||
: CompactionPicker(ioptions, icmp) {}
|
||||
virtual Compaction* PickCompaction(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
const MutableDBOptions& mutable_db_options,
|
||||
VersionStorageInfo* vstorage,
|
||||
LogBuffer* log_buffer) override;
|
||||
Compaction* PickCompaction(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
const MutableDBOptions& mutable_db_options,
|
||||
VersionStorageInfo* vstorage,
|
||||
LogBuffer* log_buffer) override;
|
||||
|
||||
virtual bool NeedsCompaction(
|
||||
const VersionStorageInfo* vstorage) const override;
|
||||
bool NeedsCompaction(const VersionStorageInfo* vstorage) const override;
|
||||
};
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
@@ -1443,15 +1443,12 @@ TEST_F(CompactionPickerTest, CompactionPriMinOverlapping4) {
|
||||
ioptions_.compaction_pri = kMinOverlappingRatio;
|
||||
mutable_cf_options_.max_bytes_for_level_base = 10000000;
|
||||
mutable_cf_options_.max_bytes_for_level_multiplier = 10;
|
||||
mutable_cf_options_.ignore_max_compaction_bytes_for_input = false;
|
||||
|
||||
// file 7 and 8 over lap with the same file, but file 8 is smaller so
|
||||
// it will be picked.
|
||||
// Overlaps with file 26, 27. And the file is compensated so will be
|
||||
// picked up.
|
||||
// Overlaps with file 26, 27, ratio is
|
||||
// (60000000U + 60000000U / 180000000U) = 0.67
|
||||
Add(2, 6U, "150", "167", 60000000U, 0, 100, 100, 180000000U);
|
||||
Add(2, 7U, "168", "169", 60000000U); // Overlaps with file 27
|
||||
Add(2, 8U, "201", "300", 61000000U); // Overlaps with file 28
|
||||
Add(2, 7U, "178", "189", 60000000U); // Overlaps with file 28
|
||||
Add(2, 8U, "401", "500", 61000000U); // Overlaps with file 29
|
||||
|
||||
Add(3, 26U, "160", "165", 60000000U);
|
||||
// Boosted file size in output level is not considered.
|
||||
@@ -1465,7 +1462,7 @@ TEST_F(CompactionPickerTest, CompactionPriMinOverlapping4) {
|
||||
&log_buffer_));
|
||||
ASSERT_TRUE(compaction.get() != nullptr);
|
||||
ASSERT_EQ(1U, compaction->num_input_files(0));
|
||||
// Picking file 8 because overlapping ratio is the biggest.
|
||||
// Picking file 6 because overlapping ratio is the biggest.
|
||||
ASSERT_EQ(6U, compaction->input(0, 0)->fd.GetNumber());
|
||||
}
|
||||
|
||||
@@ -2468,20 +2465,23 @@ TEST_F(CompactionPickerTest, IsBottommostLevelTest) {
|
||||
DeleteVersionStorage();
|
||||
}
|
||||
|
||||
TEST_F(CompactionPickerTest, MaxCompactionBytesHit) {
|
||||
TEST_F(CompactionPickerTest, IgnoreCompactionLimitWhenAddFileFromInputLevel) {
|
||||
mutable_cf_options_.max_bytes_for_level_base = 1000000u;
|
||||
mutable_cf_options_.max_compaction_bytes = 800000u;
|
||||
mutable_cf_options_.ignore_max_compaction_bytes_for_input = false;
|
||||
ioptions_.level_compaction_dynamic_level_bytes = false;
|
||||
NewVersionStorage(6, kCompactionStyleLevel);
|
||||
// A compaction should be triggered and pick file 2 and 5.
|
||||
// It can expand because adding file 1 and 3, the compaction size will
|
||||
// exceed mutable_cf_options_.max_bytes_for_level_base.
|
||||
// It pulls in other compaction input file from the input level L1
|
||||
// without pulling in more output level files.
|
||||
// Files 1, 3, 4 will be included in the compaction.
|
||||
// File 6 is excluded since it overlaps with file 7.
|
||||
Add(1, 1U, "100", "150", 300000U);
|
||||
Add(1, 2U, "151", "200", 300001U, 0, 0);
|
||||
Add(1, 3U, "201", "250", 300000U, 0, 0);
|
||||
Add(1, 4U, "251", "300", 300000U, 0, 0);
|
||||
Add(2, 5U, "100", "256", 1U);
|
||||
Add(1, 6U, "325", "400", 300000U, 0, 0);
|
||||
Add(2, 5U, "100", "350", 1U);
|
||||
Add(2, 7U, "375", "425", 1U);
|
||||
UpdateVersionStorageInfo();
|
||||
|
||||
std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
|
||||
@@ -2489,37 +2489,12 @@ TEST_F(CompactionPickerTest, MaxCompactionBytesHit) {
|
||||
&log_buffer_));
|
||||
ASSERT_TRUE(compaction.get() != nullptr);
|
||||
ASSERT_EQ(2U, compaction->num_input_levels());
|
||||
ASSERT_EQ(1U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(1U, compaction->num_input_files(1));
|
||||
ASSERT_EQ(2U, compaction->input(0, 0)->fd.GetNumber());
|
||||
ASSERT_EQ(5U, compaction->input(1, 0)->fd.GetNumber());
|
||||
}
|
||||
|
||||
TEST_F(CompactionPickerTest, MaxCompactionBytesNotHit) {
|
||||
mutable_cf_options_.max_bytes_for_level_base = 800000u;
|
||||
mutable_cf_options_.max_compaction_bytes = 1000000u;
|
||||
mutable_cf_options_.ignore_max_compaction_bytes_for_input = false;
|
||||
ioptions_.level_compaction_dynamic_level_bytes = false;
|
||||
NewVersionStorage(6, kCompactionStyleLevel);
|
||||
// A compaction should be triggered and pick file 2 and 5.
|
||||
// and it expands to file 1 and 3 too.
|
||||
Add(1, 1U, "100", "150", 300000U);
|
||||
Add(1, 2U, "151", "200", 300001U, 0, 0);
|
||||
Add(1, 3U, "201", "250", 300000U, 0, 0);
|
||||
Add(1, 4U, "251", "300", 300000U, 0, 0);
|
||||
Add(2, 5U, "000", "251", 1U);
|
||||
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.get() != nullptr);
|
||||
ASSERT_EQ(2U, compaction->num_input_levels());
|
||||
ASSERT_EQ(3U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(4U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(1U, compaction->num_input_files(1));
|
||||
ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber());
|
||||
ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber());
|
||||
ASSERT_EQ(3U, compaction->input(0, 2)->fd.GetNumber());
|
||||
ASSERT_EQ(4U, compaction->input(0, 3)->fd.GetNumber());
|
||||
ASSERT_EQ(5U, compaction->input(1, 0)->fd.GetNumber());
|
||||
}
|
||||
|
||||
@@ -4149,9 +4124,177 @@ 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());
|
||||
|
||||
TEST_F(CompactionPickerTest, IntraL0WhenL0IsSmall) {
|
||||
mutable_cf_options_.level0_file_num_compaction_trigger = 4;
|
||||
mutable_cf_options_.max_bytes_for_level_multiplier = 10;
|
||||
for (const uint64_t lbase_size_multiplier : {1, 10, 11, 40}) {
|
||||
SCOPED_TRACE("lbase_size_multiplier=" +
|
||||
std::to_string(lbase_size_multiplier));
|
||||
NewVersionStorage(6, kCompactionStyleLevel);
|
||||
// When L0 size is <= Lbase size / max_bytes_for_level_multiplier,
|
||||
// intra-L0 compaction is picked. Otherwise, L0->L1
|
||||
// compaction is picked.
|
||||
Add(/*level=*/0, /*file_number=*/1U, /*smallest=*/"100",
|
||||
/*largest=*/"200", /*file_size=*/1000, /*path_id=*/0,
|
||||
/*smallest_seq=*/10, /*largest_seq=*/11,
|
||||
/*compensated_file_size=*/1000);
|
||||
Add(/*level=*/0, /*file_number=*/2U, /*smallest=*/"100",
|
||||
/*largest=*/"100", /*file_size=*/1000, /*path_id=*/0,
|
||||
/*smallest_seq=*/20, /*largest_seq=*/21,
|
||||
/*compensated_file_size=*/1000);
|
||||
Add(/*level=*/0, /*file_number=*/3U, /*smallest=*/"100",
|
||||
/*largest=*/"200", /*file_size=*/1000, /*path_id=*/0,
|
||||
/*smallest_seq=*/30, /*largest_seq=*/31,
|
||||
/*compensated_file_size=*/1000);
|
||||
Add(/*level=*/0, /*file_number=*/4U, /*smallest=*/"100",
|
||||
/*largest=*/"200", /*file_size=*/1000, /*path_id=*/0,
|
||||
/*smallest_seq=*/40, /*largest_seq=*/41,
|
||||
/*compensated_file_size=*/1000);
|
||||
const uint64_t l0_size = 4000;
|
||||
const uint64_t lbase_size = l0_size * lbase_size_multiplier;
|
||||
Add(/*level=*/1, /*file_number=*/5U, /*smallest=*/"100",
|
||||
/*largest=*/"200", /*file_size=*/lbase_size, /*path_id=*/0,
|
||||
/*smallest_seq=*/0, /*largest_seq=*/0,
|
||||
/*compensated_file_size=*/lbase_size);
|
||||
UpdateVersionStorageInfo();
|
||||
|
||||
LevelCompactionPicker compaction_picker(ioptions_, &icmp_);
|
||||
std::unique_ptr<Compaction> compaction(compaction_picker.PickCompaction(
|
||||
cf_name_, mutable_cf_options_, mutable_db_options_, vstorage_.get(),
|
||||
&log_buffer_));
|
||||
ASSERT_TRUE(compaction.get() != nullptr);
|
||||
ASSERT_EQ(CompactionReason::kLevelL0FilesNum,
|
||||
compaction->compaction_reason());
|
||||
ASSERT_EQ(4U, compaction->num_input_files(0));
|
||||
if (lbase_size_multiplier >
|
||||
mutable_cf_options_.max_bytes_for_level_multiplier) {
|
||||
ASSERT_EQ(1U, compaction->num_input_levels());
|
||||
ASSERT_EQ(0, compaction->output_level());
|
||||
} else {
|
||||
ASSERT_EQ(2U, compaction->num_input_levels());
|
||||
ASSERT_EQ(1, compaction->output_level());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
||||
|
||||
@@ -1139,8 +1139,7 @@ Compaction* UniversalCompactionBuilder::PickIncrementalForReduceSizeAmp(
|
||||
// from bottom_start_idx and bottom_end_idx, but for now, we use
|
||||
// SetupOtherInputs() for simplicity.
|
||||
int parent_index = -1; // Create and use bottom_start_idx?
|
||||
if (!picker_->SetupOtherInputs(cf_name_, mutable_cf_options_, vstorage_,
|
||||
&second_last_level_inputs,
|
||||
if (!picker_->SetupOtherInputs(cf_name_, vstorage_, &second_last_level_inputs,
|
||||
&bottom_level_inputs, &parent_index,
|
||||
/*base_index=*/-1)) {
|
||||
return nullptr;
|
||||
@@ -1311,9 +1310,8 @@ Compaction* UniversalCompactionBuilder::PickDeleteTriggeredCompaction() {
|
||||
int parent_index = -1;
|
||||
|
||||
output_level_inputs.level = output_level;
|
||||
if (!picker_->SetupOtherInputs(cf_name_, mutable_cf_options_, vstorage_,
|
||||
&start_level_inputs, &output_level_inputs,
|
||||
&parent_index, -1)) {
|
||||
if (!picker_->SetupOtherInputs(cf_name_, vstorage_, &start_level_inputs,
|
||||
&output_level_inputs, &parent_index, -1)) {
|
||||
return nullptr;
|
||||
}
|
||||
inputs.push_back(start_level_inputs);
|
||||
|
||||
@@ -17,14 +17,13 @@ class UniversalCompactionPicker : public CompactionPicker {
|
||||
UniversalCompactionPicker(const ImmutableOptions& ioptions,
|
||||
const InternalKeyComparator* icmp)
|
||||
: CompactionPicker(ioptions, icmp) {}
|
||||
virtual Compaction* PickCompaction(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
const MutableDBOptions& mutable_db_options,
|
||||
VersionStorageInfo* vstorage,
|
||||
LogBuffer* log_buffer) override;
|
||||
virtual int MaxOutputLevel() const override { return NumberLevels() - 1; }
|
||||
Compaction* PickCompaction(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
const MutableDBOptions& mutable_db_options,
|
||||
VersionStorageInfo* vstorage,
|
||||
LogBuffer* log_buffer) override;
|
||||
int MaxOutputLevel() const override { return NumberLevels() - 1; }
|
||||
|
||||
virtual bool NeedsCompaction(
|
||||
const VersionStorageInfo* vstorage) const override;
|
||||
bool NeedsCompaction(const VersionStorageInfo* vstorage) const override;
|
||||
};
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
@@ -195,8 +195,8 @@ CompactionJob::ProcessKeyValueCompactionWithCompactionService(
|
||||
|
||||
auto cfd = compaction->column_family_data();
|
||||
sub_compact->Current().AddOutput(std::move(meta),
|
||||
cfd->internal_comparator(), false, false,
|
||||
true, file.paranoid_hash);
|
||||
cfd->internal_comparator(), false, true,
|
||||
file.paranoid_hash);
|
||||
}
|
||||
sub_compact->compaction_job_stats = compaction_result.stats;
|
||||
sub_compact->Current().SetNumOutputRecords(
|
||||
|
||||
@@ -1338,7 +1338,7 @@ class PrecludeLastLevelTest : public DBTestBase {
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::StartPeriodicTaskScheduler:Init", [&](void* arg) {
|
||||
auto periodic_task_scheduler_ptr =
|
||||
reinterpret_cast<PeriodicTaskScheduler*>(arg);
|
||||
static_cast<PeriodicTaskScheduler*>(arg);
|
||||
periodic_task_scheduler_ptr->TEST_OverrideTimer(mock_clock_.get());
|
||||
});
|
||||
mock_clock_->SetCurrentTime(kMockStartTime);
|
||||
@@ -1575,9 +1575,8 @@ 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.Add(tables_props.begin()->second->seqno_to_time_mapping));
|
||||
ASSERT_OK(tp_mapping.Sort());
|
||||
ASSERT_OK(tp_mapping.DecodeFrom(
|
||||
tables_props.begin()->second->seqno_to_time_mapping));
|
||||
ASSERT_FALSE(tp_mapping.Empty());
|
||||
auto seqs = tp_mapping.TEST_GetInternalMapping();
|
||||
ASSERT_FALSE(seqs.empty());
|
||||
@@ -1824,7 +1823,6 @@ TEST_P(PrecludeLastLevelTestWithParms, PeriodicCompactionToPenultimateLevel) {
|
||||
options.env = mock_env_.get();
|
||||
options.level0_file_num_compaction_trigger = kNumTrigger;
|
||||
options.num_levels = kNumLevels;
|
||||
options.ignore_max_compaction_bytes_for_input = false;
|
||||
options.periodic_compaction_seconds = 10000;
|
||||
DestroyAndReopen(options);
|
||||
|
||||
|
||||
+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
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
const ReadOptions read_options;
|
||||
return VerifySstFileChecksum(options, env_options, read_options, file_path);
|
||||
}
|
||||
|
||||
+7
-38
@@ -53,10 +53,9 @@ class ErrorFS : public FileSystemWrapper {
|
||||
num_writable_file_errors_(0) {}
|
||||
const char* Name() const override { return "ErrorEnv"; }
|
||||
|
||||
virtual IOStatus NewWritableFile(const std::string& fname,
|
||||
const FileOptions& opts,
|
||||
std::unique_ptr<FSWritableFile>* result,
|
||||
IODebugContext* dbg) override {
|
||||
IOStatus NewWritableFile(const std::string& fname, const FileOptions& opts,
|
||||
std::unique_ptr<FSWritableFile>* result,
|
||||
IODebugContext* dbg) override {
|
||||
result->reset();
|
||||
if (writable_file_error_) {
|
||||
++num_writable_file_errors_;
|
||||
@@ -823,7 +822,6 @@ TEST_F(CorruptionTest, ParanoidFileChecksOnFlush) {
|
||||
Options options;
|
||||
options.level_compaction_dynamic_level_bytes = false;
|
||||
options.env = env_.get();
|
||||
options.check_flush_compaction_key_order = false;
|
||||
options.paranoid_file_checks = true;
|
||||
options.create_if_missing = true;
|
||||
Status s;
|
||||
@@ -854,7 +852,6 @@ TEST_F(CorruptionTest, ParanoidFileChecksOnCompact) {
|
||||
options.env = env_.get();
|
||||
options.paranoid_file_checks = true;
|
||||
options.create_if_missing = true;
|
||||
options.check_flush_compaction_key_order = false;
|
||||
Status s;
|
||||
for (const auto& mode : corruption_modes) {
|
||||
delete db_;
|
||||
@@ -886,7 +883,6 @@ TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRangeFirst) {
|
||||
Options options;
|
||||
options.level_compaction_dynamic_level_bytes = false;
|
||||
options.env = env_.get();
|
||||
options.check_flush_compaction_key_order = false;
|
||||
options.paranoid_file_checks = true;
|
||||
options.create_if_missing = true;
|
||||
for (bool do_flush : {true, false}) {
|
||||
@@ -923,7 +919,6 @@ TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRange) {
|
||||
Options options;
|
||||
options.level_compaction_dynamic_level_bytes = false;
|
||||
options.env = env_.get();
|
||||
options.check_flush_compaction_key_order = false;
|
||||
options.paranoid_file_checks = true;
|
||||
options.create_if_missing = true;
|
||||
for (bool do_flush : {true, false}) {
|
||||
@@ -963,7 +958,6 @@ TEST_F(CorruptionTest, ParanoidFileChecksWithDeleteRangeLast) {
|
||||
Options options;
|
||||
options.level_compaction_dynamic_level_bytes = false;
|
||||
options.env = env_.get();
|
||||
options.check_flush_compaction_key_order = false;
|
||||
options.paranoid_file_checks = true;
|
||||
options.create_if_missing = true;
|
||||
for (bool do_flush : {true, false}) {
|
||||
@@ -1032,7 +1026,6 @@ TEST_F(CorruptionTest, CompactionKeyOrderCheck) {
|
||||
options.env = env_.get();
|
||||
options.paranoid_file_checks = false;
|
||||
options.create_if_missing = true;
|
||||
options.check_flush_compaction_key_order = false;
|
||||
delete db_;
|
||||
db_ = nullptr;
|
||||
ASSERT_OK(DestroyDB(dbname_, options));
|
||||
@@ -1047,7 +1040,6 @@ TEST_F(CorruptionTest, CompactionKeyOrderCheck) {
|
||||
ASSERT_OK(dbi->TEST_FlushMemTable());
|
||||
|
||||
mock->SetCorruptionMode(mock::MockTableFactory::kCorruptNone);
|
||||
ASSERT_OK(db_->SetOptions({{"check_flush_compaction_key_order", "true"}}));
|
||||
CompactRangeOptions cro;
|
||||
cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
|
||||
ASSERT_NOK(
|
||||
@@ -1060,7 +1052,6 @@ TEST_F(CorruptionTest, FlushKeyOrderCheck) {
|
||||
options.env = env_.get();
|
||||
options.paranoid_file_checks = false;
|
||||
options.create_if_missing = true;
|
||||
ASSERT_OK(db_->SetOptions({{"check_flush_compaction_key_order", "true"}}));
|
||||
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo1", "v1"));
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo2", "v1"));
|
||||
@@ -1085,28 +1076,6 @@ TEST_F(CorruptionTest, FlushKeyOrderCheck) {
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
}
|
||||
|
||||
TEST_F(CorruptionTest, DisableKeyOrderCheck) {
|
||||
ASSERT_OK(db_->SetOptions({{"check_flush_compaction_key_order", "false"}}));
|
||||
DBImpl* dbi = static_cast_with_check<DBImpl>(db_);
|
||||
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"OutputValidator::Add:order_check",
|
||||
[&](void* /*arg*/) { ASSERT_TRUE(false); });
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo1", "v1"));
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo3", "v1"));
|
||||
ASSERT_OK(dbi->TEST_FlushMemTable());
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo2", "v1"));
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "foo4", "v1"));
|
||||
ASSERT_OK(dbi->TEST_FlushMemTable());
|
||||
CompactRangeOptions cro;
|
||||
cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
|
||||
ASSERT_OK(
|
||||
dbi->CompactRange(cro, dbi->DefaultColumnFamily(), nullptr, nullptr));
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
}
|
||||
|
||||
TEST_F(CorruptionTest, VerifyWholeTableChecksum) {
|
||||
CloseDb();
|
||||
Options options;
|
||||
@@ -1133,7 +1102,7 @@ TEST_F(CorruptionTest, VerifyWholeTableChecksum) {
|
||||
int count{0};
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::VerifyFullFileChecksum:mismatch", [&](void* arg) {
|
||||
auto* s = reinterpret_cast<Status*>(arg);
|
||||
auto* s = static_cast<Status*>(arg);
|
||||
ASSERT_NE(s, nullptr);
|
||||
++count;
|
||||
ASSERT_NOK(*s);
|
||||
@@ -1278,7 +1247,7 @@ TEST_P(CrashDuringRecoveryWithCorruptionTest, CrashDuringRecovery) {
|
||||
SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::GetLogSizeAndMaybeTruncate:0", [&](void* arg) {
|
||||
auto* tmp_s = reinterpret_cast<Status*>(arg);
|
||||
auto* tmp_s = static_cast<Status*>(arg);
|
||||
assert(tmp_s);
|
||||
*tmp_s = Status::IOError("Injected");
|
||||
});
|
||||
@@ -1460,7 +1429,7 @@ TEST_P(CrashDuringRecoveryWithCorruptionTest, TxnDbCrashDuringRecovery) {
|
||||
SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::Open::BeforeSyncWAL", [&](void* arg) {
|
||||
auto* tmp_s = reinterpret_cast<Status*>(arg);
|
||||
auto* tmp_s = static_cast<Status*>(arg);
|
||||
assert(tmp_s);
|
||||
*tmp_s = Status::IOError("Injected");
|
||||
});
|
||||
@@ -1628,7 +1597,7 @@ TEST_P(CrashDuringRecoveryWithCorruptionTest, CrashDuringRecoveryWithFlush) {
|
||||
SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::GetLogSizeAndMaybeTruncate:0", [&](void* arg) {
|
||||
auto* tmp_s = reinterpret_cast<Status*>(arg);
|
||||
auto* tmp_s = static_cast<Status*>(arg);
|
||||
assert(tmp_s);
|
||||
*tmp_s = Status::IOError("Injected");
|
||||
});
|
||||
|
||||
@@ -131,7 +131,7 @@ TEST_F(CuckooTableDBTest, Flush) {
|
||||
ASSERT_OK(dbfull()->TEST_FlushMemTable());
|
||||
|
||||
TablePropertiesCollection ptc;
|
||||
ASSERT_OK(reinterpret_cast<DB*>(dbfull())->GetPropertiesOfAllTables(&ptc));
|
||||
ASSERT_OK(static_cast<DB*>(dbfull())->GetPropertiesOfAllTables(&ptc));
|
||||
VerifySstUniqueIds(ptc);
|
||||
ASSERT_EQ(1U, ptc.size());
|
||||
ASSERT_EQ(3U, ptc.begin()->second->num_entries);
|
||||
@@ -148,7 +148,7 @@ TEST_F(CuckooTableDBTest, Flush) {
|
||||
ASSERT_OK(Put("key6", "v6"));
|
||||
ASSERT_OK(dbfull()->TEST_FlushMemTable());
|
||||
|
||||
ASSERT_OK(reinterpret_cast<DB*>(dbfull())->GetPropertiesOfAllTables(&ptc));
|
||||
ASSERT_OK(static_cast<DB*>(dbfull())->GetPropertiesOfAllTables(&ptc));
|
||||
VerifySstUniqueIds(ptc);
|
||||
ASSERT_EQ(2U, ptc.size());
|
||||
auto row = ptc.begin();
|
||||
@@ -166,7 +166,7 @@ TEST_F(CuckooTableDBTest, Flush) {
|
||||
ASSERT_OK(Delete("key5"));
|
||||
ASSERT_OK(Delete("key4"));
|
||||
ASSERT_OK(dbfull()->TEST_FlushMemTable());
|
||||
ASSERT_OK(reinterpret_cast<DB*>(dbfull())->GetPropertiesOfAllTables(&ptc));
|
||||
ASSERT_OK(static_cast<DB*>(dbfull())->GetPropertiesOfAllTables(&ptc));
|
||||
VerifySstUniqueIds(ptc);
|
||||
ASSERT_EQ(3U, ptc.size());
|
||||
row = ptc.begin();
|
||||
@@ -191,7 +191,7 @@ TEST_F(CuckooTableDBTest, FlushWithDuplicateKeys) {
|
||||
ASSERT_OK(dbfull()->TEST_FlushMemTable());
|
||||
|
||||
TablePropertiesCollection ptc;
|
||||
ASSERT_OK(reinterpret_cast<DB*>(dbfull())->GetPropertiesOfAllTables(&ptc));
|
||||
ASSERT_OK(static_cast<DB*>(dbfull())->GetPropertiesOfAllTables(&ptc));
|
||||
VerifySstUniqueIds(ptc);
|
||||
ASSERT_EQ(1U, ptc.size());
|
||||
ASSERT_EQ(2U, ptc.begin()->second->num_entries);
|
||||
|
||||
+278
-93
@@ -25,10 +25,60 @@
|
||||
#include "util/random.h"
|
||||
#include "utilities/counted_fs.h"
|
||||
#include "utilities/fault_injection_env.h"
|
||||
#include "utilities/fault_injection_fs.h"
|
||||
#include "utilities/merge_operators.h"
|
||||
#include "utilities/merge_operators/string_append/stringappend.h"
|
||||
|
||||
namespace ROCKSDB_NAMESPACE {
|
||||
namespace {
|
||||
class MyFlushBlockPolicy : public FlushBlockPolicy {
|
||||
public:
|
||||
explicit MyFlushBlockPolicy(const int num_keys_in_block,
|
||||
const BlockBuilder& data_block_builder)
|
||||
: num_keys_in_block_(num_keys_in_block),
|
||||
num_keys_(0),
|
||||
data_block_builder_(data_block_builder) {}
|
||||
|
||||
bool Update(const Slice& /*key*/, const Slice& /*value*/) override {
|
||||
if (data_block_builder_.empty()) {
|
||||
// First key in this block
|
||||
num_keys_ = 1;
|
||||
return false;
|
||||
}
|
||||
// Flush every 10 keys
|
||||
if (num_keys_ == num_keys_in_block_) {
|
||||
num_keys_ = 1;
|
||||
return true;
|
||||
}
|
||||
num_keys_++;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
const int num_keys_in_block_;
|
||||
int num_keys_;
|
||||
const BlockBuilder& data_block_builder_;
|
||||
};
|
||||
|
||||
class MyFlushBlockPolicyFactory : public FlushBlockPolicyFactory {
|
||||
public:
|
||||
explicit MyFlushBlockPolicyFactory(const int num_keys_in_block)
|
||||
: num_keys_in_block_(num_keys_in_block) {}
|
||||
|
||||
virtual const char* Name() const override {
|
||||
return "MyFlushBlockPolicyFactory";
|
||||
}
|
||||
|
||||
virtual FlushBlockPolicy* NewFlushBlockPolicy(
|
||||
const BlockBasedTableOptions& /*table_options*/,
|
||||
const BlockBuilder& data_block_builder) const override {
|
||||
return new MyFlushBlockPolicy(num_keys_in_block_, data_block_builder);
|
||||
}
|
||||
|
||||
private:
|
||||
const int num_keys_in_block_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static bool enable_io_uring = true;
|
||||
extern "C" bool RocksDbIOUringEnable() { return enable_io_uring; }
|
||||
@@ -1853,6 +1903,214 @@ TEST_P(DBMultiGetTestWithParam, MultiGetBatchedMultiLevel) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(DBMultiGetTestWithParam, MultiGetDuplicatesEmptyLevel) {
|
||||
#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;
|
||||
}
|
||||
std::shared_ptr<FaultInjectionTestFS> fault_fs(
|
||||
new FaultInjectionTestFS(env_->GetFileSystem()));
|
||||
std::unique_ptr<Env> env(new CompositeEnvWrapper(env_, fault_fs));
|
||||
Options options = CurrentOptions();
|
||||
options.env = env.get();
|
||||
options.disable_auto_compactions = true;
|
||||
options.merge_operator = MergeOperators::CreateStringAppendOperator();
|
||||
|
||||
LRUCacheOptions cache_opts;
|
||||
cache_opts.capacity = 1 << 20;
|
||||
|
||||
BlockBasedTableOptions table_opts;
|
||||
table_opts.metadata_cache_options.top_level_index_pinning = PinningTier::kAll;
|
||||
table_opts.metadata_cache_options.partition_pinning = PinningTier::kNone;
|
||||
table_opts.index_type =
|
||||
BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch;
|
||||
table_opts.cache_index_and_filter_blocks = true;
|
||||
table_opts.block_cache = cache_opts.MakeSharedCache();
|
||||
table_opts.flush_block_policy_factory.reset(new MyFlushBlockPolicyFactory(1));
|
||||
|
||||
options.table_factory.reset(new BlockBasedTableFactory(table_opts));
|
||||
Reopen(options);
|
||||
int key;
|
||||
|
||||
// Setup the LSM so that the following search bounds are generated for
|
||||
// key 9 for each level -
|
||||
// Level 1 - lb = 0, rb = max
|
||||
// Level 2 - lb = 0, rb = 0
|
||||
// Level 3 - lb = 0, rb = -1
|
||||
// Level 4 - lb = 0, rb = 0
|
||||
|
||||
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)));
|
||||
const Snapshot* snap = dbfull()->GetSnapshot();
|
||||
ASSERT_OK(
|
||||
Merge("key_" + std::to_string(key), "val_l2_ext_" + 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));
|
||||
|
||||
int num_reads = 0;
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"FaultInjectionTestFS::RandomRead", [&](void*) {
|
||||
++num_reads;
|
||||
// Fail on the 2nd read. First read is index partition,
|
||||
// second read is data block in level 1
|
||||
if (num_reads == 2) {
|
||||
fault_fs->SetFilesystemActive(false);
|
||||
} else {
|
||||
fault_fs->SetFilesystemActive(true);
|
||||
}
|
||||
});
|
||||
SyncPoint::GetInstance()->EnableProcessing();
|
||||
size_t capacity = table_opts.block_cache->GetCapacity();
|
||||
table_opts.block_cache->SetCapacity(0);
|
||||
table_opts.block_cache->SetCapacity(capacity);
|
||||
|
||||
values = MultiGet(keys, nullptr, std::get<1>(GetParam()));
|
||||
ASSERT_EQ(values.size(), 2);
|
||||
|
||||
SyncPoint::GetInstance()->DisableProcessing();
|
||||
dbfull()->ReleaseSnapshot(snap);
|
||||
Destroy(options);
|
||||
}
|
||||
|
||||
TEST_P(DBMultiGetTestWithParam, MultiGetDuplicatesNonEmptyLevel) {
|
||||
#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;
|
||||
}
|
||||
std::shared_ptr<FaultInjectionTestFS> fault_fs(
|
||||
new FaultInjectionTestFS(env_->GetFileSystem()));
|
||||
std::unique_ptr<Env> env(new CompositeEnvWrapper(env_, fault_fs));
|
||||
Options options = CurrentOptions();
|
||||
options.env = env.get();
|
||||
options.disable_auto_compactions = true;
|
||||
options.merge_operator = MergeOperators::CreateStringAppendOperator();
|
||||
|
||||
LRUCacheOptions cache_opts;
|
||||
cache_opts.capacity = 1 << 20;
|
||||
|
||||
BlockBasedTableOptions table_opts;
|
||||
table_opts.metadata_cache_options.top_level_index_pinning = PinningTier::kAll;
|
||||
table_opts.metadata_cache_options.partition_pinning = PinningTier::kNone;
|
||||
table_opts.index_type =
|
||||
BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch;
|
||||
table_opts.cache_index_and_filter_blocks = true;
|
||||
table_opts.block_cache = cache_opts.MakeSharedCache();
|
||||
table_opts.flush_block_policy_factory.reset(new MyFlushBlockPolicyFactory(1));
|
||||
|
||||
options.table_factory.reset(new BlockBasedTableFactory(table_opts));
|
||||
Reopen(options);
|
||||
int key;
|
||||
|
||||
// Setup the LSM so that the following search bounds are generated for
|
||||
// key 9 for each level -
|
||||
// Level 1 - lb = 0, rb = max
|
||||
// Level 2 - lb = 0, rb = 0
|
||||
// Level 3 - lb = 0, rb = 1
|
||||
// Level 4 - N/A
|
||||
|
||||
key = 8;
|
||||
ASSERT_OK(Put("key_" + std::to_string(key), "val_l2_" + std::to_string(key)));
|
||||
ASSERT_OK(Flush());
|
||||
MoveFilesToLevel(4);
|
||||
|
||||
key = 7;
|
||||
ASSERT_OK(Put("key_" + std::to_string(key), "val_l2_" + std::to_string(key)));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
key = 9;
|
||||
ASSERT_OK(Put("key_" + std::to_string(key), "val_l2_" + std::to_string(key)));
|
||||
ASSERT_OK(Flush());
|
||||
MoveFilesToLevel(3);
|
||||
|
||||
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), "merge1_l2_" + std::to_string(key)));
|
||||
const Snapshot* snap = dbfull()->GetSnapshot();
|
||||
ASSERT_OK(
|
||||
Merge("key_" + std::to_string(key), "merge2_l2_" + std::to_string(key)));
|
||||
ASSERT_OK(Flush());
|
||||
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));
|
||||
|
||||
int num_reads = 0;
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"FaultInjectionTestFS::RandomRead", [&](void*) {
|
||||
++num_reads;
|
||||
// Fail on the 2nd read. First read is index partition,
|
||||
// second read is data block in level 1
|
||||
if (num_reads == 2) {
|
||||
fault_fs->SetFilesystemActive(false);
|
||||
} else {
|
||||
fault_fs->SetFilesystemActive(true);
|
||||
}
|
||||
});
|
||||
SyncPoint::GetInstance()->EnableProcessing();
|
||||
size_t capacity = table_opts.block_cache->GetCapacity();
|
||||
table_opts.block_cache->SetCapacity(0);
|
||||
table_opts.block_cache->SetCapacity(capacity);
|
||||
|
||||
values = MultiGet(keys, nullptr, std::get<1>(GetParam()));
|
||||
ASSERT_EQ(values.size(), 2);
|
||||
ASSERT_EQ(values[0], "Corruption: Not active");
|
||||
ASSERT_EQ(values[1], "val_l2_9,merge1_l2_9,merge2_l2_9");
|
||||
|
||||
SyncPoint::GetInstance()->DisableProcessing();
|
||||
dbfull()->ReleaseSnapshot(snap);
|
||||
Destroy(options);
|
||||
}
|
||||
|
||||
TEST_P(DBMultiGetTestWithParam, MultiGetBatchedMultiLevelMerge) {
|
||||
#ifndef USE_COROUTINES
|
||||
if (std::get<1>(GetParam())) {
|
||||
@@ -3084,8 +3342,7 @@ TEST_F(DBBasicTest, BestEffortsRecoveryWithVersionBuildingFailure) {
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"VersionBuilder::CheckConsistencyBeforeReturn", [&](void* arg) {
|
||||
ASSERT_NE(nullptr, arg);
|
||||
*(reinterpret_cast<Status*>(arg)) =
|
||||
Status::Corruption("Inject corruption");
|
||||
*(static_cast<Status*>(arg)) = Status::Corruption("Inject corruption");
|
||||
});
|
||||
SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
@@ -3126,7 +3383,8 @@ 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));
|
||||
@@ -3515,7 +3773,7 @@ class DBBasicTestMultiGet : public DBTestBase {
|
||||
table_options.pin_l0_filter_and_index_blocks_in_cache = true;
|
||||
}
|
||||
table_options.flush_block_policy_factory.reset(
|
||||
new MyFlushBlockPolicyFactory());
|
||||
new MyFlushBlockPolicyFactory(10));
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
if (!compression_enabled_) {
|
||||
options.compression = kNoCompression;
|
||||
@@ -3603,46 +3861,6 @@ class DBBasicTestMultiGet : public DBTestBase {
|
||||
static void TearDownTestCase() {}
|
||||
|
||||
protected:
|
||||
class MyFlushBlockPolicyFactory : public FlushBlockPolicyFactory {
|
||||
public:
|
||||
MyFlushBlockPolicyFactory() {}
|
||||
|
||||
virtual const char* Name() const override {
|
||||
return "MyFlushBlockPolicyFactory";
|
||||
}
|
||||
|
||||
virtual FlushBlockPolicy* NewFlushBlockPolicy(
|
||||
const BlockBasedTableOptions& /*table_options*/,
|
||||
const BlockBuilder& data_block_builder) const override {
|
||||
return new MyFlushBlockPolicy(data_block_builder);
|
||||
}
|
||||
};
|
||||
|
||||
class MyFlushBlockPolicy : public FlushBlockPolicy {
|
||||
public:
|
||||
explicit MyFlushBlockPolicy(const BlockBuilder& data_block_builder)
|
||||
: num_keys_(0), data_block_builder_(data_block_builder) {}
|
||||
|
||||
bool Update(const Slice& /*key*/, const Slice& /*value*/) override {
|
||||
if (data_block_builder_.empty()) {
|
||||
// First key in this block
|
||||
num_keys_ = 1;
|
||||
return false;
|
||||
}
|
||||
// Flush every 10 keys
|
||||
if (num_keys_ == 10) {
|
||||
num_keys_ = 1;
|
||||
return true;
|
||||
}
|
||||
num_keys_++;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
int num_keys_;
|
||||
const BlockBuilder& data_block_builder_;
|
||||
};
|
||||
|
||||
class MyBlockCache : public CacheWrapper {
|
||||
public:
|
||||
explicit MyBlockCache(std::shared_ptr<Cache> target)
|
||||
@@ -4059,7 +4277,7 @@ class DeadlineRandomAccessFile : public FSRandomAccessFileOwnerWrapper {
|
||||
const IOOptions& options, IODebugContext* dbg) override;
|
||||
|
||||
IOStatus ReadAsync(FSReadRequest& req, const IOOptions& opts,
|
||||
std::function<void(const FSReadRequest&, void*)> cb,
|
||||
std::function<void(FSReadRequest&, void*)> cb,
|
||||
void* cb_arg, void** io_handle, IOHandleDeleter* del_fn,
|
||||
IODebugContext* dbg) override;
|
||||
|
||||
@@ -4205,7 +4423,7 @@ IOStatus DeadlineRandomAccessFile::Read(uint64_t offset, size_t len,
|
||||
|
||||
IOStatus DeadlineRandomAccessFile::ReadAsync(
|
||||
FSReadRequest& req, const IOOptions& opts,
|
||||
std::function<void(const FSReadRequest&, void*)> cb, void* cb_arg,
|
||||
std::function<void(FSReadRequest&, void*)> cb, void* cb_arg,
|
||||
void** io_handle, IOHandleDeleter* del_fn, IODebugContext* dbg) {
|
||||
const std::chrono::microseconds deadline = fs_.GetDeadline();
|
||||
const std::chrono::microseconds io_timeout = fs_.GetIOTimeout();
|
||||
@@ -4286,68 +4504,35 @@ TEST_P(DBBasicTestMultiGetDeadline, MultiGetDeadlineExceeded) {
|
||||
SetTimeElapseOnlySleepOnReopen(&options);
|
||||
ReopenWithColumnFamilies(GetCFNames(), options);
|
||||
|
||||
// Test the non-batched version of MultiGet with multiple column
|
||||
// families
|
||||
// Test batched MultiGet with an IO delay in the first data block read.
|
||||
// Both keys in the first CF should succeed as they're in the same data
|
||||
// block and would form one batch, and we check for deadline between
|
||||
// batches.
|
||||
std::vector<std::string> key_str;
|
||||
size_t i;
|
||||
for (i = 0; i < 5; ++i) {
|
||||
for (i = 0; i < 10; ++i) {
|
||||
key_str.emplace_back(Key(static_cast<int>(i)));
|
||||
}
|
||||
std::vector<ColumnFamilyHandle*> cfs(key_str.size());
|
||||
;
|
||||
std::vector<Slice> keys(key_str.size());
|
||||
std::vector<std::string> values(key_str.size());
|
||||
std::vector<PinnableSlice> pin_values(keys.size());
|
||||
|
||||
for (i = 0; i < key_str.size(); ++i) {
|
||||
cfs[i] = handles_[i];
|
||||
// 2 keys per CF
|
||||
cfs[i] = handles_[i / 2];
|
||||
keys[i] = Slice(key_str[i].data(), key_str[i].size());
|
||||
}
|
||||
|
||||
ReadOptions ro;
|
||||
ro.deadline = std::chrono::microseconds{env->NowMicros() + 10000};
|
||||
ro.async_io = GetParam();
|
||||
// Delay the first IO
|
||||
fs->SetDelayTrigger(ro.deadline, ro.io_timeout, 0);
|
||||
|
||||
std::vector<Status> statuses = dbfull()->MultiGet(ro, cfs, keys, &values);
|
||||
// The first key is successful because we check after the lookup, but
|
||||
// subsequent keys fail due to deadline exceeded
|
||||
CheckStatus(statuses, 1);
|
||||
|
||||
// Clear the cache
|
||||
cache->SetCapacity(0);
|
||||
cache->SetCapacity(1048576);
|
||||
// Test non-batched Multiget with multiple column families and
|
||||
// introducing an IO delay in one of the middle CFs
|
||||
key_str.clear();
|
||||
for (i = 0; i < 10; ++i) {
|
||||
key_str.emplace_back(Key(static_cast<int>(i)));
|
||||
}
|
||||
cfs.resize(key_str.size());
|
||||
keys.resize(key_str.size());
|
||||
values.resize(key_str.size());
|
||||
for (i = 0; i < key_str.size(); ++i) {
|
||||
// 2 keys per CF
|
||||
cfs[i] = handles_[i / 2];
|
||||
keys[i] = Slice(key_str[i].data(), key_str[i].size());
|
||||
}
|
||||
ro.deadline = std::chrono::microseconds{env->NowMicros() + 10000};
|
||||
fs->SetDelayTrigger(ro.deadline, ro.io_timeout, 1);
|
||||
statuses = dbfull()->MultiGet(ro, cfs, keys, &values);
|
||||
CheckStatus(statuses, 3);
|
||||
|
||||
// Test batched MultiGet with an IO delay in the first data block read.
|
||||
// Both keys in the first CF should succeed as they're in the same data
|
||||
// block and would form one batch, and we check for deadline between
|
||||
// batches.
|
||||
std::vector<PinnableSlice> pin_values(keys.size());
|
||||
cache->SetCapacity(0);
|
||||
cache->SetCapacity(1048576);
|
||||
statuses.clear();
|
||||
statuses.resize(keys.size());
|
||||
ro.deadline = std::chrono::microseconds{env->NowMicros() + 10000};
|
||||
fs->SetDelayTrigger(ro.deadline, ro.io_timeout, 0);
|
||||
std::vector<Status> statuses(key_str.size());
|
||||
dbfull()->MultiGet(ro, keys.size(), cfs.data(), keys.data(),
|
||||
pin_values.data(), statuses.data());
|
||||
// The first key is successful because we check after the lookup, but
|
||||
// subsequent keys fail due to deadline exceeded
|
||||
CheckStatus(statuses, 2);
|
||||
|
||||
// Similar to the previous one, but an IO delay in the third CF data block
|
||||
@@ -4425,7 +4610,7 @@ TEST_F(DBBasicTest, ManifestWriteFailure) {
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"VersionSet::ProcessManifestWrites:AfterSyncManifest", [&](void* arg) {
|
||||
ASSERT_NE(nullptr, arg);
|
||||
auto* s = reinterpret_cast<Status*>(arg);
|
||||
auto* s = static_cast<Status*>(arg);
|
||||
ASSERT_OK(*s);
|
||||
// Manually overwrite return status
|
||||
*s = Status::IOError();
|
||||
@@ -4480,7 +4665,7 @@ TEST_F(DBBasicTest, FailOpenIfLoggerCreationFail) {
|
||||
SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"rocksdb::CreateLoggerFromOptions:AfterGetPath", [&](void* arg) {
|
||||
auto* s = reinterpret_cast<Status*>(arg);
|
||||
auto* s = static_cast<Status*>(arg);
|
||||
assert(s);
|
||||
*s = Status::IOError("Injected");
|
||||
});
|
||||
|
||||
@@ -1373,7 +1373,7 @@ class StableCacheKeyTestFS : public FaultInjectionTestFS {
|
||||
SetFailGetUniqueId(true);
|
||||
}
|
||||
|
||||
virtual ~StableCacheKeyTestFS() override {}
|
||||
~StableCacheKeyTestFS() override {}
|
||||
|
||||
IOStatus LinkFile(const std::string&, const std::string&, const IOOptions&,
|
||||
IODebugContext*) override {
|
||||
@@ -1424,7 +1424,7 @@ TEST_P(DBBlockCacheKeyTest, StableCacheKeys) {
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"BlockBasedTableBuilder::BlockBasedTableBuilder:PreSetupBaseCacheKey",
|
||||
[&](void* arg) {
|
||||
TableProperties* props = reinterpret_cast<TableProperties*>(arg);
|
||||
TableProperties* props = static_cast<TableProperties*>(arg);
|
||||
props->orig_file_number = 0;
|
||||
});
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "port/stack_trace.h"
|
||||
#include "rocksdb/advanced_options.h"
|
||||
#include "rocksdb/convenience.h"
|
||||
#include "rocksdb/experimental.h"
|
||||
#include "rocksdb/filter_policy.h"
|
||||
#include "rocksdb/perf_context.h"
|
||||
#include "rocksdb/statistics.h"
|
||||
@@ -3562,6 +3563,277 @@ TEST_F(DBBloomFilterTest, WeirdPrefixExtractorWithFilter3) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBBloomFilterTest, SstQueryFilter) {
|
||||
using experimental::KeySegmentsExtractor;
|
||||
using experimental::MakeSharedBytewiseMinMaxSQFC;
|
||||
using experimental::SelectKeySegment;
|
||||
using experimental::SstQueryFilterConfigs;
|
||||
using experimental::SstQueryFilterConfigsManager;
|
||||
using KeyCategorySet = KeySegmentsExtractor::KeyCategorySet;
|
||||
|
||||
struct MySegmentExtractor : public KeySegmentsExtractor {
|
||||
char min_first_char;
|
||||
char max_first_char;
|
||||
char delim_char;
|
||||
MySegmentExtractor(char _min_first_char, char _max_first_char,
|
||||
char _delim_char)
|
||||
: min_first_char(_min_first_char),
|
||||
max_first_char(_max_first_char),
|
||||
delim_char(_delim_char) {}
|
||||
|
||||
const char* Name() const override { return "MySegmentExtractor"; }
|
||||
|
||||
std::string GetId() const override {
|
||||
return std::string("MySegmentExtractor+") + min_first_char +
|
||||
max_first_char + delim_char;
|
||||
}
|
||||
|
||||
void Extract(const Slice& key_or_bound, KeyKind /*kind*/,
|
||||
Result* result) const override {
|
||||
size_t len = key_or_bound.size();
|
||||
if (len == 0) {
|
||||
result->category = KeySegmentsExtractor::kReservedLowCategory;
|
||||
} else if (static_cast<unsigned char>(key_or_bound[0]) <
|
||||
static_cast<unsigned char>(min_first_char)) {
|
||||
result->category = KeySegmentsExtractor::kReservedLowCategory;
|
||||
} else if (static_cast<unsigned char>(key_or_bound[0]) >
|
||||
static_cast<unsigned char>(max_first_char)) {
|
||||
result->category = KeySegmentsExtractor::kReservedHighCategory;
|
||||
}
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
if (key_or_bound[i] == delim_char || i + 1 == key_or_bound.size()) {
|
||||
result->segment_ends.push_back(i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Use '_' as delimiter, but different spans for default category
|
||||
auto extractor_to_c = std::make_shared<MySegmentExtractor>('a', 'c', '_');
|
||||
auto extractor_to_z = std::make_shared<MySegmentExtractor>('a', 'z', '_');
|
||||
auto extractor_alt = std::make_shared<MySegmentExtractor>('0', '9', '_');
|
||||
|
||||
// Filter on 2nd field, only for default category
|
||||
auto filter1_def = MakeSharedBytewiseMinMaxSQFC(
|
||||
experimental::SelectKeySegment(1),
|
||||
KeyCategorySet{KeySegmentsExtractor::kDefaultCategory});
|
||||
|
||||
// Also filter on 3rd field regardless of category
|
||||
auto filter2_all =
|
||||
MakeSharedBytewiseMinMaxSQFC(experimental::SelectKeySegment(2));
|
||||
|
||||
SstQueryFilterConfigs configs1 = {{filter1_def, filter2_all}, extractor_to_c};
|
||||
SstQueryFilterConfigs configs2 = {{filter1_def, filter2_all}, extractor_to_z};
|
||||
SstQueryFilterConfigs configs3 = {{filter2_all}, extractor_alt};
|
||||
|
||||
SstQueryFilterConfigsManager::Data data = {
|
||||
{42, {{"foo", configs1}}}, {43, {{"foo", configs2}, {"bar", configs3}}}};
|
||||
|
||||
std::shared_ptr<SstQueryFilterConfigsManager> configs_manager;
|
||||
ASSERT_OK(SstQueryFilterConfigsManager::MakeShared(data, &configs_manager));
|
||||
|
||||
// Test manager behaviors
|
||||
auto MakeFactory = [configs_manager](
|
||||
const std::string& configs_name,
|
||||
SstQueryFilterConfigsManager::FilteringVersion ver)
|
||||
-> std::shared_ptr<SstQueryFilterConfigsManager::Factory> {
|
||||
std::shared_ptr<SstQueryFilterConfigsManager::Factory> factory;
|
||||
Status s = configs_manager->MakeSharedFactory(configs_name, ver, &factory);
|
||||
assert(s.ok());
|
||||
return factory;
|
||||
};
|
||||
std::shared_ptr<SstQueryFilterConfigsManager::Factory> factory;
|
||||
|
||||
// Version 0 is always OK, returning empty/not found configs
|
||||
ASSERT_TRUE(MakeFactory("blah", 0)->GetConfigs().IsEmptyNotFound());
|
||||
ASSERT_TRUE(MakeFactory("foo", 0)->GetConfigs().IsEmptyNotFound());
|
||||
ASSERT_TRUE(MakeFactory("bar", 0)->GetConfigs().IsEmptyNotFound());
|
||||
|
||||
// We can't be sure about the proper configuration for versions outside the
|
||||
// known range (and reserved version 0).
|
||||
ASSERT_TRUE(configs_manager->MakeSharedFactory("foo", 1, &factory)
|
||||
.IsInvalidArgument());
|
||||
ASSERT_TRUE(configs_manager->MakeSharedFactory("foo", 41, &factory)
|
||||
.IsInvalidArgument());
|
||||
ASSERT_TRUE(configs_manager->MakeSharedFactory("foo", 44, &factory)
|
||||
.IsInvalidArgument());
|
||||
ASSERT_TRUE(configs_manager->MakeSharedFactory("foo", 500, &factory)
|
||||
.IsInvalidArgument());
|
||||
|
||||
ASSERT_TRUE(MakeFactory("blah", 42)->GetConfigs().IsEmptyNotFound());
|
||||
ASSERT_TRUE(MakeFactory("blah", 43)->GetConfigs().IsEmptyNotFound());
|
||||
ASSERT_FALSE(MakeFactory("foo", 42)->GetConfigs().IsEmptyNotFound());
|
||||
ASSERT_FALSE(MakeFactory("foo", 43)->GetConfigs().IsEmptyNotFound());
|
||||
ASSERT_TRUE(MakeFactory("bar", 42)->GetConfigs().IsEmptyNotFound());
|
||||
ASSERT_FALSE(MakeFactory("bar", 43)->GetConfigs().IsEmptyNotFound());
|
||||
|
||||
ASSERT_OK(configs_manager->MakeSharedFactory("foo", 42, &factory));
|
||||
ASSERT_EQ(factory->GetConfigsName(), "foo");
|
||||
ASSERT_EQ(factory->GetConfigs().IsEmptyNotFound(), false);
|
||||
|
||||
Options options = CurrentOptions();
|
||||
options.statistics = CreateDBStatistics();
|
||||
options.table_properties_collector_factories.push_back(factory);
|
||||
|
||||
DestroyAndReopen(options);
|
||||
|
||||
// For lower level file
|
||||
ASSERT_OK(Put(" ", "val0"));
|
||||
ASSERT_OK(Put(" _345_678", "val0"));
|
||||
ASSERT_OK(Put("aaa", "val0"));
|
||||
ASSERT_OK(Put("abc_123", "val1"));
|
||||
ASSERT_OK(Put("abc_13", "val2"));
|
||||
ASSERT_OK(Put("abc_156_987", "val3"));
|
||||
ASSERT_OK(Put("bcd_1722", "val4"));
|
||||
ASSERT_OK(Put("xyz_145", "val5"));
|
||||
ASSERT_OK(Put("xyz_167", "val6"));
|
||||
ASSERT_OK(Put("xyz_178", "val7"));
|
||||
ASSERT_OK(Put("zzz", "val0"));
|
||||
ASSERT_OK(Put("~~~", "val0"));
|
||||
ASSERT_OK(Put("~~~_456_789", "val0"));
|
||||
|
||||
ASSERT_OK(Flush());
|
||||
MoveFilesToLevel(1);
|
||||
|
||||
ASSERT_EQ(factory->GetFilteringVersion(), 42U);
|
||||
ASSERT_NOK(factory->SetFilteringVersion(41));
|
||||
ASSERT_NOK(factory->SetFilteringVersion(44));
|
||||
ASSERT_EQ(factory->GetFilteringVersion(), 42U);
|
||||
ASSERT_OK(factory->SetFilteringVersion(43));
|
||||
ASSERT_EQ(factory->GetFilteringVersion(), 43U);
|
||||
|
||||
// For higher level file
|
||||
ASSERT_OK(Put(" ", "val0"));
|
||||
ASSERT_OK(Put(" _345_680", "val0"));
|
||||
ASSERT_OK(Put("aaa", "val9"));
|
||||
ASSERT_OK(Put("abc_234", "val1"));
|
||||
ASSERT_OK(Put("abc_245_567", "val2"));
|
||||
ASSERT_OK(Put("abc_25", "val3"));
|
||||
ASSERT_OK(Put("xyz_180", "val4"));
|
||||
ASSERT_OK(Put("xyz_191", "val4"));
|
||||
ASSERT_OK(Put("xyz_260", "val4"));
|
||||
ASSERT_OK(Put("zzz", "val9"));
|
||||
ASSERT_OK(Put("~~~", "val0"));
|
||||
ASSERT_OK(Put("~~~_456_790", "val0"));
|
||||
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
using Keys = std::vector<std::string>;
|
||||
auto RangeQueryKeys =
|
||||
[factory, db = db_](
|
||||
std::string lb, std::string ub,
|
||||
std::shared_ptr<SstQueryFilterConfigsManager::Factory> alt_factory =
|
||||
nullptr) {
|
||||
Slice lb_slice = lb;
|
||||
Slice ub_slice = ub;
|
||||
|
||||
ReadOptions ro;
|
||||
ro.iterate_lower_bound = &lb_slice;
|
||||
ro.iterate_upper_bound = &ub_slice;
|
||||
ro.table_filter = (alt_factory ? alt_factory : factory)
|
||||
->GetTableFilterForRangeQuery(lb_slice, ub_slice);
|
||||
auto it = db->NewIterator(ro);
|
||||
Keys ret;
|
||||
for (it->Seek(lb_slice); it->Valid(); it->Next()) {
|
||||
ret.push_back(it->key().ToString());
|
||||
}
|
||||
EXPECT_OK(it->status());
|
||||
delete it;
|
||||
return ret;
|
||||
};
|
||||
|
||||
// Control 1: range is not filtered but min/max filter is checked
|
||||
// because of common prefix leading up to 2nd segment
|
||||
// TODO/future: statistics for when filter is checked vs. not applicable
|
||||
EXPECT_EQ(RangeQueryKeys("abc_150", "abc_249"),
|
||||
Keys({"abc_156_987", "abc_234", "abc_245_567"}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 2);
|
||||
|
||||
// Test 1: range is filtered to just lowest level, fully containing the
|
||||
// segments in that category
|
||||
EXPECT_EQ(RangeQueryKeys("abc_100", "abc_179"),
|
||||
Keys({"abc_123", "abc_13", "abc_156_987"}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 1);
|
||||
|
||||
// Test 2: range is filtered to just lowest level, partial overlap
|
||||
EXPECT_EQ(RangeQueryKeys("abc_1500_x_y", "abc_16QQ"), Keys({"abc_156_987"}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 1);
|
||||
|
||||
// Test 3: range is filtered to just highest level, fully containing the
|
||||
// segments in that category but would be overlapping the range for the other
|
||||
// file if the filter included all categories
|
||||
EXPECT_EQ(RangeQueryKeys("abc_200", "abc_300"),
|
||||
Keys({"abc_234", "abc_245_567", "abc_25"}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 1);
|
||||
|
||||
// Test 4: range is filtered to just highest level, partial overlap (etc.)
|
||||
EXPECT_EQ(RangeQueryKeys("abc_200", "abc_249"),
|
||||
Keys({"abc_234", "abc_245_567"}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 1);
|
||||
|
||||
// Test 5: range is filtered from both levels, because of category scope
|
||||
EXPECT_EQ(RangeQueryKeys("abc_300", "abc_400"), Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 0);
|
||||
|
||||
// Control 2: range is not filtered because association between 1st and
|
||||
// 2nd segment is not represented
|
||||
EXPECT_EQ(RangeQueryKeys("abc_170", "abc_190"), Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 2);
|
||||
|
||||
// Control 3: range is not filtered because there's no (bloom) filter on
|
||||
// 1st segment (like prefix filtering)
|
||||
EXPECT_EQ(RangeQueryKeys("baa_170", "baa_190"), Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 2);
|
||||
|
||||
// Control 4: range is not filtered because difference in segments leading
|
||||
// up to 2nd segment
|
||||
EXPECT_EQ(RangeQueryKeys("abc_500", "abd_501"), Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 2);
|
||||
|
||||
// TODO: exclusive upper bound tests
|
||||
|
||||
// ======= Testing 3rd segment (cross-category filter) =======
|
||||
// Control 5: not filtered because of segment range overlap
|
||||
EXPECT_EQ(RangeQueryKeys(" z__700", " z__750"), Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 2);
|
||||
|
||||
// Test 6: filtered on both levels
|
||||
EXPECT_EQ(RangeQueryKeys(" z__100", " z__300"), Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 0);
|
||||
|
||||
// Control 6: finding something, with 2nd segment filter helping
|
||||
EXPECT_EQ(RangeQueryKeys("abc_156_9", "abc_156_99"), Keys({"abc_156_987"}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 1);
|
||||
|
||||
EXPECT_EQ(RangeQueryKeys("abc_245_56", "abc_245_57"), Keys({"abc_245_567"}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 1);
|
||||
|
||||
// Test 6: filtered on both levels, for different segments
|
||||
EXPECT_EQ(RangeQueryKeys("abc_245_900", "abc_245_999"), Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 0);
|
||||
|
||||
// ======= Testing extractor read portability =======
|
||||
EXPECT_EQ(RangeQueryKeys("abc_300", "abc_400"), Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 0);
|
||||
|
||||
// Only modifies how filters are written
|
||||
ASSERT_OK(factory->SetFilteringVersion(0));
|
||||
ASSERT_EQ(factory->GetFilteringVersion(), 0U);
|
||||
ASSERT_EQ(factory->GetConfigs().IsEmptyNotFound(), true);
|
||||
|
||||
EXPECT_EQ(RangeQueryKeys("abc_300", "abc_400"), Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 0);
|
||||
|
||||
// Even a different config name with different extractor can read
|
||||
EXPECT_EQ(RangeQueryKeys("abc_300", "abc_400", MakeFactory("bar", 43)),
|
||||
Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 0);
|
||||
|
||||
// Or a "not found" config name
|
||||
EXPECT_EQ(RangeQueryKeys("abc_300", "abc_400", MakeFactory("blah", 43)),
|
||||
Keys({}));
|
||||
EXPECT_EQ(TestGetAndResetTickerCount(options, NON_LAST_LEVEL_SEEK_DATA), 0);
|
||||
}
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
||||
|
||||
+133
-70
@@ -76,7 +76,7 @@ class CompactionStatsCollector : public EventListener {
|
||||
class DBCompactionTest : public DBTestBase {
|
||||
public:
|
||||
DBCompactionTest()
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/true) {}
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/false) {}
|
||||
|
||||
protected:
|
||||
/*
|
||||
@@ -121,7 +121,7 @@ class DBCompactionTestWithParam
|
||||
public testing::WithParamInterface<std::tuple<uint32_t, bool>> {
|
||||
public:
|
||||
DBCompactionTestWithParam()
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/true) {
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/false) {
|
||||
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=*/true) {
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/false) {
|
||||
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=*/true) {
|
||||
: DBTestBase("db_compaction_test", /*env_do_fsync=*/false) {
|
||||
abort_on_pause_ = std::get<0>(GetParam());
|
||||
flush_ = std::get<1>(GetParam());
|
||||
close_db_ = std::get<2>(GetParam());
|
||||
@@ -505,7 +505,7 @@ TEST_F(DBCompactionTest, TestTableReaderForCompaction) {
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"TableCache::FindTable:0", [&](void* arg) {
|
||||
assert(arg != nullptr);
|
||||
bool no_io = *(reinterpret_cast<bool*>(arg));
|
||||
bool no_io = *(static_cast<bool*>(arg));
|
||||
if (!no_io) {
|
||||
// filter out cases for table properties queries.
|
||||
num_table_cache_lookup++;
|
||||
@@ -681,7 +681,7 @@ TEST_F(DBCompactionTest, CompactRangeBottomPri) {
|
||||
int bottom_pri_count = 0;
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"ThreadPoolImpl::Impl::BGThread:BeforeRun", [&](void* arg) {
|
||||
Env::Priority* pri = reinterpret_cast<Env::Priority*>(arg);
|
||||
Env::Priority* pri = static_cast<Env::Priority*>(arg);
|
||||
// First time is low pri pool in the test case.
|
||||
if (low_pri_count == 0 && bottom_pri_count == 0) {
|
||||
ASSERT_EQ(Env::Priority::LOW, *pri);
|
||||
@@ -845,6 +845,20 @@ 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);
|
||||
@@ -855,9 +869,6 @@ 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++) {
|
||||
@@ -1859,13 +1870,60 @@ TEST_F(DBCompactionTest, ManualCompactionWithUnorderedWrite) {
|
||||
ASSERT_EQ(Get("foo"), "v2");
|
||||
}
|
||||
|
||||
TEST_F(DBCompactionTest, DeleteFileRange) {
|
||||
// Test params:
|
||||
// 1) whether to enable user-defined timestamps.
|
||||
class DBDeleteFileRangeTest : public DBTestBase,
|
||||
public testing::WithParamInterface<bool> {
|
||||
public:
|
||||
DBDeleteFileRangeTest()
|
||||
: DBTestBase("db_delete_file_range_test", /*env_do_fsync=*/true) {}
|
||||
|
||||
void SetUp() override { enable_udt_ = GetParam(); }
|
||||
|
||||
protected:
|
||||
void PutKeyValue(const Slice& key, const Slice& value) {
|
||||
if (enable_udt_) {
|
||||
EXPECT_OK(db_->Put(WriteOptions(), key, min_ts_, value));
|
||||
} else {
|
||||
EXPECT_OK(Put(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetValue(const std::string& key) {
|
||||
ReadOptions roptions;
|
||||
std::string result;
|
||||
if (enable_udt_) {
|
||||
roptions.timestamp = &min_ts_;
|
||||
}
|
||||
Status s = db_->Get(roptions, key, &result);
|
||||
EXPECT_TRUE(s.ok());
|
||||
return result;
|
||||
}
|
||||
|
||||
Status MaybeGetValue(const std::string& key, std::string* result) {
|
||||
ReadOptions roptions;
|
||||
if (enable_udt_) {
|
||||
roptions.timestamp = &min_ts_;
|
||||
}
|
||||
Status s = db_->Get(roptions, key, result);
|
||||
EXPECT_TRUE(s.IsNotFound() || s.ok());
|
||||
return s;
|
||||
}
|
||||
|
||||
bool enable_udt_ = false;
|
||||
Slice min_ts_ = MinU64Ts();
|
||||
};
|
||||
|
||||
TEST_P(DBDeleteFileRangeTest, DeleteFileRange) {
|
||||
Options options = CurrentOptions();
|
||||
options.write_buffer_size = 10 * 1024 * 1024;
|
||||
options.max_bytes_for_level_multiplier = 2;
|
||||
options.num_levels = 4;
|
||||
options.level0_file_num_compaction_trigger = 3;
|
||||
options.max_background_compactions = 3;
|
||||
if (enable_udt_) {
|
||||
options.comparator = test::BytewiseComparatorWithU64TsWrapper();
|
||||
}
|
||||
|
||||
DestroyAndReopen(options);
|
||||
int32_t value_size = 10 * 1024; // 10 KB
|
||||
@@ -1877,14 +1935,14 @@ TEST_F(DBCompactionTest, DeleteFileRange) {
|
||||
// file 1 [0 => 100]
|
||||
for (int32_t i = 0; i < 100; i++) {
|
||||
values[i] = rnd.RandomString(value_size);
|
||||
ASSERT_OK(Put(Key(i), values[i]));
|
||||
PutKeyValue(Key(i), values[i]);
|
||||
}
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
// file 2 [100 => 300]
|
||||
for (int32_t i = 100; i < 300; i++) {
|
||||
values[i] = rnd.RandomString(value_size);
|
||||
ASSERT_OK(Put(Key(i), values[i]));
|
||||
PutKeyValue(Key(i), values[i]);
|
||||
}
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
@@ -1900,7 +1958,7 @@ TEST_F(DBCompactionTest, DeleteFileRange) {
|
||||
// file 3 [ 0 => 200]
|
||||
for (int32_t i = 0; i < 200; i++) {
|
||||
values[i] = rnd.RandomString(value_size);
|
||||
ASSERT_OK(Put(Key(i), values[i]));
|
||||
PutKeyValue(Key(i), values[i]);
|
||||
}
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
@@ -1912,7 +1970,7 @@ TEST_F(DBCompactionTest, DeleteFileRange) {
|
||||
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||
}
|
||||
values[j] = rnd.RandomString(value_size);
|
||||
ASSERT_OK(Put(Key(j), values[j]));
|
||||
PutKeyValue(Key(j), values[j]);
|
||||
}
|
||||
}
|
||||
ASSERT_OK(Flush());
|
||||
@@ -1937,11 +1995,10 @@ TEST_F(DBCompactionTest, DeleteFileRange) {
|
||||
int32_t deleted_count = 0;
|
||||
for (int32_t i = 0; i < 4300; i++) {
|
||||
if (i < 1000 || i > 2000) {
|
||||
ASSERT_EQ(Get(Key(i)), values[i]);
|
||||
ASSERT_EQ(GetValue(Key(i)), values[i]);
|
||||
} else {
|
||||
ReadOptions roptions;
|
||||
std::string result;
|
||||
Status s = db_->Get(roptions, Key(i), &result);
|
||||
Status s = MaybeGetValue(Key(i), &result);
|
||||
ASSERT_TRUE(s.IsNotFound() || s.ok());
|
||||
if (s.IsNotFound()) {
|
||||
deleted_count++;
|
||||
@@ -1971,7 +2028,7 @@ TEST_F(DBCompactionTest, DeleteFileRange) {
|
||||
for (int32_t i = 0; i < 4300; i++) {
|
||||
ReadOptions roptions;
|
||||
std::string result;
|
||||
ASSERT_TRUE(db_->Get(roptions, Key(i), &result).IsNotFound());
|
||||
ASSERT_TRUE(MaybeGetValue(Key(i), &result).IsNotFound());
|
||||
deleted_count2++;
|
||||
}
|
||||
ASSERT_GT(deleted_count2, deleted_count);
|
||||
@@ -1979,13 +2036,16 @@ TEST_F(DBCompactionTest, DeleteFileRange) {
|
||||
ASSERT_GT(old_num_files, new_num_files);
|
||||
}
|
||||
|
||||
TEST_F(DBCompactionTest, DeleteFilesInRanges) {
|
||||
TEST_P(DBDeleteFileRangeTest, DeleteFilesInRanges) {
|
||||
Options options = CurrentOptions();
|
||||
options.write_buffer_size = 10 * 1024 * 1024;
|
||||
options.max_bytes_for_level_multiplier = 2;
|
||||
options.num_levels = 4;
|
||||
options.max_background_compactions = 3;
|
||||
options.disable_auto_compactions = true;
|
||||
if (enable_udt_) {
|
||||
options.comparator = test::BytewiseComparatorWithU64TsWrapper();
|
||||
}
|
||||
|
||||
DestroyAndReopen(options);
|
||||
int32_t value_size = 10 * 1024; // 10 KB
|
||||
@@ -1998,7 +2058,7 @@ TEST_F(DBCompactionTest, DeleteFilesInRanges) {
|
||||
for (auto j = 0; j < 100; j++) {
|
||||
auto k = i * 100 + j;
|
||||
values[k] = rnd.RandomString(value_size);
|
||||
ASSERT_OK(Put(Key(k), values[k]));
|
||||
PutKeyValue(Key(k), values[k]);
|
||||
}
|
||||
ASSERT_OK(Flush());
|
||||
}
|
||||
@@ -2013,7 +2073,7 @@ TEST_F(DBCompactionTest, DeleteFilesInRanges) {
|
||||
for (auto i = 0; i < 10; i += 2) {
|
||||
for (auto j = 0; j < 100; j++) {
|
||||
auto k = i * 100 + j;
|
||||
ASSERT_OK(Put(Key(k), values[k]));
|
||||
PutKeyValue(Key(k), values[k]);
|
||||
}
|
||||
ASSERT_OK(Flush());
|
||||
}
|
||||
@@ -2039,13 +2099,12 @@ TEST_F(DBCompactionTest, DeleteFilesInRanges) {
|
||||
|
||||
// Keys [0, 300) should not exist.
|
||||
for (auto i = 0; i < 300; i++) {
|
||||
ReadOptions ropts;
|
||||
std::string result;
|
||||
auto s = db_->Get(ropts, Key(i), &result);
|
||||
auto s = MaybeGetValue(Key(i), &result);
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
}
|
||||
for (auto i = 300; i < 1000; i++) {
|
||||
ASSERT_EQ(Get(Key(i)), values[i]);
|
||||
ASSERT_EQ(GetValue(Key(i)), values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2067,16 +2126,15 @@ TEST_F(DBCompactionTest, DeleteFilesInRanges) {
|
||||
|
||||
// Keys [600, 900) should not exist.
|
||||
for (auto i = 600; i < 900; i++) {
|
||||
ReadOptions ropts;
|
||||
std::string result;
|
||||
auto s = db_->Get(ropts, Key(i), &result);
|
||||
auto s = MaybeGetValue(Key(i), &result);
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
}
|
||||
for (auto i = 300; i < 600; i++) {
|
||||
ASSERT_EQ(Get(Key(i)), values[i]);
|
||||
ASSERT_EQ(GetValue(Key(i)), values[i]);
|
||||
}
|
||||
for (auto i = 900; i < 1000; i++) {
|
||||
ASSERT_EQ(Get(Key(i)), values[i]);
|
||||
ASSERT_EQ(GetValue(Key(i)), values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2087,15 +2145,14 @@ TEST_F(DBCompactionTest, DeleteFilesInRanges) {
|
||||
ASSERT_EQ("", FilesPerLevel(0));
|
||||
|
||||
for (auto i = 0; i < 1000; i++) {
|
||||
ReadOptions ropts;
|
||||
std::string result;
|
||||
auto s = db_->Get(ropts, Key(i), &result);
|
||||
auto s = MaybeGetValue(Key(i), &result);
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBCompactionTest, DeleteFileRangeFileEndpointsOverlapBug) {
|
||||
TEST_P(DBDeleteFileRangeTest, DeleteFileRangeFileEndpointsOverlapBug) {
|
||||
// regression test for #2833: groups of files whose user-keys overlap at the
|
||||
// endpoints could be split by `DeleteFilesInRange`. This caused old data to
|
||||
// reappear, either because a new version of the key was removed, or a range
|
||||
@@ -2107,6 +2164,9 @@ TEST_F(DBCompactionTest, DeleteFileRangeFileEndpointsOverlapBug) {
|
||||
Options options = CurrentOptions();
|
||||
options.level0_file_num_compaction_trigger = kNumL0Files;
|
||||
options.target_file_size_base = 1 << 10; // 1KB
|
||||
if (enable_udt_) {
|
||||
options.comparator = test::BytewiseComparatorWithU64TsWrapper();
|
||||
}
|
||||
DestroyAndReopen(options);
|
||||
|
||||
// The snapshot prevents key 1 from having its old version dropped. The low
|
||||
@@ -2130,8 +2190,8 @@ TEST_F(DBCompactionTest, DeleteFileRangeFileEndpointsOverlapBug) {
|
||||
std::string vals[kNumL0Files];
|
||||
for (int i = 0; i < kNumL0Files; ++i) {
|
||||
vals[i] = rnd.RandomString(kValSize);
|
||||
ASSERT_OK(Put(Key(i), vals[i]));
|
||||
ASSERT_OK(Put(Key(i + 1), vals[i]));
|
||||
PutKeyValue(Key(i), vals[i]);
|
||||
PutKeyValue(Key(i + 1), vals[i]);
|
||||
ASSERT_OK(Flush());
|
||||
if (i == 0) {
|
||||
snapshot = db_->GetSnapshot();
|
||||
@@ -2144,11 +2204,14 @@ TEST_F(DBCompactionTest, DeleteFileRangeFileEndpointsOverlapBug) {
|
||||
std::string begin_str = Key(0), end_str = Key(1);
|
||||
Slice begin = begin_str, end = end_str;
|
||||
ASSERT_OK(DeleteFilesInRange(db_, db_->DefaultColumnFamily(), &begin, &end));
|
||||
ASSERT_EQ(vals[1], Get(Key(1)));
|
||||
ASSERT_EQ(vals[1], GetValue(Key(1)));
|
||||
|
||||
db_->ReleaseSnapshot(snapshot);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(DBDeleteFileRangeTest, DBDeleteFileRangeTest,
|
||||
::testing::Bool());
|
||||
|
||||
TEST_P(DBCompactionTestWithParam, TrivialMoveToLastLevelWithFiles) {
|
||||
int32_t trivial_move = 0;
|
||||
int32_t non_trivial_move = 0;
|
||||
@@ -4181,7 +4244,7 @@ TEST_F(DBCompactionTest, CompactBottomLevelFilesWithDeletions) {
|
||||
ASSERT_NE(kMaxSequenceNumber, dbfull()->bottommost_files_mark_threshold_);
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
ASSERT_TRUE(compaction->compaction_reason() ==
|
||||
CompactionReason::kBottommostFiles);
|
||||
});
|
||||
@@ -4237,7 +4300,7 @@ TEST_F(DBCompactionTest, DelayCompactBottomLevelFilesWithDeletions) {
|
||||
std::atomic_int compaction_count = 0;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
ASSERT_TRUE(compaction->compaction_reason() ==
|
||||
CompactionReason::kBottommostFiles);
|
||||
compaction_count++;
|
||||
@@ -4368,7 +4431,7 @@ TEST_F(DBCompactionTest, RoundRobinTtlCompactionNormal) {
|
||||
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
auto compaction_reason = compaction->compaction_reason();
|
||||
if (compaction_reason == CompactionReason::kTtl) {
|
||||
ttl_compactions++;
|
||||
@@ -4518,7 +4581,7 @@ TEST_F(DBCompactionTest, RoundRobinTtlCompactionUnsortedTime) {
|
||||
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
auto compaction_reason = compaction->compaction_reason();
|
||||
if (compaction_reason == CompactionReason::kTtl) {
|
||||
ttl_compactions++;
|
||||
@@ -4634,7 +4697,7 @@ TEST_F(DBCompactionTest, LevelCompactExpiredTtlFiles) {
|
||||
ASSERT_OK(Flush());
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
ASSERT_TRUE(compaction->compaction_reason() == CompactionReason::kTtl);
|
||||
});
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||
@@ -4682,7 +4745,7 @@ TEST_F(DBCompactionTest, LevelCompactExpiredTtlFiles) {
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
ASSERT_TRUE(compaction->compaction_reason() == CompactionReason::kTtl);
|
||||
});
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||
@@ -4709,7 +4772,6 @@ TEST_F(DBCompactionTest, LevelTtlCompactionOutputCuttingIteractingWithOther) {
|
||||
options.env = env_;
|
||||
options.target_file_size_base = 4 << 10;
|
||||
options.disable_auto_compactions = true;
|
||||
options.level_compaction_dynamic_file_size = false;
|
||||
|
||||
DestroyAndReopen(options);
|
||||
Random rnd(301);
|
||||
@@ -4810,7 +4872,7 @@ TEST_F(DBCompactionTest, LevelTtlCascadingCompactions) {
|
||||
int ttl_compactions = 0;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
auto compaction_reason = compaction->compaction_reason();
|
||||
if (compaction_reason == CompactionReason::kTtl) {
|
||||
ttl_compactions++;
|
||||
@@ -4958,7 +5020,7 @@ TEST_F(DBCompactionTest, LevelPeriodicCompaction) {
|
||||
int periodic_compactions = 0;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
auto compaction_reason = compaction->compaction_reason();
|
||||
if (compaction_reason == CompactionReason::kPeriodicCompaction) {
|
||||
periodic_compactions++;
|
||||
@@ -5142,7 +5204,7 @@ TEST_F(DBCompactionTest, LevelPeriodicCompactionWithOldDB) {
|
||||
bool set_creation_time_to_zero = true;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
auto compaction_reason = compaction->compaction_reason();
|
||||
if (compaction_reason == CompactionReason::kPeriodicCompaction) {
|
||||
periodic_compactions++;
|
||||
@@ -5150,7 +5212,7 @@ TEST_F(DBCompactionTest, LevelPeriodicCompactionWithOldDB) {
|
||||
});
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"PropertyBlockBuilder::AddTableProperty:Start", [&](void* arg) {
|
||||
TableProperties* props = reinterpret_cast<TableProperties*>(arg);
|
||||
TableProperties* props = static_cast<TableProperties*>(arg);
|
||||
if (set_file_creation_time_to_zero) {
|
||||
props->file_creation_time = 0;
|
||||
}
|
||||
@@ -5214,7 +5276,7 @@ TEST_F(DBCompactionTest, LevelPeriodicAndTtlCompaction) {
|
||||
int ttl_compactions = 0;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
auto compaction_reason = compaction->compaction_reason();
|
||||
if (compaction_reason == CompactionReason::kPeriodicCompaction) {
|
||||
periodic_compactions++;
|
||||
@@ -5397,7 +5459,7 @@ TEST_F(DBCompactionTest, LevelPeriodicCompactionWithCompactionFilters) {
|
||||
int periodic_compactions = 0;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
auto compaction_reason = compaction->compaction_reason();
|
||||
if (compaction_reason == CompactionReason::kPeriodicCompaction) {
|
||||
periodic_compactions++;
|
||||
@@ -6150,7 +6212,7 @@ class CompactionPriTest : public DBTestBase,
|
||||
public testing::WithParamInterface<uint32_t> {
|
||||
public:
|
||||
CompactionPriTest()
|
||||
: DBTestBase("compaction_pri_test", /*env_do_fsync=*/true) {
|
||||
: DBTestBase("compaction_pri_test", /*env_do_fsync=*/false) {
|
||||
compaction_pri_ = GetParam();
|
||||
}
|
||||
|
||||
@@ -6270,26 +6332,30 @@ 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 = 4;
|
||||
options.num_levels = 3;
|
||||
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;
|
||||
options.max_bytes_for_level_base = 8 * kKeysPerBuffer * 1024;
|
||||
// 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.disable_auto_compactions = true;
|
||||
// Setup 7 threads but limited subcompactions so that
|
||||
// RoundRobin requires extra compactions from reserved threads
|
||||
// Setup `kNumSubcompactions` threads but limited subcompactions so
|
||||
// that RoundRobin requires extra compactions from reserved threads
|
||||
options.max_subcompactions = 1;
|
||||
options.max_background_compactions = 7;
|
||||
options.max_background_compactions = kNumSubcompactions;
|
||||
options.max_compaction_bytes = 100000000;
|
||||
DestroyAndReopen(options);
|
||||
env_->SetBackgroundThreads(7, Env::LOW);
|
||||
env_->SetBackgroundThreads(kNumSubcompactions, 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 < files_per_level[lvl]; i++) {
|
||||
for (int i = 0; i < kFilesPerLevel; 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
|
||||
@@ -6300,9 +6366,8 @@ TEST_P(RoundRobinSubcompactionsAgainstPressureToken, PressureTokenTest) {
|
||||
ASSERT_OK(Flush());
|
||||
}
|
||||
MoveFilesToLevel(lvl);
|
||||
ASSERT_EQ(files_per_level[lvl], NumTableFilesAtLevel(lvl, 0));
|
||||
ASSERT_EQ(kFilesPerLevel, 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.
|
||||
@@ -6311,10 +6376,10 @@ TEST_P(RoundRobinSubcompactionsAgainstPressureToken, PressureTokenTest) {
|
||||
"CompactionJob::GenSubcompactionBoundaries:0", [&](void* arg) {
|
||||
uint64_t num_planned_subcompactions = *(static_cast<uint64_t*>(arg));
|
||||
if (grab_pressure_token_) {
|
||||
// 7 files are selected for round-robin under auto
|
||||
// `kNumSubcompactions` 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, 7);
|
||||
ASSERT_EQ(num_planned_subcompactions, kNumSubcompactions);
|
||||
} else {
|
||||
ASSERT_EQ(num_planned_subcompactions, 1);
|
||||
}
|
||||
@@ -7132,8 +7197,7 @@ TEST_F(DBCompactionTest, ConsistencyFailTest) {
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"VersionBuilder::CheckConsistency0", [&](void* arg) {
|
||||
auto p =
|
||||
reinterpret_cast<std::pair<FileMetaData**, FileMetaData**>*>(arg);
|
||||
auto p = static_cast<std::pair<FileMetaData**, FileMetaData**>*>(arg);
|
||||
// just swap the two FileMetaData so that we hit error
|
||||
// in CheckConsistency funcion
|
||||
FileMetaData* temp = *(p->first);
|
||||
@@ -7170,8 +7234,7 @@ TEST_F(DBCompactionTest, ConsistencyFailTest2) {
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"VersionBuilder::CheckConsistency1", [&](void* arg) {
|
||||
auto p =
|
||||
reinterpret_cast<std::pair<FileMetaData**, FileMetaData**>*>(arg);
|
||||
auto p = static_cast<std::pair<FileMetaData**, FileMetaData**>*>(arg);
|
||||
// just swap the two FileMetaData so that we hit error
|
||||
// in CheckConsistency funcion
|
||||
FileMetaData* temp = *(p->first);
|
||||
@@ -7984,7 +8047,7 @@ TEST_F(DBCompactionTest, UpdateLevelSubCompactionTest) {
|
||||
bool has_compaction = false;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
ASSERT_TRUE(compaction->max_subcompactions() == 10);
|
||||
has_compaction = true;
|
||||
});
|
||||
@@ -8008,7 +8071,7 @@ TEST_F(DBCompactionTest, UpdateLevelSubCompactionTest) {
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"LevelCompactionPicker::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
ASSERT_TRUE(compaction->max_subcompactions() == 2);
|
||||
has_compaction = true;
|
||||
});
|
||||
@@ -8036,7 +8099,7 @@ TEST_F(DBCompactionTest, UpdateUniversalSubCompactionTest) {
|
||||
bool has_compaction = false;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"UniversalCompactionBuilder::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
ASSERT_TRUE(compaction->max_subcompactions() == 10);
|
||||
has_compaction = true;
|
||||
});
|
||||
@@ -8059,7 +8122,7 @@ TEST_F(DBCompactionTest, UpdateUniversalSubCompactionTest) {
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"UniversalCompactionBuilder::PickCompaction:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
ASSERT_TRUE(compaction->max_subcompactions() == 2);
|
||||
has_compaction = true;
|
||||
});
|
||||
@@ -9636,6 +9699,7 @@ TEST_F(DBCompactionTest, BottomPriCompactionCountsTowardConcurrencyLimit) {
|
||||
test::SleepingBackgroundTask sleeping_task_low;
|
||||
env_->Schedule(&test::SleepingBackgroundTask::DoSleepTask, &sleeping_task_low,
|
||||
Env::Priority::LOW);
|
||||
sleeping_task_low.WaitUntilSleeping();
|
||||
|
||||
TEST_SYNC_POINT(
|
||||
"DBCompactionTest::BottomPriCompactionCountsTowardConcurrencyLimit:"
|
||||
@@ -10184,8 +10248,7 @@ TEST_F(DBCompactionTest, ErrorWhenReadFileHead) {
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"RandomAccessFileReader::Read::BeforeReturn",
|
||||
[&count, &error_file](void* pair_ptr) {
|
||||
auto p =
|
||||
reinterpret_cast<std::pair<std::string*, IOStatus*>*>(pair_ptr);
|
||||
auto p = static_cast<std::pair<std::string*, IOStatus*>*>(pair_ptr);
|
||||
int cur = ++count;
|
||||
if (cur == error_file) {
|
||||
IOStatus* io_s = p->second;
|
||||
|
||||
@@ -338,7 +338,7 @@ TEST_F(DBTestDynamicLevel, DynamicLevelMaxBytesCompactRange) {
|
||||
std::set<int> output_levels;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"CompactionPicker::CompactRange:Return", [&](void* arg) {
|
||||
Compaction* compaction = reinterpret_cast<Compaction*>(arg);
|
||||
Compaction* compaction = static_cast<Compaction*>(arg);
|
||||
output_levels.insert(compaction->output_level());
|
||||
});
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
@@ -121,7 +121,7 @@ Status DBImpl::GetSortedWalFiles(VectorLogPtr& files) {
|
||||
|
||||
// DisableFileDeletions / EnableFileDeletions not supported in read-only DB
|
||||
if (deletions_disabled.ok()) {
|
||||
Status s2 = EnableFileDeletions(/*force=*/false);
|
||||
Status s2 = EnableFileDeletions();
|
||||
assert(s2.ok());
|
||||
s2.PermitUncheckedError();
|
||||
} else {
|
||||
|
||||
+39
-6
@@ -272,7 +272,7 @@ TEST_F(DBFlushTest, ScheduleOnlyOneBgThread) {
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::MaybeScheduleFlushOrCompaction:AfterSchedule:0", [&](void* arg) {
|
||||
ASSERT_NE(nullptr, arg);
|
||||
auto unscheduled_flushes = *reinterpret_cast<int*>(arg);
|
||||
auto unscheduled_flushes = *static_cast<int*>(arg);
|
||||
ASSERT_EQ(0, unscheduled_flushes);
|
||||
++called;
|
||||
});
|
||||
@@ -1791,7 +1791,7 @@ TEST_F(DBFlushTest, MemPurgeCorrectLogNumberAndSSTFileCreation) {
|
||||
std::atomic<uint64_t> num_memtable_at_first_flush(0);
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"FlushJob::WriteLevel0Table:num_memtables", [&](void* arg) {
|
||||
uint64_t* mems_size = reinterpret_cast<uint64_t*>(arg);
|
||||
uint64_t* mems_size = static_cast<uint64_t*>(arg);
|
||||
// atomic_compare_exchange_strong sometimes updates the value
|
||||
// of ZERO (the "expected" object), so we make sure ZERO is indeed...
|
||||
// zero.
|
||||
@@ -2038,7 +2038,7 @@ TEST_F(DBFlushTest, FireOnFlushCompletedAfterCommittedResult) {
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"FlushJob::WriteLevel0Table", [&listener](void* arg) {
|
||||
// Wait for the second flush finished, out of mutex.
|
||||
auto* mems = reinterpret_cast<autovector<MemTable*>*>(arg);
|
||||
auto* mems = static_cast<autovector<MemTable*>*>(arg);
|
||||
if (mems->front()->GetEarliestSequenceNumber() == listener->seq1 - 1) {
|
||||
TEST_SYNC_POINT(
|
||||
"DBFlushTest::FireOnFlushCompletedAfterCommittedResult:"
|
||||
@@ -2386,7 +2386,7 @@ TEST_F(DBFlushTest, PickRightMemtables) {
|
||||
});
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::FlushMemTableToOutputFile:AfterPickMemtables", [&](void* arg) {
|
||||
auto* job = reinterpret_cast<FlushJob*>(arg);
|
||||
auto* job = static_cast<FlushJob*>(arg);
|
||||
assert(job);
|
||||
const auto& mems = job->GetMemTables();
|
||||
assert(mems.size() == 1);
|
||||
@@ -2634,7 +2634,7 @@ TEST_P(DBAtomicFlushTest, ManualFlushUnder2PC) {
|
||||
// it means atomic flush didn't write the min_log_number_to_keep to MANIFEST.
|
||||
cfs.push_back(kDefaultColumnFamilyName);
|
||||
ASSERT_OK(TryReopenWithColumnFamilies(cfs, options));
|
||||
DBImpl* db_impl = reinterpret_cast<DBImpl*>(db_);
|
||||
DBImpl* db_impl = static_cast<DBImpl*>(db_);
|
||||
ASSERT_TRUE(db_impl->allow_2pc());
|
||||
ASSERT_NE(db_impl->MinLogNumberToKeep(), 0);
|
||||
}
|
||||
@@ -3035,6 +3035,39 @@ 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
|
||||
@@ -3138,7 +3171,7 @@ TEST_P(DBAtomicFlushTest, BgThreadNoWaitAfterManifestError) {
|
||||
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"VersionSet::ProcessManifestWrites:AfterSyncManifest", [&](void* arg) {
|
||||
auto* ptr = reinterpret_cast<IOStatus*>(arg);
|
||||
auto* ptr = static_cast<IOStatus*>(arg);
|
||||
assert(ptr);
|
||||
*ptr = IOStatus::IOError("Injected failure");
|
||||
});
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
|
||||
namespace ROCKSDB_NAMESPACE {
|
||||
|
||||
extern void MarkKeyMayExist(void* arg);
|
||||
extern bool SaveValue(void* arg, const ParsedInternalKey& parsed_key,
|
||||
const Slice& v, bool hit_and_return);
|
||||
|
||||
CompactedDBImpl::CompactedDBImpl(const DBOptions& options,
|
||||
const std::string& dbname)
|
||||
: DBImpl(options, dbname, /*seq_per_batch*/ false, +/*batch_per_txn*/ true,
|
||||
@@ -37,12 +33,6 @@ size_t CompactedDBImpl::FindFile(const Slice& key) {
|
||||
files_.files);
|
||||
}
|
||||
|
||||
Status CompactedDBImpl::Get(const ReadOptions& options, ColumnFamilyHandle*,
|
||||
const Slice& key, PinnableSlice* value) {
|
||||
return Get(options, /*column_family*/ nullptr, key, value,
|
||||
/*timestamp*/ nullptr);
|
||||
}
|
||||
|
||||
Status CompactedDBImpl::Get(const ReadOptions& _read_options,
|
||||
ColumnFamilyHandle*, const Slice& key,
|
||||
PinnableSlice* value, std::string* timestamp) {
|
||||
@@ -112,62 +102,59 @@ Status CompactedDBImpl::Get(const ReadOptions& _read_options,
|
||||
return Status::NotFound();
|
||||
}
|
||||
|
||||
std::vector<Status> CompactedDBImpl::MultiGet(
|
||||
const ReadOptions& options, const std::vector<ColumnFamilyHandle*>&,
|
||||
const std::vector<Slice>& keys, std::vector<std::string>* values) {
|
||||
return MultiGet(options, keys, values, /*timestamps*/ nullptr);
|
||||
}
|
||||
|
||||
std::vector<Status> CompactedDBImpl::MultiGet(
|
||||
const ReadOptions& _read_options, const std::vector<ColumnFamilyHandle*>&,
|
||||
const std::vector<Slice>& keys, std::vector<std::string>* values,
|
||||
std::vector<std::string>* timestamps) {
|
||||
void CompactedDBImpl::MultiGet(const ReadOptions& _read_options,
|
||||
size_t num_keys,
|
||||
ColumnFamilyHandle** /*column_families*/,
|
||||
const Slice* keys, PinnableSlice* values,
|
||||
std::string* timestamps, Status* statuses,
|
||||
const bool /*sorted_input*/) {
|
||||
assert(user_comparator_);
|
||||
size_t num_keys = keys.size();
|
||||
Status s;
|
||||
if (_read_options.io_activity != Env::IOActivity::kUnknown &&
|
||||
_read_options.io_activity != Env::IOActivity::kMultiGet) {
|
||||
Status s = Status::InvalidArgument(
|
||||
s = Status::InvalidArgument(
|
||||
"Can only call MultiGet with `ReadOptions::io_activity` is "
|
||||
"`Env::IOActivity::kUnknown` or `Env::IOActivity::kMultiGet`");
|
||||
return std::vector<Status>(num_keys, s);
|
||||
}
|
||||
|
||||
ReadOptions read_options(_read_options);
|
||||
if (read_options.io_activity == Env::IOActivity::kUnknown) {
|
||||
read_options.io_activity = Env::IOActivity::kMultiGet;
|
||||
if (s.ok()) {
|
||||
if (read_options.io_activity == Env::IOActivity::kUnknown) {
|
||||
read_options.io_activity = Env::IOActivity::kMultiGet;
|
||||
}
|
||||
|
||||
if (read_options.timestamp) {
|
||||
s = FailIfTsMismatchCf(DefaultColumnFamily(), *(read_options.timestamp));
|
||||
if (s.ok()) {
|
||||
if (read_options.timestamp->size() > 0) {
|
||||
s = FailIfReadCollapsedHistory(cfd_, cfd_->GetSuperVersion(),
|
||||
*(read_options.timestamp));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s = FailIfCfHasTs(DefaultColumnFamily());
|
||||
}
|
||||
}
|
||||
|
||||
if (read_options.timestamp) {
|
||||
Status s =
|
||||
FailIfTsMismatchCf(DefaultColumnFamily(), *(read_options.timestamp));
|
||||
if (!s.ok()) {
|
||||
return std::vector<Status>(num_keys, s);
|
||||
}
|
||||
if (read_options.timestamp->size() > 0) {
|
||||
s = FailIfReadCollapsedHistory(cfd_, cfd_->GetSuperVersion(),
|
||||
*(read_options.timestamp));
|
||||
if (!s.ok()) {
|
||||
return std::vector<Status>(num_keys, s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Status s = FailIfCfHasTs(DefaultColumnFamily());
|
||||
if (!s.ok()) {
|
||||
return std::vector<Status>(num_keys, s);
|
||||
if (!s.ok()) {
|
||||
for (size_t i = 0; i < num_keys; ++i) {
|
||||
statuses[i] = s;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the timestamps for returning results so that we can distinguish
|
||||
// between tombstone or key that has never been written
|
||||
if (timestamps) {
|
||||
for (auto& ts : *timestamps) {
|
||||
ts.clear();
|
||||
for (size_t i = 0; i < num_keys; ++i) {
|
||||
timestamps[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
GetWithTimestampReadCallback read_cb(kMaxSequenceNumber);
|
||||
autovector<TableReader*, 16> reader_list;
|
||||
for (const auto& key : keys) {
|
||||
for (size_t i = 0; i < num_keys; ++i) {
|
||||
const Slice& key = keys[i];
|
||||
LookupKey lkey(key, kMaxSequenceNumber, read_options.timestamp);
|
||||
const FdWithKeyRange& f = files_.files[FindFile(lkey.user_key())];
|
||||
if (user_comparator_->CompareWithoutTimestamp(
|
||||
@@ -181,30 +168,26 @@ std::vector<Status> CompactedDBImpl::MultiGet(
|
||||
reader_list.push_back(f.fd.table_reader);
|
||||
}
|
||||
}
|
||||
std::vector<Status> statuses(num_keys, Status::NotFound());
|
||||
values->resize(num_keys);
|
||||
if (timestamps) {
|
||||
timestamps->resize(num_keys);
|
||||
for (size_t i = 0; i < num_keys; ++i) {
|
||||
statuses[i] = Status::NotFound();
|
||||
}
|
||||
int idx = 0;
|
||||
for (auto* r : reader_list) {
|
||||
if (r != nullptr) {
|
||||
PinnableSlice pinnable_val;
|
||||
std::string& value = (*values)[idx];
|
||||
PinnableSlice& pinnable_val = values[idx];
|
||||
LookupKey lkey(keys[idx], kMaxSequenceNumber, read_options.timestamp);
|
||||
std::string* timestamp = timestamps ? &(*timestamps)[idx] : nullptr;
|
||||
std::string* timestamp = timestamps ? ×tamps[idx] : nullptr;
|
||||
GetContext get_context(
|
||||
user_comparator_, nullptr, nullptr, nullptr, GetContext::kNotFound,
|
||||
lkey.user_key(), &pinnable_val, /*columns=*/nullptr,
|
||||
user_comparator_->timestamp_size() > 0 ? timestamp : nullptr, nullptr,
|
||||
nullptr, true, nullptr, nullptr, nullptr, nullptr, &read_cb);
|
||||
Status s =
|
||||
Status status =
|
||||
r->Get(read_options, lkey.internal_key(), &get_context, nullptr);
|
||||
assert(static_cast<size_t>(idx) < statuses.size());
|
||||
if (!s.ok() && !s.IsNotFound()) {
|
||||
statuses[idx] = s;
|
||||
assert(static_cast<size_t>(idx) < num_keys);
|
||||
if (!status.ok() && !status.IsNotFound()) {
|
||||
statuses[idx] = status;
|
||||
} else {
|
||||
value.assign(pinnable_val.data(), pinnable_val.size());
|
||||
if (get_context.State() == GetContext::kFound) {
|
||||
statuses[idx] = Status::OK();
|
||||
}
|
||||
@@ -212,7 +195,6 @@ std::vector<Status> CompactedDBImpl::MultiGet(
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
return statuses;
|
||||
}
|
||||
|
||||
Status CompactedDBImpl::Init(const Options& options) {
|
||||
|
||||
@@ -26,33 +26,23 @@ class CompactedDBImpl : public DBImpl {
|
||||
|
||||
// Implementations of the DB interface
|
||||
using DB::Get;
|
||||
virtual Status Get(const ReadOptions& options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
PinnableSlice* value) override;
|
||||
|
||||
Status Get(const ReadOptions& _read_options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
PinnableSlice* value, std::string* timestamp) override;
|
||||
Status Get(const ReadOptions& options, ColumnFamilyHandle* column_family,
|
||||
const Slice& key, PinnableSlice* value,
|
||||
std::string* timestamp) override;
|
||||
|
||||
using DB::MultiGet;
|
||||
// Note that CompactedDBImpl::MultiGet is not the optimized version of
|
||||
// MultiGet to use.
|
||||
// TODO: optimize CompactedDBImpl::MultiGet, see DBImpl::MultiGet for details.
|
||||
virtual std::vector<Status> MultiGet(
|
||||
const ReadOptions& options, const std::vector<ColumnFamilyHandle*>&,
|
||||
const std::vector<Slice>& keys,
|
||||
std::vector<std::string>* values) override;
|
||||
|
||||
std::vector<Status> MultiGet(const ReadOptions& _read_options,
|
||||
const std::vector<ColumnFamilyHandle*>&,
|
||||
const std::vector<Slice>& keys,
|
||||
std::vector<std::string>* values,
|
||||
std::vector<std::string>* timestamps) override;
|
||||
void MultiGet(const ReadOptions& options, size_t num_keys,
|
||||
ColumnFamilyHandle** column_families, const Slice* keys,
|
||||
PinnableSlice* values, std::string* timestamps,
|
||||
Status* statuses, const bool sorted_input) override;
|
||||
|
||||
using DBImpl::Put;
|
||||
virtual Status Put(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/, const Slice& /*value*/) override {
|
||||
Status Put(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/, const Slice& /*key*/,
|
||||
const Slice& /*value*/) override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
|
||||
@@ -65,54 +55,53 @@ class CompactedDBImpl : public DBImpl {
|
||||
}
|
||||
|
||||
using DBImpl::Merge;
|
||||
virtual Status Merge(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/, const Slice& /*value*/) override {
|
||||
Status Merge(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/, const Slice& /*key*/,
|
||||
const Slice& /*value*/) override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
|
||||
using DBImpl::Delete;
|
||||
virtual Status Delete(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/) override {
|
||||
Status Delete(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/) override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
virtual Status Write(const WriteOptions& /*options*/,
|
||||
WriteBatch* /*updates*/) override {
|
||||
Status Write(const WriteOptions& /*options*/,
|
||||
WriteBatch* /*updates*/) override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
using DBImpl::CompactRange;
|
||||
virtual Status CompactRange(const CompactRangeOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice* /*begin*/,
|
||||
const Slice* /*end*/) override {
|
||||
Status CompactRange(const CompactRangeOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice* /*begin*/, const Slice* /*end*/) override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
|
||||
virtual Status DisableFileDeletions() override {
|
||||
Status DisableFileDeletions() override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
virtual Status EnableFileDeletions(bool /*force*/) override {
|
||||
Status EnableFileDeletions() override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
virtual Status GetLiveFiles(std::vector<std::string>& ret,
|
||||
uint64_t* manifest_file_size,
|
||||
bool /*flush_memtable*/) override {
|
||||
Status GetLiveFiles(std::vector<std::string>& ret,
|
||||
uint64_t* manifest_file_size,
|
||||
bool /*flush_memtable*/) override {
|
||||
return DBImpl::GetLiveFiles(ret, manifest_file_size,
|
||||
false /* flush_memtable */);
|
||||
}
|
||||
using DBImpl::Flush;
|
||||
virtual Status Flush(const FlushOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/) override {
|
||||
Status Flush(const FlushOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/) override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
|
||||
virtual Status SyncWAL() override {
|
||||
Status SyncWAL() override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
|
||||
using DB::IngestExternalFile;
|
||||
virtual Status IngestExternalFile(
|
||||
Status IngestExternalFile(
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const std::vector<std::string>& /*external_files*/,
|
||||
const IngestExternalFileOptions& /*ingestion_options*/) override {
|
||||
@@ -120,7 +109,7 @@ class CompactedDBImpl : public DBImpl {
|
||||
}
|
||||
|
||||
using DB::CreateColumnFamilyWithImport;
|
||||
virtual Status CreateColumnFamilyWithImport(
|
||||
Status CreateColumnFamilyWithImport(
|
||||
const ColumnFamilyOptions& /*options*/,
|
||||
const std::string& /*column_family_name*/,
|
||||
const ImportColumnFamilyOptions& /*import_options*/,
|
||||
@@ -130,9 +119,9 @@ class CompactedDBImpl : public DBImpl {
|
||||
}
|
||||
|
||||
using DB::ClipColumnFamily;
|
||||
virtual Status ClipColumnFamily(ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*begin*/,
|
||||
const Slice& /*end*/) override {
|
||||
Status ClipColumnFamily(ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*begin*/,
|
||||
const Slice& /*end*/) override {
|
||||
return Status::NotSupported("Not supported in compacted db mode.");
|
||||
}
|
||||
|
||||
|
||||
+258
-410
File diff suppressed because it is too large.
Load diff
+171
-169
@@ -229,16 +229,12 @@ class DBImpl : public DB {
|
||||
const Slice& end_key, const Slice& ts) override;
|
||||
|
||||
using DB::Write;
|
||||
virtual Status Write(const WriteOptions& options,
|
||||
WriteBatch* updates) override;
|
||||
Status Write(const WriteOptions& options, WriteBatch* updates) override;
|
||||
|
||||
using DB::Get;
|
||||
virtual Status Get(const ReadOptions& options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
PinnableSlice* value) override;
|
||||
virtual Status Get(const ReadOptions& _read_options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
PinnableSlice* value, std::string* timestamp) override;
|
||||
Status Get(const ReadOptions& _read_options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
PinnableSlice* value, std::string* timestamp) override;
|
||||
|
||||
using DB::GetEntity;
|
||||
Status GetEntity(const ReadOptions& options,
|
||||
@@ -263,17 +259,6 @@ class DBImpl : public DB {
|
||||
}
|
||||
|
||||
using DB::MultiGet;
|
||||
virtual std::vector<Status> MultiGet(
|
||||
const ReadOptions& options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_family,
|
||||
const std::vector<Slice>& keys,
|
||||
std::vector<std::string>* values) override;
|
||||
virtual std::vector<Status> MultiGet(
|
||||
const ReadOptions& _read_options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_family,
|
||||
const std::vector<Slice>& keys, std::vector<std::string>* values,
|
||||
std::vector<std::string>* timestamps) override;
|
||||
|
||||
// This MultiGet is a batched version, which may be faster than calling Get
|
||||
// multiple times, especially if the keys have some spatial locality that
|
||||
// enables them to be queried in the same SST files/set of files. The larger
|
||||
@@ -281,19 +266,6 @@ class DBImpl : public DB {
|
||||
// The values and statuses parameters are arrays with number of elements
|
||||
// equal to keys.size(). This allows the storage for those to be alloacted
|
||||
// by the caller on the stack for small batches
|
||||
void MultiGet(const ReadOptions& options, ColumnFamilyHandle* column_family,
|
||||
const size_t num_keys, const Slice* keys, PinnableSlice* values,
|
||||
Status* statuses, const bool sorted_input = false) override;
|
||||
void MultiGet(const ReadOptions& _read_options,
|
||||
ColumnFamilyHandle* column_family, const size_t num_keys,
|
||||
const Slice* keys, PinnableSlice* values,
|
||||
std::string* timestamps, Status* statuses,
|
||||
const bool sorted_input = false) override;
|
||||
|
||||
void MultiGet(const ReadOptions& options, const size_t num_keys,
|
||||
ColumnFamilyHandle** column_families, const Slice* keys,
|
||||
PinnableSlice* values, Status* statuses,
|
||||
const bool sorted_input = false) override;
|
||||
void MultiGet(const ReadOptions& _read_options, const size_t num_keys,
|
||||
ColumnFamilyHandle** column_families, const Slice* keys,
|
||||
PinnableSlice* values, std::string* timestamps,
|
||||
@@ -319,18 +291,45 @@ class DBImpl : public DB {
|
||||
const Slice* keys,
|
||||
PinnableAttributeGroups* results) override;
|
||||
|
||||
virtual Status CreateColumnFamily(const ColumnFamilyOptions& cf_options,
|
||||
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) override;
|
||||
virtual Status CreateColumnFamilies(
|
||||
ColumnFamilyHandle** handle);
|
||||
Status CreateColumnFamilies(
|
||||
const ColumnFamilyOptions& cf_options,
|
||||
const std::vector<std::string>& column_family_names,
|
||||
std::vector<ColumnFamilyHandle*>* handles) override;
|
||||
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);
|
||||
|
||||
Status CreateColumnFamilies(
|
||||
const std::vector<ColumnFamilyDescriptor>& column_families,
|
||||
std::vector<ColumnFamilyHandle*>* handles) override;
|
||||
virtual Status DropColumnFamily(ColumnFamilyHandle* column_family) override;
|
||||
virtual Status DropColumnFamilies(
|
||||
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);
|
||||
Status DropColumnFamily(ColumnFamilyHandle* column_family) override;
|
||||
Status DropColumnFamilies(
|
||||
const std::vector<ColumnFamilyHandle*>& column_families) override;
|
||||
|
||||
// Returns false if key doesn't exist in the database and true if it may.
|
||||
@@ -338,21 +337,20 @@ class DBImpl : public DB {
|
||||
// memory. On return, if value was found, then value_found will be set to true
|
||||
// , otherwise false.
|
||||
using DB::KeyMayExist;
|
||||
virtual bool KeyMayExist(const ReadOptions& options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
std::string* value, std::string* timestamp,
|
||||
bool* value_found = nullptr) override;
|
||||
bool KeyMayExist(const ReadOptions& options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
std::string* value, std::string* timestamp,
|
||||
bool* value_found = nullptr) override;
|
||||
|
||||
using DB::NewIterator;
|
||||
virtual Iterator* NewIterator(const ReadOptions& _read_options,
|
||||
ColumnFamilyHandle* column_family) override;
|
||||
virtual Status NewIterators(
|
||||
const ReadOptions& _read_options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_families,
|
||||
std::vector<Iterator*>* iterators) override;
|
||||
Iterator* NewIterator(const ReadOptions& _read_options,
|
||||
ColumnFamilyHandle* column_family) override;
|
||||
Status NewIterators(const ReadOptions& _read_options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_families,
|
||||
std::vector<Iterator*>* iterators) override;
|
||||
|
||||
virtual const Snapshot* GetSnapshot() override;
|
||||
virtual void ReleaseSnapshot(const Snapshot* snapshot) override;
|
||||
const Snapshot* GetSnapshot() override;
|
||||
void ReleaseSnapshot(const Snapshot* snapshot) override;
|
||||
// Create a timestamped snapshot. This snapshot can be shared by multiple
|
||||
// readers. If any of them uses it for write conflict checking, then
|
||||
// is_write_conflict_boundary is true. For simplicity, set it to true by
|
||||
@@ -367,35 +365,33 @@ class DBImpl : public DB {
|
||||
timestamped_snapshots) const;
|
||||
|
||||
using DB::GetProperty;
|
||||
virtual bool GetProperty(ColumnFamilyHandle* column_family,
|
||||
const Slice& property, std::string* value) override;
|
||||
bool GetProperty(ColumnFamilyHandle* column_family, const Slice& property,
|
||||
std::string* value) override;
|
||||
using DB::GetMapProperty;
|
||||
virtual bool GetMapProperty(
|
||||
ColumnFamilyHandle* column_family, const Slice& property,
|
||||
std::map<std::string, std::string>* value) override;
|
||||
bool GetMapProperty(ColumnFamilyHandle* column_family, const Slice& property,
|
||||
std::map<std::string, std::string>* value) override;
|
||||
using DB::GetIntProperty;
|
||||
virtual bool GetIntProperty(ColumnFamilyHandle* column_family,
|
||||
const Slice& property, uint64_t* value) override;
|
||||
bool GetIntProperty(ColumnFamilyHandle* column_family, const Slice& property,
|
||||
uint64_t* value) override;
|
||||
using DB::GetAggregatedIntProperty;
|
||||
virtual bool GetAggregatedIntProperty(const Slice& property,
|
||||
uint64_t* aggregated_value) override;
|
||||
bool GetAggregatedIntProperty(const Slice& property,
|
||||
uint64_t* aggregated_value) override;
|
||||
using DB::GetApproximateSizes;
|
||||
virtual Status GetApproximateSizes(const SizeApproximationOptions& options,
|
||||
ColumnFamilyHandle* column_family,
|
||||
const Range* range, int n,
|
||||
uint64_t* sizes) override;
|
||||
Status GetApproximateSizes(const SizeApproximationOptions& options,
|
||||
ColumnFamilyHandle* column_family,
|
||||
const Range* range, int n,
|
||||
uint64_t* sizes) override;
|
||||
using DB::GetApproximateMemTableStats;
|
||||
virtual void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
|
||||
const Range& range,
|
||||
uint64_t* const count,
|
||||
uint64_t* const size) override;
|
||||
void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
|
||||
const Range& range, uint64_t* const count,
|
||||
uint64_t* const size) override;
|
||||
using DB::CompactRange;
|
||||
virtual Status CompactRange(const CompactRangeOptions& options,
|
||||
ColumnFamilyHandle* column_family,
|
||||
const Slice* begin, const Slice* end) override;
|
||||
Status CompactRange(const CompactRangeOptions& options,
|
||||
ColumnFamilyHandle* column_family, const Slice* begin,
|
||||
const Slice* end) override;
|
||||
|
||||
using DB::CompactFiles;
|
||||
virtual Status CompactFiles(
|
||||
Status CompactFiles(
|
||||
const CompactionOptions& compact_options,
|
||||
ColumnFamilyHandle* column_family,
|
||||
const std::vector<std::string>& input_file_names, const int output_level,
|
||||
@@ -403,50 +399,54 @@ class DBImpl : public DB {
|
||||
std::vector<std::string>* const output_file_names = nullptr,
|
||||
CompactionJobInfo* compaction_job_info = nullptr) override;
|
||||
|
||||
virtual Status PauseBackgroundWork() override;
|
||||
virtual Status ContinueBackgroundWork() override;
|
||||
Status PauseBackgroundWork() override;
|
||||
Status ContinueBackgroundWork() override;
|
||||
|
||||
virtual Status EnableAutoCompaction(
|
||||
Status EnableAutoCompaction(
|
||||
const std::vector<ColumnFamilyHandle*>& column_family_handles) override;
|
||||
|
||||
virtual void EnableManualCompaction() override;
|
||||
virtual void DisableManualCompaction() override;
|
||||
void EnableManualCompaction() override;
|
||||
void DisableManualCompaction() override;
|
||||
|
||||
using DB::SetOptions;
|
||||
Status SetOptions(
|
||||
ColumnFamilyHandle* column_family,
|
||||
const std::unordered_map<std::string, std::string>& options_map) override;
|
||||
|
||||
virtual Status SetDBOptions(
|
||||
Status SetDBOptions(
|
||||
const std::unordered_map<std::string, std::string>& options_map) override;
|
||||
|
||||
using DB::NumberLevels;
|
||||
virtual int NumberLevels(ColumnFamilyHandle* column_family) override;
|
||||
int NumberLevels(ColumnFamilyHandle* column_family) override;
|
||||
using DB::MaxMemCompactionLevel;
|
||||
virtual int MaxMemCompactionLevel(ColumnFamilyHandle* column_family) override;
|
||||
int MaxMemCompactionLevel(ColumnFamilyHandle* column_family) override;
|
||||
using DB::Level0StopWriteTrigger;
|
||||
virtual int Level0StopWriteTrigger(
|
||||
ColumnFamilyHandle* column_family) override;
|
||||
virtual const std::string& GetName() const override;
|
||||
virtual Env* GetEnv() const override;
|
||||
virtual FileSystem* GetFileSystem() const override;
|
||||
int Level0StopWriteTrigger(ColumnFamilyHandle* column_family) override;
|
||||
const std::string& GetName() const override;
|
||||
Env* GetEnv() const override;
|
||||
FileSystem* GetFileSystem() const override;
|
||||
using DB::GetOptions;
|
||||
virtual Options GetOptions(ColumnFamilyHandle* column_family) const override;
|
||||
Options GetOptions(ColumnFamilyHandle* column_family) const override;
|
||||
using DB::GetDBOptions;
|
||||
virtual DBOptions GetDBOptions() const override;
|
||||
DBOptions GetDBOptions() const override;
|
||||
using DB::Flush;
|
||||
virtual Status Flush(const FlushOptions& options,
|
||||
ColumnFamilyHandle* column_family) override;
|
||||
virtual Status Flush(
|
||||
Status Flush(const FlushOptions& options,
|
||||
ColumnFamilyHandle* column_family) override;
|
||||
Status Flush(
|
||||
const FlushOptions& options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_families) override;
|
||||
virtual Status FlushWAL(bool sync) override;
|
||||
bool WALBufferIsEmpty();
|
||||
virtual Status SyncWAL() override;
|
||||
virtual Status LockWAL() override;
|
||||
virtual Status UnlockWAL() override;
|
||||
Status FlushWAL(bool sync) override {
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
return FlushWAL(WriteOptions(), sync);
|
||||
}
|
||||
|
||||
virtual SequenceNumber GetLatestSequenceNumber() const override;
|
||||
virtual Status FlushWAL(const WriteOptions& write_options, bool sync);
|
||||
bool WALBufferIsEmpty();
|
||||
Status SyncWAL() override;
|
||||
Status LockWAL() override;
|
||||
Status UnlockWAL() override;
|
||||
|
||||
SequenceNumber GetLatestSequenceNumber() const override;
|
||||
|
||||
// IncreaseFullHistoryTsLow(ColumnFamilyHandle*, std::string) will acquire
|
||||
// and release db_mutex
|
||||
@@ -458,21 +458,21 @@ class DBImpl : public DB {
|
||||
Status GetFullHistoryTsLow(ColumnFamilyHandle* column_family,
|
||||
std::string* ts_low) override;
|
||||
|
||||
virtual Status GetDbIdentity(std::string& identity) const override;
|
||||
Status GetDbIdentity(std::string& identity) const override;
|
||||
|
||||
virtual Status GetDbIdentityFromIdentityFile(std::string* identity) const;
|
||||
|
||||
virtual Status GetDbSessionId(std::string& session_id) const override;
|
||||
Status GetDbSessionId(std::string& session_id) const override;
|
||||
|
||||
ColumnFamilyHandle* DefaultColumnFamily() const override;
|
||||
|
||||
ColumnFamilyHandle* PersistentStatsColumnFamily() const;
|
||||
|
||||
virtual Status Close() override;
|
||||
Status Close() override;
|
||||
|
||||
virtual Status DisableFileDeletions() override;
|
||||
Status DisableFileDeletions() override;
|
||||
|
||||
virtual Status EnableFileDeletions(bool force) override;
|
||||
Status EnableFileDeletions() override;
|
||||
|
||||
virtual bool IsFileDeletionsEnabled() const;
|
||||
|
||||
@@ -481,40 +481,35 @@ class DBImpl : public DB {
|
||||
std::unique_ptr<StatsHistoryIterator>* stats_iterator) override;
|
||||
|
||||
using DB::ResetStats;
|
||||
virtual Status ResetStats() override;
|
||||
Status ResetStats() override;
|
||||
// All the returned filenames start with "/"
|
||||
virtual Status GetLiveFiles(std::vector<std::string>&,
|
||||
uint64_t* manifest_file_size,
|
||||
bool flush_memtable = true) override;
|
||||
virtual Status GetSortedWalFiles(VectorLogPtr& files) override;
|
||||
virtual Status GetCurrentWalFile(
|
||||
std::unique_ptr<LogFile>* current_log_file) override;
|
||||
virtual Status GetCreationTimeOfOldestFile(
|
||||
uint64_t* creation_time) override;
|
||||
Status GetLiveFiles(std::vector<std::string>&, uint64_t* manifest_file_size,
|
||||
bool flush_memtable = true) override;
|
||||
Status GetSortedWalFiles(VectorLogPtr& files) override;
|
||||
Status GetCurrentWalFile(std::unique_ptr<LogFile>* current_log_file) override;
|
||||
Status GetCreationTimeOfOldestFile(uint64_t* creation_time) override;
|
||||
|
||||
virtual Status GetUpdatesSince(
|
||||
Status GetUpdatesSince(
|
||||
SequenceNumber seq_number, std::unique_ptr<TransactionLogIterator>* iter,
|
||||
const TransactionLogIterator::ReadOptions& read_options =
|
||||
TransactionLogIterator::ReadOptions()) override;
|
||||
virtual Status DeleteFile(std::string name) override;
|
||||
Status DeleteFile(std::string name) override;
|
||||
Status DeleteFilesInRanges(ColumnFamilyHandle* column_family,
|
||||
const RangePtr* ranges, size_t n,
|
||||
bool include_end = true);
|
||||
|
||||
virtual void GetLiveFilesMetaData(
|
||||
std::vector<LiveFileMetaData>* metadata) override;
|
||||
void GetLiveFilesMetaData(std::vector<LiveFileMetaData>* metadata) override;
|
||||
|
||||
virtual Status GetLiveFilesChecksumInfo(
|
||||
FileChecksumList* checksum_list) override;
|
||||
Status GetLiveFilesChecksumInfo(FileChecksumList* checksum_list) override;
|
||||
|
||||
virtual Status GetLiveFilesStorageInfo(
|
||||
Status GetLiveFilesStorageInfo(
|
||||
const LiveFilesStorageInfoOptions& opts,
|
||||
std::vector<LiveFileStorageInfo>* files) override;
|
||||
|
||||
// Obtains the meta data of the specified column family of the DB.
|
||||
// TODO(yhchiang): output parameter is placed in the end in this codebase.
|
||||
virtual void GetColumnFamilyMetaData(ColumnFamilyHandle* column_family,
|
||||
ColumnFamilyMetaData* metadata) override;
|
||||
void GetColumnFamilyMetaData(ColumnFamilyHandle* column_family,
|
||||
ColumnFamilyMetaData* metadata) override;
|
||||
|
||||
void GetAllColumnFamilyMetaData(
|
||||
std::vector<ColumnFamilyMetaData>* metadata) override;
|
||||
@@ -526,32 +521,32 @@ class DBImpl : public DB {
|
||||
int target_level) override;
|
||||
|
||||
using DB::IngestExternalFile;
|
||||
virtual Status IngestExternalFile(
|
||||
Status IngestExternalFile(
|
||||
ColumnFamilyHandle* column_family,
|
||||
const std::vector<std::string>& external_files,
|
||||
const IngestExternalFileOptions& ingestion_options) override;
|
||||
|
||||
using DB::IngestExternalFiles;
|
||||
virtual Status IngestExternalFiles(
|
||||
Status IngestExternalFiles(
|
||||
const std::vector<IngestExternalFileArg>& args) override;
|
||||
|
||||
using DB::CreateColumnFamilyWithImport;
|
||||
virtual Status CreateColumnFamilyWithImport(
|
||||
Status CreateColumnFamilyWithImport(
|
||||
const ColumnFamilyOptions& options, const std::string& column_family_name,
|
||||
const ImportColumnFamilyOptions& import_options,
|
||||
const std::vector<const ExportImportFilesMetaData*>& metadatas,
|
||||
ColumnFamilyHandle** handle) override;
|
||||
|
||||
using DB::ClipColumnFamily;
|
||||
virtual Status ClipColumnFamily(ColumnFamilyHandle* column_family,
|
||||
const Slice& begin_key,
|
||||
const Slice& end_key) override;
|
||||
Status ClipColumnFamily(ColumnFamilyHandle* column_family,
|
||||
const Slice& begin_key,
|
||||
const Slice& end_key) override;
|
||||
|
||||
using DB::VerifyFileChecksums;
|
||||
Status VerifyFileChecksums(const ReadOptions& read_options) override;
|
||||
|
||||
using DB::VerifyChecksum;
|
||||
virtual Status VerifyChecksum(const ReadOptions& /*read_options*/) override;
|
||||
Status VerifyChecksum(const ReadOptions& /*read_options*/) override;
|
||||
// Verify the checksums of files in db. Currently only tables are checked.
|
||||
//
|
||||
// read_options: controls file I/O behavior, e.g. read ahead size while
|
||||
@@ -572,18 +567,16 @@ class DBImpl : public DB {
|
||||
const ReadOptions& read_options);
|
||||
|
||||
using DB::StartTrace;
|
||||
virtual Status StartTrace(
|
||||
const TraceOptions& options,
|
||||
std::unique_ptr<TraceWriter>&& trace_writer) override;
|
||||
Status StartTrace(const TraceOptions& options,
|
||||
std::unique_ptr<TraceWriter>&& trace_writer) override;
|
||||
|
||||
using DB::EndTrace;
|
||||
virtual Status EndTrace() override;
|
||||
Status EndTrace() override;
|
||||
|
||||
using DB::NewDefaultReplayer;
|
||||
virtual Status NewDefaultReplayer(
|
||||
const std::vector<ColumnFamilyHandle*>& handles,
|
||||
std::unique_ptr<TraceReader>&& reader,
|
||||
std::unique_ptr<Replayer>* replayer) override;
|
||||
Status NewDefaultReplayer(const std::vector<ColumnFamilyHandle*>& handles,
|
||||
std::unique_ptr<TraceReader>&& reader,
|
||||
std::unique_ptr<Replayer>* replayer) override;
|
||||
|
||||
using DB::StartBlockCacheTrace;
|
||||
Status StartBlockCacheTrace(
|
||||
@@ -605,14 +598,12 @@ class DBImpl : public DB {
|
||||
Status EndIOTrace() override;
|
||||
|
||||
using DB::GetPropertiesOfAllTables;
|
||||
virtual Status GetPropertiesOfAllTables(
|
||||
ColumnFamilyHandle* column_family,
|
||||
TablePropertiesCollection* props) override;
|
||||
virtual Status GetPropertiesOfTablesInRange(
|
||||
Status GetPropertiesOfAllTables(ColumnFamilyHandle* column_family,
|
||||
TablePropertiesCollection* props) override;
|
||||
Status GetPropertiesOfTablesInRange(
|
||||
ColumnFamilyHandle* column_family, const Range* range, std::size_t n,
|
||||
TablePropertiesCollection* props) override;
|
||||
|
||||
|
||||
// ---- End of implementations of the DB interface ----
|
||||
SystemClock* GetSystemClock() const;
|
||||
|
||||
@@ -1149,6 +1140,8 @@ class DBImpl : public DB {
|
||||
|
||||
void TEST_UnlockMutex();
|
||||
|
||||
InstrumentedMutex* TEST_Mutex() { return &mutex_; }
|
||||
|
||||
void TEST_SignalAllBgCv();
|
||||
|
||||
// REQUIRES: mutex locked
|
||||
@@ -1406,7 +1399,8 @@ 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(bool db_mutex_already_held);
|
||||
Status WriteOptionsFile(const WriteOptions& write_options,
|
||||
bool db_mutex_already_held);
|
||||
|
||||
Status CompactRangeInternal(const CompactRangeOptions& options,
|
||||
ColumnFamilyHandle* column_family,
|
||||
@@ -1532,7 +1526,8 @@ class DBImpl : public DB {
|
||||
virtual bool OwnTablesAndLogs() const { return true; }
|
||||
|
||||
// Setup DB identity file, and write DB ID to manifest if necessary.
|
||||
Status SetupDBId(bool read_only, RecoveryContext* recovery_ctx);
|
||||
Status SetupDBId(const WriteOptions& write_options, 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);
|
||||
|
||||
@@ -1659,7 +1654,8 @@ class DBImpl : public DB {
|
||||
return w;
|
||||
}
|
||||
Status ClearWriter() {
|
||||
Status s = writer->WriteBuffer();
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
Status s = writer->WriteBuffer(WriteOptions());
|
||||
delete writer;
|
||||
writer = nullptr;
|
||||
return s;
|
||||
@@ -1835,12 +1831,15 @@ class DBImpl : public DB {
|
||||
const Status CreateArchivalDirectory();
|
||||
|
||||
// Create a column family, without some of the follow-up work yet
|
||||
Status CreateColumnFamilyImpl(const ColumnFamilyOptions& cf_options,
|
||||
Status CreateColumnFamilyImpl(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
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);
|
||||
@@ -1872,7 +1871,8 @@ class DBImpl : public DB {
|
||||
void ReleaseFileNumberFromPendingOutputs(
|
||||
std::unique_ptr<std::list<uint64_t>::iterator>& v);
|
||||
|
||||
IOStatus SyncClosedLogs(JobContext* job_context, VersionEdit* synced_wals,
|
||||
IOStatus SyncClosedLogs(const WriteOptions& write_options,
|
||||
JobContext* job_context, VersionEdit* synced_wals,
|
||||
bool error_recovery_in_prog);
|
||||
|
||||
// Flush the in-memory write buffer to storage. Switches to a new
|
||||
@@ -2058,12 +2058,10 @@ class DBImpl : public DB {
|
||||
WriteBatch* tmp_batch, WriteBatch** merged_batch,
|
||||
size_t* write_with_wal, WriteBatch** to_be_cached_state);
|
||||
|
||||
// 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,
|
||||
IOStatus WriteToWAL(const WriteBatch& merged_batch,
|
||||
const WriteOptions& write_options,
|
||||
log::Writer* log_writer, uint64_t* log_used,
|
||||
uint64_t* log_size,
|
||||
LogFileNumberSize& log_file_number_size);
|
||||
|
||||
IOStatus WriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
@@ -2175,7 +2173,9 @@ class DBImpl : public DB {
|
||||
// Cancel scheduled periodic tasks
|
||||
Status CancelPeriodicTaskScheduler();
|
||||
|
||||
Status RegisterRecordSeqnoTimeWorker(bool is_new_db);
|
||||
Status RegisterRecordSeqnoTimeWorker(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
bool is_new_db);
|
||||
|
||||
void PrintStatistics();
|
||||
|
||||
@@ -2203,7 +2203,9 @@ 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, VersionEdit* edit);
|
||||
Status ApplyWALToManifest(const ReadOptions& read_options,
|
||||
const WriteOptions& write_options,
|
||||
VersionEdit* edit);
|
||||
// WALs with log number up to up_to are not synced successfully.
|
||||
void MarkLogsNotSynced(uint64_t up_to);
|
||||
|
||||
@@ -2275,8 +2277,9 @@ class DBImpl : public DB {
|
||||
size_t GetWalPreallocateBlockSize(uint64_t write_buffer_size) const;
|
||||
Env::WriteLifeTimeHint CalculateWALWriteHint() { return Env::WLTH_SHORT; }
|
||||
|
||||
IOStatus CreateWAL(uint64_t log_file_num, uint64_t recycle_log_number,
|
||||
size_t preallocate_block_size, log::Writer** new_log);
|
||||
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);
|
||||
|
||||
// Validate self-consistency of DB options
|
||||
static Status ValidateOptions(const DBOptions& db_options);
|
||||
@@ -2811,17 +2814,16 @@ class GetWithTimestampReadCallback : public ReadCallback {
|
||||
}
|
||||
};
|
||||
|
||||
extern Options SanitizeOptions(const std::string& db, const Options& src,
|
||||
bool read_only = false,
|
||||
Status* logger_creation_s = nullptr);
|
||||
Options SanitizeOptions(const std::string& db, const Options& src,
|
||||
bool read_only = false,
|
||||
Status* logger_creation_s = nullptr);
|
||||
|
||||
extern DBOptions SanitizeOptions(const std::string& db, const DBOptions& src,
|
||||
bool read_only = false,
|
||||
Status* logger_creation_s = nullptr);
|
||||
DBOptions SanitizeOptions(const std::string& db, const DBOptions& src,
|
||||
bool read_only = false,
|
||||
Status* logger_creation_s = nullptr);
|
||||
|
||||
extern CompressionType GetCompressionFlush(
|
||||
const ImmutableCFOptions& ioptions,
|
||||
const MutableCFOptions& mutable_cf_options);
|
||||
CompressionType GetCompressionFlush(const ImmutableCFOptions& ioptions,
|
||||
const MutableCFOptions& mutable_cf_options);
|
||||
|
||||
// Return the earliest log file to keep after the memtable flush is
|
||||
// finalized.
|
||||
@@ -2829,13 +2831,13 @@ extern CompressionType GetCompressionFlush(
|
||||
// `memtables_to_flush`) will be flushed and thus will not depend on any WAL
|
||||
// file.
|
||||
// The function is only applicable to 2pc mode.
|
||||
extern uint64_t PrecomputeMinLogNumberToKeep2PC(
|
||||
uint64_t PrecomputeMinLogNumberToKeep2PC(
|
||||
VersionSet* vset, const ColumnFamilyData& cfd_to_flush,
|
||||
const autovector<VersionEdit*>& edit_list,
|
||||
const autovector<MemTable*>& memtables_to_flush,
|
||||
LogsWithPrepTracker* prep_tracker);
|
||||
// For atomic flush.
|
||||
extern uint64_t PrecomputeMinLogNumberToKeep2PC(
|
||||
uint64_t PrecomputeMinLogNumberToKeep2PC(
|
||||
VersionSet* vset, const autovector<ColumnFamilyData*>& cfds_to_flush,
|
||||
const autovector<autovector<VersionEdit*>>& edit_lists,
|
||||
const autovector<const autovector<MemTable*>*>& memtables_to_flush,
|
||||
@@ -2843,21 +2845,21 @@ extern uint64_t PrecomputeMinLogNumberToKeep2PC(
|
||||
|
||||
// In non-2PC mode, WALs with log number < the returned number can be
|
||||
// deleted after the cfd_to_flush column family is flushed successfully.
|
||||
extern uint64_t PrecomputeMinLogNumberToKeepNon2PC(
|
||||
uint64_t PrecomputeMinLogNumberToKeepNon2PC(
|
||||
VersionSet* vset, const ColumnFamilyData& cfd_to_flush,
|
||||
const autovector<VersionEdit*>& edit_list);
|
||||
// For atomic flush.
|
||||
extern uint64_t PrecomputeMinLogNumberToKeepNon2PC(
|
||||
uint64_t PrecomputeMinLogNumberToKeepNon2PC(
|
||||
VersionSet* vset, const autovector<ColumnFamilyData*>& cfds_to_flush,
|
||||
const autovector<autovector<VersionEdit*>>& edit_lists);
|
||||
|
||||
// `cfd_to_flush` is the column family whose memtable will be flushed and thus
|
||||
// will not depend on any WAL file. nullptr means no memtable is being flushed.
|
||||
// The function is only applicable to 2pc mode.
|
||||
extern uint64_t FindMinPrepLogReferencedByMemTable(
|
||||
uint64_t FindMinPrepLogReferencedByMemTable(
|
||||
VersionSet* vset, const autovector<MemTable*>& memtables_to_flush);
|
||||
// For atomic flush.
|
||||
extern uint64_t FindMinPrepLogReferencedByMemTable(
|
||||
uint64_t FindMinPrepLogReferencedByMemTable(
|
||||
VersionSet* vset,
|
||||
const autovector<const autovector<MemTable*>*>& memtables_to_flush);
|
||||
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
#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"
|
||||
@@ -112,7 +116,8 @@ bool DBImpl::ShouldRescheduleFlushRequestToRetainUDT(
|
||||
return true;
|
||||
}
|
||||
|
||||
IOStatus DBImpl::SyncClosedLogs(JobContext* job_context,
|
||||
IOStatus DBImpl::SyncClosedLogs(const WriteOptions& write_options,
|
||||
JobContext* job_context,
|
||||
VersionEdit* synced_wals,
|
||||
bool error_recovery_in_prog) {
|
||||
TEST_SYNC_POINT("DBImpl::SyncClosedLogs:Start");
|
||||
@@ -143,7 +148,13 @@ IOStatus DBImpl::SyncClosedLogs(JobContext* job_context,
|
||||
if (error_recovery_in_prog) {
|
||||
log->file()->reset_seen_error();
|
||||
}
|
||||
io_s = log->file()->Sync(immutable_db_options_.use_fsync);
|
||||
|
||||
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);
|
||||
if (!io_s.ok()) {
|
||||
break;
|
||||
}
|
||||
@@ -152,16 +163,21 @@ IOStatus DBImpl::SyncClosedLogs(JobContext* job_context,
|
||||
if (error_recovery_in_prog) {
|
||||
log->file()->reset_seen_error();
|
||||
}
|
||||
io_s = log->Close();
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
io_s = log->Close(WriteOptions());
|
||||
if (!io_s.ok()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (io_s.ok()) {
|
||||
io_s = directories_.GetWalDir()->FsyncWithDirOptions(
|
||||
IOOptions(), nullptr,
|
||||
DirFsyncOptions(DirFsyncOptions::FsyncReason::kNewFileSynced));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::SyncClosedLogs:BeforeReLock",
|
||||
@@ -199,6 +215,8 @@ 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
|
||||
@@ -265,13 +283,12 @@ Status DBImpl::FlushMemTableToOutputFile(
|
||||
VersionEdit synced_wals;
|
||||
bool error_recovery_in_prog = error_handler_.IsRecoveryInProgress();
|
||||
mutex_.Unlock();
|
||||
log_io_s =
|
||||
SyncClosedLogs(job_context, &synced_wals, error_recovery_in_prog);
|
||||
log_io_s = SyncClosedLogs(write_options, job_context, &synced_wals,
|
||||
error_recovery_in_prog);
|
||||
mutex_.Lock();
|
||||
if (log_io_s.ok() && synced_wals.IsWalAddition()) {
|
||||
const ReadOptions read_options(Env::IOActivity::kFlush);
|
||||
log_io_s =
|
||||
status_to_io_status(ApplyWALToManifest(read_options, &synced_wals));
|
||||
log_io_s = status_to_io_status(
|
||||
ApplyWALToManifest(read_options, write_options, &synced_wals));
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::FlushMemTableToOutputFile:CommitWal:1",
|
||||
nullptr);
|
||||
}
|
||||
@@ -465,6 +482,8 @@ 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) {
|
||||
@@ -552,13 +571,12 @@ Status DBImpl::AtomicFlushMemTablesToOutputFiles(
|
||||
VersionEdit synced_wals;
|
||||
bool error_recovery_in_prog = error_handler_.IsRecoveryInProgress();
|
||||
mutex_.Unlock();
|
||||
log_io_s =
|
||||
SyncClosedLogs(job_context, &synced_wals, error_recovery_in_prog);
|
||||
log_io_s = SyncClosedLogs(write_options, job_context, &synced_wals,
|
||||
error_recovery_in_prog);
|
||||
mutex_.Lock();
|
||||
if (log_io_s.ok() && synced_wals.IsWalAddition()) {
|
||||
const ReadOptions read_options(Env::IOActivity::kFlush);
|
||||
log_io_s =
|
||||
status_to_io_status(ApplyWALToManifest(read_options, &synced_wals));
|
||||
log_io_s = status_to_io_status(
|
||||
ApplyWALToManifest(read_options, write_options, &synced_wals));
|
||||
}
|
||||
|
||||
if (!log_io_s.ok() && !log_io_s.IsShutdownInProgress() &&
|
||||
@@ -653,9 +671,14 @@ Status DBImpl::AtomicFlushMemTablesToOutputFiles(
|
||||
// Sync on all distinct output directories.
|
||||
for (auto dir : distinct_output_dirs) {
|
||||
if (dir != nullptr) {
|
||||
Status error_status = dir->FsyncWithDirOptions(
|
||||
IOOptions(), nullptr,
|
||||
DirFsyncOptions(DirFsyncOptions::FsyncReason::kNewFileSynced));
|
||||
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));
|
||||
}
|
||||
if (!error_status.ok()) {
|
||||
s = error_status;
|
||||
break;
|
||||
@@ -1049,8 +1072,10 @@ Status DBImpl::IncreaseFullHistoryTsLowImpl(ColumnFamilyData* cfd,
|
||||
edit.SetColumnFamily(cfd->GetID());
|
||||
edit.SetFullHistoryTsLow(ts_low);
|
||||
|
||||
// TODO: plumb Env::IOActivity
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::IncreaseFullHistoryTsLowImpl:BeforeEdit",
|
||||
&edit);
|
||||
|
||||
@@ -1064,7 +1089,7 @@ Status DBImpl::IncreaseFullHistoryTsLowImpl(ColumnFamilyData* cfd,
|
||||
}
|
||||
|
||||
Status s = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
|
||||
read_options, &edit, &mutex_,
|
||||
read_options, write_options, &edit, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
@@ -1115,7 +1140,7 @@ Status DBImpl::CompactRangeInternal(const CompactRangeOptions& options,
|
||||
// TODO(ajkr): We could also optimize away the flush in certain cases where
|
||||
// one/both sides of the interval are unbounded. But it requires more
|
||||
// changes to RangesOverlapWithMemtables.
|
||||
Range range(*begin, *end);
|
||||
UserKeyRange range(*begin, *end);
|
||||
SuperVersion* super_version = cfd->GetReferencedSuperVersion(this);
|
||||
s = cfd->RangesOverlapWithMemtables(
|
||||
{range}, super_version, immutable_db_options_.allow_data_in_errors,
|
||||
@@ -1394,10 +1419,9 @@ Status DBImpl::CompactFiles(const CompactionOptions& compact_options,
|
||||
|
||||
// Perform CompactFiles
|
||||
TEST_SYNC_POINT("TestCompactFiles::IngestExternalFile2");
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"TestCompactFiles:PausingManualCompaction:3",
|
||||
reinterpret_cast<void*>(
|
||||
const_cast<std::atomic<int>*>(&manual_compaction_paused_)));
|
||||
TEST_SYNC_POINT_CALLBACK("TestCompactFiles:PausingManualCompaction:3",
|
||||
static_cast<void*>(const_cast<std::atomic<int>*>(
|
||||
&manual_compaction_paused_)));
|
||||
{
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
auto* current = cfd->current();
|
||||
@@ -1670,7 +1694,7 @@ Status DBImpl::PauseBackgroundWork() {
|
||||
Status DBImpl::ContinueBackgroundWork() {
|
||||
InstrumentedMutexLock guard_lock(&mutex_);
|
||||
if (bg_work_paused_ == 0) {
|
||||
return Status::InvalidArgument();
|
||||
return Status::InvalidArgument("Background work already unpaused");
|
||||
}
|
||||
assert(bg_work_paused_ > 0);
|
||||
assert(bg_compaction_paused_ > 0);
|
||||
@@ -1754,6 +1778,7 @@ 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);
|
||||
|
||||
@@ -1870,9 +1895,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, &edit,
|
||||
&mutex_, directories_.GetDbDir());
|
||||
Status status = versions_->LogAndApply(cfd, mutable_cf_options,
|
||||
read_options, write_options, &edit,
|
||||
&mutex_, directories_.GetDbDir());
|
||||
|
||||
cfd->compaction_picker()->UnregisterCompaction(c.get());
|
||||
c.reset();
|
||||
@@ -3019,8 +3044,8 @@ void DBImpl::SchedulePendingPurge(std::string fname, std::string dir_to_sync,
|
||||
}
|
||||
|
||||
void DBImpl::BGWorkFlush(void* arg) {
|
||||
FlushThreadArg fta = *(reinterpret_cast<FlushThreadArg*>(arg));
|
||||
delete reinterpret_cast<FlushThreadArg*>(arg);
|
||||
FlushThreadArg fta = *(static_cast<FlushThreadArg*>(arg));
|
||||
delete static_cast<FlushThreadArg*>(arg);
|
||||
|
||||
IOSTATS_SET_THREAD_POOL_ID(fta.thread_pri_);
|
||||
TEST_SYNC_POINT("DBImpl::BGWorkFlush");
|
||||
@@ -3029,8 +3054,8 @@ void DBImpl::BGWorkFlush(void* arg) {
|
||||
}
|
||||
|
||||
void DBImpl::BGWorkCompaction(void* arg) {
|
||||
CompactionArg ca = *(reinterpret_cast<CompactionArg*>(arg));
|
||||
delete reinterpret_cast<CompactionArg*>(arg);
|
||||
CompactionArg ca = *(static_cast<CompactionArg*>(arg));
|
||||
delete static_cast<CompactionArg*>(arg);
|
||||
IOSTATS_SET_THREAD_POOL_ID(Env::Priority::LOW);
|
||||
TEST_SYNC_POINT("DBImpl::BGWorkCompaction");
|
||||
auto prepicked_compaction =
|
||||
@@ -3054,12 +3079,12 @@ void DBImpl::BGWorkBottomCompaction(void* arg) {
|
||||
void DBImpl::BGWorkPurge(void* db) {
|
||||
IOSTATS_SET_THREAD_POOL_ID(Env::Priority::HIGH);
|
||||
TEST_SYNC_POINT("DBImpl::BGWorkPurge:start");
|
||||
reinterpret_cast<DBImpl*>(db)->BackgroundCallPurge();
|
||||
static_cast<DBImpl*>(db)->BackgroundCallPurge();
|
||||
TEST_SYNC_POINT("DBImpl::BGWorkPurge:end");
|
||||
}
|
||||
|
||||
void DBImpl::UnscheduleCompactionCallback(void* arg) {
|
||||
CompactionArg* ca_ptr = reinterpret_cast<CompactionArg*>(arg);
|
||||
CompactionArg* ca_ptr = static_cast<CompactionArg*>(arg);
|
||||
Env::Priority compaction_pri = ca_ptr->compaction_pri_;
|
||||
if (Env::Priority::BOTTOM == compaction_pri) {
|
||||
// Decrement bg_bottom_compaction_scheduled_ if priority is BOTTOM
|
||||
@@ -3069,7 +3094,7 @@ void DBImpl::UnscheduleCompactionCallback(void* arg) {
|
||||
ca_ptr->db->bg_compaction_scheduled_--;
|
||||
}
|
||||
CompactionArg ca = *(ca_ptr);
|
||||
delete reinterpret_cast<CompactionArg*>(arg);
|
||||
delete static_cast<CompactionArg*>(arg);
|
||||
if (ca.prepicked_compaction != nullptr) {
|
||||
// if it's a manual compaction, set status to ManualCompactionPaused
|
||||
if (ca.prepicked_compaction->manual_compaction_state) {
|
||||
@@ -3089,14 +3114,14 @@ void DBImpl::UnscheduleCompactionCallback(void* arg) {
|
||||
|
||||
void DBImpl::UnscheduleFlushCallback(void* arg) {
|
||||
// Decrement bg_flush_scheduled_ in flush callback
|
||||
reinterpret_cast<FlushThreadArg*>(arg)->db_->bg_flush_scheduled_--;
|
||||
Env::Priority flush_pri = reinterpret_cast<FlushThreadArg*>(arg)->thread_pri_;
|
||||
static_cast<FlushThreadArg*>(arg)->db_->bg_flush_scheduled_--;
|
||||
Env::Priority flush_pri = static_cast<FlushThreadArg*>(arg)->thread_pri_;
|
||||
if (Env::Priority::LOW == flush_pri) {
|
||||
TEST_SYNC_POINT("DBImpl::UnscheduleLowFlushCallback");
|
||||
} else if (Env::Priority::HIGH == flush_pri) {
|
||||
TEST_SYNC_POINT("DBImpl::UnscheduleHighFlushCallback");
|
||||
}
|
||||
delete reinterpret_cast<FlushThreadArg*>(arg);
|
||||
delete static_cast<FlushThreadArg*>(arg);
|
||||
TEST_SYNC_POINT("DBImpl::UnscheduleFlushCallback");
|
||||
}
|
||||
|
||||
@@ -3480,6 +3505,7 @@ 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;
|
||||
@@ -3692,7 +3718,7 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
}
|
||||
status = versions_->LogAndApply(
|
||||
c->column_family_data(), *c->mutable_cf_options(), read_options,
|
||||
c->edit(), &mutex_, directories_.GetDbDir(),
|
||||
write_options, c->edit(), &mutex_, directories_.GetDbDir(),
|
||||
/*new_descriptor_log=*/false, /*column_family_options=*/nullptr,
|
||||
[&c, &compaction_released](const Status& s) {
|
||||
c->ReleaseCompactionFiles(s);
|
||||
@@ -3766,7 +3792,7 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
}
|
||||
status = versions_->LogAndApply(
|
||||
c->column_family_data(), *c->mutable_cf_options(), read_options,
|
||||
c->edit(), &mutex_, directories_.GetDbDir(),
|
||||
write_options, c->edit(), &mutex_, directories_.GetDbDir(),
|
||||
/*new_descriptor_log=*/false, /*column_family_options=*/nullptr,
|
||||
[&c, &compaction_released](const Status& s) {
|
||||
c->ReleaseCompactionFiles(s);
|
||||
|
||||
@@ -208,11 +208,11 @@ void DBImpl::TEST_SignalAllBgCv() { bg_cv_.SignalAll(); }
|
||||
void* DBImpl::TEST_BeginWrite() {
|
||||
auto w = new WriteThread::Writer();
|
||||
write_thread_.EnterUnbatched(w, &mutex_);
|
||||
return reinterpret_cast<void*>(w);
|
||||
return static_cast<void*>(w);
|
||||
}
|
||||
|
||||
void DBImpl::TEST_EndWrite(void* w) {
|
||||
auto writer = reinterpret_cast<WriteThread::Writer*>(w);
|
||||
auto writer = static_cast<WriteThread::Writer*>(w);
|
||||
write_thread_.ExitUnbatched(writer);
|
||||
delete writer;
|
||||
}
|
||||
|
||||
@@ -61,8 +61,10 @@ 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
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
Status status;
|
||||
VersionEdit edit;
|
||||
JobContext job_context(next_job_id_.fetch_add(1), true);
|
||||
@@ -143,7 +145,7 @@ Status DBImpl::PromoteL0(ColumnFamilyHandle* column_family, int target_level) {
|
||||
}
|
||||
|
||||
status = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
|
||||
read_options, &edit, &mutex_,
|
||||
read_options, write_options, &edit, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
if (status.ok()) {
|
||||
InstallSuperVersionAndScheduleWork(cfd,
|
||||
|
||||
+10
-10
@@ -18,6 +18,7 @@
|
||||
#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"
|
||||
|
||||
@@ -51,7 +52,7 @@ Status DBImpl::DisableFileDeletions() {
|
||||
if (my_disable_delete_obsolete_files == 1) {
|
||||
ROCKS_LOG_INFO(immutable_db_options_.info_log, "File Deletions Disabled");
|
||||
} else {
|
||||
ROCKS_LOG_WARN(immutable_db_options_.info_log,
|
||||
ROCKS_LOG_INFO(immutable_db_options_.info_log,
|
||||
"File Deletions Disabled, but already disabled. Counter: %d",
|
||||
my_disable_delete_obsolete_files);
|
||||
}
|
||||
@@ -66,17 +67,14 @@ Status DBImpl::DisableFileDeletionsWithLock() {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status DBImpl::EnableFileDeletions(bool force) {
|
||||
Status DBImpl::EnableFileDeletions() {
|
||||
// Job id == 0 means that this is not our background process, but rather
|
||||
// user thread
|
||||
JobContext job_context(0);
|
||||
int saved_counter; // initialize on all paths
|
||||
{
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
if (force) {
|
||||
// if force, we need to enable file deletions right away
|
||||
disable_delete_obsolete_files_ = 0;
|
||||
} else if (disable_delete_obsolete_files_ > 0) {
|
||||
if (disable_delete_obsolete_files_ > 0) {
|
||||
--disable_delete_obsolete_files_;
|
||||
}
|
||||
saved_counter = disable_delete_obsolete_files_;
|
||||
@@ -91,7 +89,7 @@ Status DBImpl::EnableFileDeletions(bool force) {
|
||||
PurgeObsoleteFiles(job_context);
|
||||
}
|
||||
} else {
|
||||
ROCKS_LOG_WARN(immutable_db_options_.info_log,
|
||||
ROCKS_LOG_INFO(immutable_db_options_.info_log,
|
||||
"File Deletions Enable, but not really enabled. Counter: %d",
|
||||
saved_counter);
|
||||
}
|
||||
@@ -510,7 +508,8 @@ 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.
|
||||
auto s = w->Close();
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
auto s = w->Close(WriteOptions());
|
||||
s.PermitUncheckedError();
|
||||
}
|
||||
|
||||
@@ -925,7 +924,8 @@ void DBImpl::SetDBId(std::string&& id, bool read_only,
|
||||
}
|
||||
}
|
||||
|
||||
Status DBImpl::SetupDBId(bool read_only, RecoveryContext* recovery_ctx) {
|
||||
Status DBImpl::SetupDBId(const WriteOptions& write_options, 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
|
||||
@@ -958,7 +958,7 @@ Status DBImpl::SetupDBId(bool read_only, RecoveryContext* recovery_ctx) {
|
||||
}
|
||||
// Persist it to IDENTITY file if allowed
|
||||
if (!read_only) {
|
||||
s = SetIdentityFile(env_, dbname_, db_id_);
|
||||
s = SetIdentityFile(write_options, env_, dbname_, db_id_);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
+64
-34
@@ -21,6 +21,7 @@
|
||||
#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"
|
||||
@@ -309,7 +310,8 @@ Status DBImpl::ValidateOptions(const DBOptions& db_options) {
|
||||
|
||||
Status DBImpl::NewDB(std::vector<std::string>* new_filenames) {
|
||||
VersionEdit new_db;
|
||||
Status s = SetIdentityFile(env_, dbname_);
|
||||
const WriteOptions write_options(Env::IOActivity::kDBOpen);
|
||||
Status s = SetIdentityFile(write_options, env_, dbname_);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
@@ -339,20 +341,23 @@ 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 */, immutable_db_options_.listeners,
|
||||
nullptr, tmp_set.Contains(FileType::kDescriptorFile),
|
||||
io_tracer_, nullptr /* stats */,
|
||||
Histograms::HISTOGRAM_ENUM_MAX /* hist_type */,
|
||||
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(record);
|
||||
s = log.AddRecord(write_options, record);
|
||||
if (s.ok()) {
|
||||
s = SyncManifest(&immutable_db_options_, log.file());
|
||||
s = SyncManifest(&immutable_db_options_, write_options, log.file());
|
||||
}
|
||||
}
|
||||
if (s.ok()) {
|
||||
// Make "CURRENT" file that points to the new manifest file.
|
||||
s = SetCurrentFile(fs_.get(), dbname_, 1, directories_.GetDbDir());
|
||||
s = SetCurrentFile(write_options, fs_.get(), dbname_, 1,
|
||||
directories_.GetDbDir());
|
||||
if (new_filenames) {
|
||||
new_filenames->emplace_back(
|
||||
manifest.substr(manifest.find_last_of("/\\") + 1));
|
||||
@@ -418,6 +423,7 @@ 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);
|
||||
@@ -642,7 +648,7 @@ Status DBImpl::Recover(
|
||||
}
|
||||
}
|
||||
}
|
||||
s = SetupDBId(read_only, recovery_ctx);
|
||||
s = SetupDBId(write_options, 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);
|
||||
@@ -872,8 +878,9 @@ Status DBImpl::PersistentStatsProcessFormatVersion() {
|
||||
if (s.ok()) {
|
||||
ColumnFamilyOptions cfo;
|
||||
OptimizeForPersistentStats(&cfo);
|
||||
s = CreateColumnFamilyImpl(cfo, kPersistentStatsColumnFamilyName,
|
||||
&handle);
|
||||
s = CreateColumnFamilyImpl(ReadOptions(Env::IOActivity::kDBOpen),
|
||||
WriteOptions(Env::IOActivity::kDBOpen), cfo,
|
||||
kPersistentStatsColumnFamilyName, &handle);
|
||||
}
|
||||
if (s.ok()) {
|
||||
persist_stats_cf_handle_ = static_cast<ColumnFamilyHandleImpl*>(handle);
|
||||
@@ -895,6 +902,7 @@ 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;
|
||||
@@ -926,7 +934,9 @@ Status DBImpl::InitPersistStatsColumnFamily() {
|
||||
ColumnFamilyHandle* handle = nullptr;
|
||||
ColumnFamilyOptions cfo;
|
||||
OptimizeForPersistentStats(&cfo);
|
||||
s = CreateColumnFamilyImpl(cfo, kPersistentStatsColumnFamilyName, &handle);
|
||||
s = CreateColumnFamilyImpl(ReadOptions(Env::IOActivity::kDBOpen),
|
||||
WriteOptions(Env::IOActivity::kDBOpen), cfo,
|
||||
kPersistentStatsColumnFamilyName, &handle);
|
||||
persist_stats_cf_handle_ = static_cast<ColumnFamilyHandleImpl*>(handle);
|
||||
mutex_.Lock();
|
||||
}
|
||||
@@ -937,9 +947,12 @@ Status DBImpl::LogAndApplyForRecovery(const RecoveryContext& recovery_ctx) {
|
||||
mutex_.AssertHeld();
|
||||
assert(versions_->descriptor_log_ == nullptr);
|
||||
const ReadOptions read_options(Env::IOActivity::kDBOpen);
|
||||
Status s = versions_->LogAndApply(
|
||||
recovery_ctx.cfds_, recovery_ctx.mutable_cf_opts_, read_options,
|
||||
recovery_ctx.edit_lists_, &mutex_, directories_.GetDbDir());
|
||||
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());
|
||||
if (s.ok() && !(recovery_ctx.files_to_delete_.empty())) {
|
||||
mutex_.Unlock();
|
||||
for (const auto& stale_sst_file : recovery_ctx.files_to_delete_) {
|
||||
@@ -1665,9 +1678,11 @@ 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, cfd->internal_comparator(),
|
||||
cfd->int_tbl_prop_collector_factories(),
|
||||
*cfd->ioptions(), mutable_cf_options, read_option, write_option,
|
||||
cfd->internal_comparator(), cfd->internal_tbl_prop_coll_factories(),
|
||||
GetCompressionFlush(*cfd->ioptions(), mutable_cf_options),
|
||||
mutable_cf_options.compression_opts, cfd->GetID(), cfd->GetName(),
|
||||
0 /* level */, false /* is_bottommost */,
|
||||
@@ -1677,16 +1692,15 @@ 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_, read_option, cfd->table_cache(),
|
||||
iter.get(), std::move(range_del_iters), &meta, &blob_file_additions,
|
||||
file_options_for_compaction_, 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, Env::IO_HIGH,
|
||||
empty_seqno_to_time_mapping, &event_logger_, job_id,
|
||||
nullptr /* table_properties */, write_hint,
|
||||
nullptr /*full_history_ts_low*/, &blob_callback_, version,
|
||||
&num_input_entries);
|
||||
@@ -1888,7 +1902,8 @@ Status DB::OpenAndTrimHistory(
|
||||
return s;
|
||||
}
|
||||
|
||||
IOStatus DBImpl::CreateWAL(uint64_t log_file_num, uint64_t recycle_log_number,
|
||||
IOStatus DBImpl::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 io_s;
|
||||
@@ -1922,14 +1937,15 @@ IOStatus DBImpl::CreateWAL(uint64_t log_file_num, uint64_t recycle_log_number,
|
||||
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 */, listeners,
|
||||
nullptr, tmp_set.Contains(FileType::kWalFile),
|
||||
immutable_db_options_.clock, io_tracer_, nullptr /* stats */,
|
||||
Histograms::HISTOGRAM_ENUM_MAX /* hist_type */, 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();
|
||||
io_s = (*new_log)->AddCompressionTypeRecord(write_options);
|
||||
}
|
||||
return io_s;
|
||||
}
|
||||
@@ -1938,6 +1954,9 @@ 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;
|
||||
@@ -2014,7 +2033,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(new_log_number, 0 /*recycle_log_number*/,
|
||||
s = impl->CreateWAL(write_options, new_log_number, 0 /*recycle_log_number*/,
|
||||
preallocate_block_size, &new_log);
|
||||
if (s.ok()) {
|
||||
InstrumentedMutexLock wl(&impl->log_write_mutex_);
|
||||
@@ -2039,21 +2058,25 @@ 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, log_writer, &log_used, &log_size,
|
||||
Env::IO_TOTAL, log_file_number_size);
|
||||
s = impl->WriteToWAL(empty_batch, write_options, log_writer, &log_used,
|
||||
&log_size, log_file_number_size);
|
||||
if (s.ok()) {
|
||||
// Need to fsync, otherwise it might get lost after a power reset.
|
||||
s = impl->FlushWAL(false);
|
||||
s = impl->FlushWAL(write_options, false);
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::Open::BeforeSyncWAL", /*arg=*/&s);
|
||||
IOOptions opts;
|
||||
if (s.ok()) {
|
||||
s = log_writer->file()->Sync(impl->immutable_db_options_.use_fsync);
|
||||
s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = log_writer->file()->Sync(opts,
|
||||
impl->immutable_db_options_.use_fsync);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2084,7 +2107,8 @@ 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(cf.options, cf.name, &handle);
|
||||
s = impl->CreateColumnFamilyImpl(read_options, write_options,
|
||||
cf.options, cf.name, &handle);
|
||||
impl->mutex_.Lock();
|
||||
if (s.ok()) {
|
||||
handles->push_back(handle);
|
||||
@@ -2136,7 +2160,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(true /*db_mutex_already_held*/);
|
||||
impl->WriteOptionsFile(write_options, true /*db_mutex_already_held*/);
|
||||
*dbptr = impl;
|
||||
impl->opened_successfully_ = true;
|
||||
impl->DeleteObsoleteFiles();
|
||||
@@ -2236,12 +2260,17 @@ 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(false);
|
||||
s = impl->FlushWAL(write_options, 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;
|
||||
s = log_writer->file()->Sync(impl->immutable_db_options_.use_fsync);
|
||||
IOOptions opts;
|
||||
s = WritableFileWriter::PrepareIOOptions(write_options, opts);
|
||||
if (s.ok()) {
|
||||
s = log_writer->file()->Sync(opts,
|
||||
impl->immutable_db_options_.use_fsync);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s.ok() && !persist_options_status.ok()) {
|
||||
@@ -2258,7 +2287,8 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
s = impl->StartPeriodicTaskScheduler();
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = impl->RegisterRecordSeqnoTimeWorker(recovery_ctx.is_new_db_);
|
||||
s = impl->RegisterRecordSeqnoTimeWorker(read_options, write_options,
|
||||
recovery_ctx.is_new_db_);
|
||||
}
|
||||
impl->options_mutex_.Unlock();
|
||||
if (!s.ok()) {
|
||||
|
||||
@@ -169,8 +169,7 @@ Iterator* DBImplReadOnly::NewIterator(const ReadOptions& _read_options,
|
||||
SequenceNumber latest_snapshot = versions_->LastSequence();
|
||||
SequenceNumber read_seq =
|
||||
read_options.snapshot != nullptr
|
||||
? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot)
|
||||
->number_
|
||||
? static_cast<const SnapshotImpl*>(read_options.snapshot)->number_
|
||||
: latest_snapshot;
|
||||
ReadCallback* read_callback = nullptr; // No read callback provided.
|
||||
auto db_iter = NewArenaWrappedDbIterator(
|
||||
@@ -216,8 +215,7 @@ Status DBImplReadOnly::NewIterators(
|
||||
SequenceNumber latest_snapshot = versions_->LastSequence();
|
||||
SequenceNumber read_seq =
|
||||
read_options.snapshot != nullptr
|
||||
? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot)
|
||||
->number_
|
||||
? static_cast<const SnapshotImpl*>(read_options.snapshot)->number_
|
||||
: latest_snapshot;
|
||||
|
||||
autovector<std::tuple<ColumnFamilyData*, SuperVersion*>> cfd_to_sv;
|
||||
|
||||
@@ -31,18 +31,17 @@ class DBImplReadOnly : public DBImpl {
|
||||
// TODO: Implement ReadOnly MultiGet?
|
||||
|
||||
using DBImpl::NewIterator;
|
||||
virtual Iterator* NewIterator(const ReadOptions& _read_options,
|
||||
ColumnFamilyHandle* column_family) override;
|
||||
Iterator* NewIterator(const ReadOptions& _read_options,
|
||||
ColumnFamilyHandle* column_family) override;
|
||||
|
||||
virtual Status NewIterators(
|
||||
const ReadOptions& options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_families,
|
||||
std::vector<Iterator*>* iterators) override;
|
||||
Status NewIterators(const ReadOptions& options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_families,
|
||||
std::vector<Iterator*>* iterators) override;
|
||||
|
||||
using DBImpl::Put;
|
||||
virtual Status Put(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/, const Slice& /*value*/) override {
|
||||
Status Put(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/, const Slice& /*key*/,
|
||||
const Slice& /*value*/) override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
|
||||
@@ -59,37 +58,36 @@ class DBImplReadOnly : public DBImpl {
|
||||
}
|
||||
|
||||
using DBImpl::Merge;
|
||||
virtual Status Merge(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/, const Slice& /*value*/) override {
|
||||
Status Merge(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/, const Slice& /*key*/,
|
||||
const Slice& /*value*/) override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
using DBImpl::Delete;
|
||||
virtual Status Delete(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/) override {
|
||||
Status Delete(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/) override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
using DBImpl::SingleDelete;
|
||||
virtual Status SingleDelete(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/) override {
|
||||
Status SingleDelete(const WriteOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*key*/) override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
virtual Status Write(const WriteOptions& /*options*/,
|
||||
WriteBatch* /*updates*/) override {
|
||||
Status Write(const WriteOptions& /*options*/,
|
||||
WriteBatch* /*updates*/) override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
using DBImpl::CompactRange;
|
||||
virtual Status CompactRange(const CompactRangeOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice* /*begin*/,
|
||||
const Slice* /*end*/) override {
|
||||
Status CompactRange(const CompactRangeOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice* /*begin*/, const Slice* /*end*/) override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
|
||||
using DBImpl::CompactFiles;
|
||||
virtual Status CompactFiles(
|
||||
Status CompactFiles(
|
||||
const CompactionOptions& /*compact_options*/,
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const std::vector<std::string>& /*input_file_names*/,
|
||||
@@ -99,33 +97,33 @@ class DBImplReadOnly : public DBImpl {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
|
||||
virtual Status DisableFileDeletions() override {
|
||||
Status DisableFileDeletions() override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
|
||||
virtual Status EnableFileDeletions(bool /*force*/) override {
|
||||
Status EnableFileDeletions() override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
virtual Status GetLiveFiles(std::vector<std::string>& ret,
|
||||
uint64_t* manifest_file_size,
|
||||
bool /*flush_memtable*/) override {
|
||||
Status GetLiveFiles(std::vector<std::string>& ret,
|
||||
uint64_t* manifest_file_size,
|
||||
bool /*flush_memtable*/) override {
|
||||
return DBImpl::GetLiveFiles(ret, manifest_file_size,
|
||||
false /* flush_memtable */);
|
||||
}
|
||||
|
||||
using DBImpl::Flush;
|
||||
virtual Status Flush(const FlushOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/) override {
|
||||
Status Flush(const FlushOptions& /*options*/,
|
||||
ColumnFamilyHandle* /*column_family*/) override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
|
||||
using DBImpl::SyncWAL;
|
||||
virtual Status SyncWAL() override {
|
||||
Status SyncWAL() override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
|
||||
using DB::IngestExternalFile;
|
||||
virtual Status IngestExternalFile(
|
||||
Status IngestExternalFile(
|
||||
ColumnFamilyHandle* /*column_family*/,
|
||||
const std::vector<std::string>& /*external_files*/,
|
||||
const IngestExternalFileOptions& /*ingestion_options*/) override {
|
||||
@@ -133,7 +131,7 @@ class DBImplReadOnly : public DBImpl {
|
||||
}
|
||||
|
||||
using DB::CreateColumnFamilyWithImport;
|
||||
virtual Status CreateColumnFamilyWithImport(
|
||||
Status CreateColumnFamilyWithImport(
|
||||
const ColumnFamilyOptions& /*options*/,
|
||||
const std::string& /*column_family_name*/,
|
||||
const ImportColumnFamilyOptions& /*import_options*/,
|
||||
@@ -142,7 +140,7 @@ class DBImplReadOnly : public DBImpl {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
|
||||
virtual Status CreateColumnFamilyWithImport(
|
||||
Status CreateColumnFamilyWithImport(
|
||||
const ColumnFamilyOptions& /*options*/,
|
||||
const std::string& /*column_family_name*/,
|
||||
const ImportColumnFamilyOptions& /*import_options*/,
|
||||
@@ -152,9 +150,9 @@ class DBImplReadOnly : public DBImpl {
|
||||
}
|
||||
|
||||
using DB::ClipColumnFamily;
|
||||
virtual Status ClipColumnFamily(ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*begin*/,
|
||||
const Slice& /*end*/) override {
|
||||
Status ClipColumnFamily(ColumnFamilyHandle* /*column_family*/,
|
||||
const Slice& /*begin*/,
|
||||
const Slice& /*end*/) override {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ class DBImplSecondary : public DBImpl {
|
||||
return Status::NotSupported("Not supported operation in secondary mode.");
|
||||
}
|
||||
|
||||
Status EnableFileDeletions(bool /*force*/) override {
|
||||
Status EnableFileDeletions() override {
|
||||
return Status::NotSupported("Not supported operation in secondary mode.");
|
||||
}
|
||||
|
||||
|
||||
+61
-27
@@ -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
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
const ReadOptions read_options;
|
||||
status = ApplyWALToManifest(read_options, &synced_wals);
|
||||
status = ApplyWALToManifest(read_options, write_options, &synced_wals);
|
||||
}
|
||||
|
||||
// Requesting sync with two_write_queues_ is expected to be very rare. We
|
||||
@@ -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
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
const ReadOptions read_options;
|
||||
w.status = ApplyWALToManifest(read_options, &synced_wals);
|
||||
w.status = ApplyWALToManifest(read_options, write_options, &synced_wals);
|
||||
}
|
||||
write_thread_.ExitAsBatchGroupLeader(wal_write_group, w.status);
|
||||
}
|
||||
@@ -819,6 +819,9 @@ Status DBImpl::PipelinedWriteImpl(const WriteOptions& write_options,
|
||||
}
|
||||
|
||||
if (w.state == WriteThread::STATE_PARALLEL_MEMTABLE_WRITER) {
|
||||
PERF_TIMER_STOP(write_pre_and_post_process_time);
|
||||
PERF_TIMER_GUARD(write_memtable_time);
|
||||
|
||||
assert(w.ShouldWriteToMemtable());
|
||||
ColumnFamilyMemTablesImpl column_family_memtables(
|
||||
versions_->GetColumnFamilySet());
|
||||
@@ -828,6 +831,10 @@ Status DBImpl::PipelinedWriteImpl(const WriteOptions& write_options,
|
||||
0 /*log_number*/, this, true /*concurrent_memtable_writes*/,
|
||||
false /*seq_per_batch*/, 0 /*batch_cnt*/, true /*batch_per_txn*/,
|
||||
write_options.memtable_insert_hint_per_batch);
|
||||
|
||||
PERF_TIMER_STOP(write_memtable_time);
|
||||
PERF_TIMER_START(write_pre_and_post_process_time);
|
||||
|
||||
if (write_thread_.CompleteParallelMemTableWriter(&w)) {
|
||||
MemTableInsertStatusCheck(w.status);
|
||||
versions_->SetLastSequence(w.write_group->last_sequence);
|
||||
@@ -860,6 +867,9 @@ Status DBImpl::UnorderedWriteMemtable(const WriteOptions& write_options,
|
||||
stats->AddDBStats(InternalStats::kIntStatsNumKeysWritten, total_count);
|
||||
RecordTick(stats_, NUMBER_KEYS_WRITTEN, total_count);
|
||||
|
||||
PERF_TIMER_STOP(write_pre_and_post_process_time);
|
||||
PERF_TIMER_GUARD(write_memtable_time);
|
||||
|
||||
ColumnFamilyMemTablesImpl column_family_memtables(
|
||||
versions_->GetColumnFamilySet());
|
||||
w.status = WriteBatchInternal::InsertInto(
|
||||
@@ -871,6 +881,8 @@ Status DBImpl::UnorderedWriteMemtable(const WriteOptions& write_options,
|
||||
if (write_options.disableWAL) {
|
||||
has_unpersisted_data_.store(true, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
PERF_TIMER_START(write_pre_and_post_process_time);
|
||||
}
|
||||
|
||||
size_t pending_cnt = pending_memtable_writes_.fetch_sub(1) - 1;
|
||||
@@ -941,9 +953,13 @@ Status DBImpl::WriteImplWALOnly(
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
PERF_TIMER_STOP(write_pre_and_post_process_time);
|
||||
PERF_TIMER_GUARD(write_delay_time);
|
||||
InstrumentedMutexLock lock(&mutex_);
|
||||
Status status =
|
||||
DelayWrite(/*num_bytes=*/0ull, *write_thread, write_options);
|
||||
PERF_TIMER_STOP(write_delay_time);
|
||||
PERF_TIMER_START(write_pre_and_post_process_time);
|
||||
if (!status.ok()) {
|
||||
WriteThread::WriteGroup write_group;
|
||||
write_thread->EnterAsBatchGroupLeader(&w, &write_group);
|
||||
@@ -1318,9 +1334,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,12 +1359,11 @@ IOStatus DBImpl::WriteToWAL(const WriteBatch& merged_batch,
|
||||
log_write_mutex_.Lock();
|
||||
}
|
||||
IOStatus io_s = log_writer->MaybeAddUserDefinedTimestampSizeRecord(
|
||||
versions_->GetColumnFamiliesTimestampSizeForRecord(),
|
||||
rate_limiter_priority);
|
||||
write_options, versions_->GetColumnFamiliesTimestampSizeForRecord());
|
||||
if (!io_s.ok()) {
|
||||
return io_s;
|
||||
}
|
||||
io_s = log_writer->AddRecord(log_entry, rate_limiter_priority);
|
||||
io_s = log_writer->AddRecord(write_options, log_entry);
|
||||
|
||||
if (UNLIKELY(needs_locking)) {
|
||||
log_write_mutex_.Unlock();
|
||||
@@ -1391,9 +1406,13 @@ IOStatus DBImpl::WriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
WriteBatchInternal::SetSequence(merged_batch, sequence);
|
||||
|
||||
uint64_t log_size;
|
||||
io_s = WriteToWAL(*merged_batch, log_writer, log_used, &log_size,
|
||||
write_group.leader->rate_limiter_priority,
|
||||
log_file_number_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);
|
||||
if (to_be_cached_state) {
|
||||
cached_recoverable_state_ = *to_be_cached_state;
|
||||
cached_recoverable_state_empty_ = false;
|
||||
@@ -1420,10 +1439,17 @@ IOStatus DBImpl::WriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
log_write_mutex_.Lock();
|
||||
}
|
||||
|
||||
for (auto& log : logs_) {
|
||||
io_s = log.writer->file()->Sync(immutable_db_options_.use_fsync);
|
||||
if (!io_s.ok()) {
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1496,9 +1522,13 @@ IOStatus DBImpl::ConcurrentWriteToWAL(
|
||||
assert(log_writer->get_log_number() == log_file_number_size.number);
|
||||
|
||||
uint64_t log_size;
|
||||
io_s = WriteToWAL(*merged_batch, log_writer, log_used, &log_size,
|
||||
write_group.leader->rate_limiter_priority,
|
||||
log_file_number_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);
|
||||
if (to_be_cached_state) {
|
||||
cached_recoverable_state_ = *to_be_cached_state;
|
||||
cached_recoverable_state_empty_ = false;
|
||||
@@ -1563,6 +1593,8 @@ Status DBImpl::WriteRecoverableState() {
|
||||
if (status.ok()) {
|
||||
cached_recoverable_state_.Clear();
|
||||
cached_recoverable_state_empty_ = true;
|
||||
} else {
|
||||
// FIXME: !ok status is untested
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -2060,16 +2092,15 @@ 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 (!cfd->mem()->IsEmpty()) {
|
||||
if (status.ok() && !cfd->mem()->IsEmpty()) {
|
||||
status = SwitchMemtable(cfd, context);
|
||||
}
|
||||
if (cfd->UnrefAndTryDelete()) {
|
||||
cfd = nullptr;
|
||||
}
|
||||
if (!status.ok()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (two_write_queues_) {
|
||||
@@ -2116,8 +2147,10 @@ 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
|
||||
// TODO: plumb Env::IOActivity, Env::IOPriority
|
||||
const ReadOptions read_options;
|
||||
const WriteOptions write_options;
|
||||
|
||||
log::Writer* new_log = nullptr;
|
||||
MemTable* new_mem = nullptr;
|
||||
IOStatus io_s;
|
||||
@@ -2164,8 +2197,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(new_log_number, recycle_log_number, preallocate_block_size,
|
||||
&new_log);
|
||||
io_s = CreateWAL(write_options, new_log_number, recycle_log_number,
|
||||
preallocate_block_size, &new_log);
|
||||
if (s.ok()) {
|
||||
s = io_s;
|
||||
}
|
||||
@@ -2202,7 +2235,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();
|
||||
io_s = cur_log_writer->WriteBuffer(write_options);
|
||||
if (s.ok()) {
|
||||
s = io_s;
|
||||
}
|
||||
@@ -2270,7 +2303,8 @@ Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
VersionEdit wal_deletion;
|
||||
wal_deletion.DeleteWalsBefore(min_wal_number_to_keep);
|
||||
s = versions_->LogAndApplyToDefaultColumnFamily(
|
||||
read_options, &wal_deletion, &mutex_, directories_.GetDbDir());
|
||||
read_options, write_options, &wal_deletion, &mutex_,
|
||||
directories_.GetDbDir());
|
||||
if (!s.ok() && versions_->io_status().IsIOError()) {
|
||||
s = error_handler_.SetBGError(versions_->io_status(),
|
||||
BackgroundErrorReason::kManifestWrite);
|
||||
|
||||
+21
-9
@@ -5,10 +5,9 @@
|
||||
|
||||
#include "db/db_info_dumper.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -99,7 +98,12 @@ void DumpDBFileSummary(const ImmutableDBOptions& options,
|
||||
for (auto& db_path : options.db_paths) {
|
||||
if (dbname.compare(db_path.path) != 0) {
|
||||
s = env->GetChildren(db_path.path, &files);
|
||||
if (!s.ok()) {
|
||||
if (s.IsNotFound() || s.IsPathNotFound()) {
|
||||
Header(options.info_log,
|
||||
"Directory from db_paths/cf_paths does not yet exist: %s\n",
|
||||
db_path.path.c_str());
|
||||
continue;
|
||||
} else if (!s.ok()) {
|
||||
Error(options.info_log, "Error when reading %s dir %s\n",
|
||||
db_path.path.c_str(), s.ToString().c_str());
|
||||
continue;
|
||||
@@ -122,12 +126,18 @@ void DumpDBFileSummary(const ImmutableDBOptions& options,
|
||||
|
||||
// Get wal file in wal_dir
|
||||
const auto& wal_dir = options.GetWalDir(dbname);
|
||||
bool log_wal_info = true;
|
||||
if (!options.IsWalDirSameAsDBPath(dbname)) {
|
||||
s = env->GetChildren(wal_dir, &files);
|
||||
if (!s.ok()) {
|
||||
Error(options.info_log, "Error when reading %s dir %s\n", wal_dir.c_str(),
|
||||
s.ToString().c_str());
|
||||
return;
|
||||
if (s.IsNotFound() || s.IsPathNotFound()) {
|
||||
Header(options.info_log,
|
||||
"Write Ahead Log directory does not yet exist: %s\n",
|
||||
wal_dir.c_str());
|
||||
log_wal_info = false;
|
||||
} else if (!s.ok()) {
|
||||
Error(options.info_log, "Error when reading wal dir %s: %s\n",
|
||||
wal_dir.c_str(), s.ToString().c_str());
|
||||
log_wal_info = false;
|
||||
}
|
||||
wal_info.clear();
|
||||
for (const std::string& file : files) {
|
||||
@@ -147,7 +157,9 @@ void DumpDBFileSummary(const ImmutableDBOptions& options,
|
||||
}
|
||||
}
|
||||
}
|
||||
Header(options.info_log, "Write Ahead Log file in %s: %s\n", wal_dir.c_str(),
|
||||
wal_info.c_str());
|
||||
if (log_wal_info) {
|
||||
Header(options.info_log, "Write Ahead Log file in %s: %s\n",
|
||||
wal_dir.c_str(), wal_info.c_str());
|
||||
}
|
||||
}
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
Loaded 100 of 651 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user