@nxtedition/rocksdb 13.5.12 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.cc +33 -2
- package/binding.gyp +2 -2
- package/chained-batch.js +9 -16
- package/deps/rocksdb/rocksdb/BUCK +18 -1
- package/deps/rocksdb/rocksdb/CMakeLists.txt +10 -3
- package/deps/rocksdb/rocksdb/Makefile +20 -9
- package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +90 -13
- package/deps/rocksdb/rocksdb/cache/clock_cache.cc +88 -75
- package/deps/rocksdb/rocksdb/cache/clock_cache.h +44 -36
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +184 -148
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.h +5 -11
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +116 -47
- package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +1 -1
- package/deps/rocksdb/rocksdb/cache/secondary_cache_adapter.cc +3 -6
- package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.h +1 -1
- package/deps/rocksdb/rocksdb/db/builder.cc +4 -2
- package/deps/rocksdb/rocksdb/db/c.cc +207 -0
- package/deps/rocksdb/rocksdb/db/c_test.c +72 -0
- package/deps/rocksdb/rocksdb/db/column_family.cc +3 -2
- package/deps/rocksdb/rocksdb/db/column_family.h +5 -0
- package/deps/rocksdb/rocksdb/db/compact_files_test.cc +4 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +2 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +51 -38
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +29 -12
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator_test.cc +5 -10
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +566 -366
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +131 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +1 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +7 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +4 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +13 -14
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +12 -7
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +8 -10
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +97 -76
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +11 -14
- package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +1 -1
- package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +8 -0
- package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +16 -3
- package/deps/rocksdb/rocksdb/db/db_basic_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +448 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +22 -20
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +4 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +5 -5
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +7 -3
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +1 -1
- package/deps/rocksdb/rocksdb/db/db_iter.cc +104 -0
- package/deps/rocksdb/rocksdb/db/db_iter.h +4 -11
- package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +331 -58
- package/deps/rocksdb/rocksdb/db/db_memtable_test.cc +129 -0
- package/deps/rocksdb/rocksdb/db/db_sst_test.cc +64 -0
- package/deps/rocksdb/rocksdb/db/db_table_properties_test.cc +40 -0
- package/deps/rocksdb/rocksdb/db/db_test2.cc +25 -15
- package/deps/rocksdb/rocksdb/db/db_test_util.cc +42 -24
- package/deps/rocksdb/rocksdb/db/db_test_util.h +29 -14
- package/deps/rocksdb/rocksdb/db/db_universal_compaction_test.cc +69 -36
- package/deps/rocksdb/rocksdb/db/db_with_timestamp_basic_test.cc +0 -1
- package/deps/rocksdb/rocksdb/db/event_helpers.cc +1 -0
- package/deps/rocksdb/rocksdb/db/experimental.cc +5 -4
- package/deps/rocksdb/rocksdb/db/external_sst_file_basic_test.cc +8 -1
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +275 -79
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.h +23 -5
- package/deps/rocksdb/rocksdb/db/external_sst_file_test.cc +591 -175
- package/deps/rocksdb/rocksdb/db/flush_job.cc +3 -4
- package/deps/rocksdb/rocksdb/db/log_reader.cc +5 -2
- package/deps/rocksdb/rocksdb/db/memtable.cc +84 -35
- package/deps/rocksdb/rocksdb/db/memtable.h +39 -34
- package/deps/rocksdb/rocksdb/db/merge_helper.cc +1 -0
- package/deps/rocksdb/rocksdb/db/merge_operator.cc +1 -1
- package/deps/rocksdb/rocksdb/db/multi_scan.cc +11 -5
- package/deps/rocksdb/rocksdb/db/version_edit.cc +1 -1
- package/deps/rocksdb/rocksdb/db/version_edit.h +1 -1
- package/deps/rocksdb/rocksdb/db/version_edit_handler.cc +34 -14
- package/deps/rocksdb/rocksdb/db/version_edit_handler.h +28 -5
- package/deps/rocksdb/rocksdb/db/version_set.cc +159 -14
- package/deps/rocksdb/rocksdb/db/version_set.h +2 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/CMakeLists.txt +1 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +60 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +16 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compaction_service.h +75 -10
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compression_manager.cc +28 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compression_manager.h +2 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_driver.cc +31 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +50 -2
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_shared_state.h +57 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_stat.h +0 -4
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +266 -35
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +5 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +0 -6
- package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +18 -2
- package/deps/rocksdb/rocksdb/env/env.cc +12 -0
- package/deps/rocksdb/rocksdb/env/env_test.cc +18 -0
- package/deps/rocksdb/rocksdb/env/file_system_tracer.cc +2 -0
- package/deps/rocksdb/rocksdb/env/fs_posix.cc +9 -5
- package/deps/rocksdb/rocksdb/env/io_posix.cc +4 -2
- package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +19 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_compression.h +33 -31
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +42 -9
- package/deps/rocksdb/rocksdb/include/rocksdb/c.h +93 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +43 -49
- package/deps/rocksdb/rocksdb/include/rocksdb/compaction_job_stats.h +4 -3
- package/deps/rocksdb/rocksdb/include/rocksdb/compression_type.h +8 -6
- package/deps/rocksdb/rocksdb/include/rocksdb/data_structure.h +487 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +11 -12
- package/deps/rocksdb/rocksdb/include/rocksdb/env.h +135 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +5 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/iostats_context.h +12 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/iterator.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/ldb_tool.h +8 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/memtablerep.h +12 -8
- package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +3 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/multi_scan.h +19 -9
- package/deps/rocksdb/rocksdb/include/rocksdb/options.h +219 -24
- package/deps/rocksdb/rocksdb/include/rocksdb/point_lock_bench_tool.h +14 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/secondary_cache.h +2 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/slice.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +7 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/status.h +16 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/table.h +16 -4
- package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +13 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/types.h +4 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/universal_compaction.h +0 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/user_defined_index.h +45 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/cache_dump_load.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction.h +6 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction_db.h +21 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
- package/deps/rocksdb/rocksdb/memory/memory_allocator_impl.h +3 -3
- package/deps/rocksdb/rocksdb/memtable/inlineskiplist.h +77 -51
- package/deps/rocksdb/rocksdb/memtable/skiplist.h +10 -13
- package/deps/rocksdb/rocksdb/memtable/skiplistrep.cc +16 -7
- package/deps/rocksdb/rocksdb/memtable/vectorrep.cc +9 -4
- package/deps/rocksdb/rocksdb/monitoring/iostats_context.cc +2 -0
- package/deps/rocksdb/rocksdb/monitoring/statistics.cc +6 -0
- package/deps/rocksdb/rocksdb/options/cf_options.cc +13 -1
- package/deps/rocksdb/rocksdb/options/cf_options.h +6 -2
- package/deps/rocksdb/rocksdb/options/options.cc +2 -0
- package/deps/rocksdb/rocksdb/options/options_helper.cc +9 -8
- package/deps/rocksdb/rocksdb/options/options_settable_test.cc +9 -5
- package/deps/rocksdb/rocksdb/port/mmap.cc +1 -1
- package/deps/rocksdb/rocksdb/port/win/xpress_win.cc +51 -0
- package/deps/rocksdb/rocksdb/port/win/xpress_win.h +4 -0
- package/deps/rocksdb/rocksdb/src.mk +8 -2
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +1125 -765
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +35 -24
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +29 -4
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +732 -256
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +225 -16
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +102 -26
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +2 -75
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +433 -141
- package/deps/rocksdb/rocksdb/table/block_based/block_builder.h +2 -0
- package/deps/rocksdb/rocksdb/table/block_based/flush_block_policy.cc +17 -10
- package/deps/rocksdb/rocksdb/table/block_based/flush_block_policy_impl.h +20 -0
- package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +112 -85
- package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +191 -36
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +2 -2
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/user_defined_index_wrapper.h +108 -31
- package/deps/rocksdb/rocksdb/table/external_table.cc +7 -3
- package/deps/rocksdb/rocksdb/table/format.cc +6 -12
- package/deps/rocksdb/rocksdb/table/format.h +10 -0
- package/deps/rocksdb/rocksdb/table/internal_iterator.h +1 -1
- package/deps/rocksdb/rocksdb/table/iterator_wrapper.h +1 -1
- package/deps/rocksdb/rocksdb/table/merging_iterator.cc +1 -1
- package/deps/rocksdb/rocksdb/table/meta_blocks.cc +5 -0
- package/deps/rocksdb/rocksdb/table/multiget_context.h +3 -1
- package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +118 -46
- package/deps/rocksdb/rocksdb/table/sst_file_dumper.h +9 -8
- package/deps/rocksdb/rocksdb/table/table_builder.h +5 -0
- package/deps/rocksdb/rocksdb/table/table_properties.cc +16 -0
- package/deps/rocksdb/rocksdb/table/table_test.cc +1540 -155
- package/deps/rocksdb/rocksdb/test_util/testutil.h +21 -5
- package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +26 -5
- package/deps/rocksdb/rocksdb/tools/ldb.cc +1 -2
- package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +2 -0
- package/deps/rocksdb/rocksdb/tools/ldb_tool.cc +9 -3
- package/deps/rocksdb/rocksdb/tools/sst_dump_test.cc +133 -165
- package/deps/rocksdb/rocksdb/tools/sst_dump_tool.cc +173 -64
- package/deps/rocksdb/rocksdb/util/aligned_buffer.h +69 -0
- package/deps/rocksdb/rocksdb/util/atomic.h +6 -0
- package/deps/rocksdb/rocksdb/util/auto_tune_compressor.cc +29 -20
- package/deps/rocksdb/rocksdb/util/auto_tune_compressor.h +10 -6
- package/deps/rocksdb/rocksdb/util/bit_fields.h +338 -0
- package/deps/rocksdb/rocksdb/util/coding.h +3 -3
- package/deps/rocksdb/rocksdb/util/compaction_job_stats_impl.cc +2 -2
- package/deps/rocksdb/rocksdb/util/compression.cc +777 -82
- package/deps/rocksdb/rocksdb/util/compression.h +5 -0
- package/deps/rocksdb/rocksdb/util/compression_test.cc +5 -3
- package/deps/rocksdb/rocksdb/util/dynamic_bloom.cc +2 -2
- package/deps/rocksdb/rocksdb/util/dynamic_bloom.h +15 -14
- package/deps/rocksdb/rocksdb/util/interval_test.cc +102 -0
- package/deps/rocksdb/rocksdb/util/semaphore.h +164 -0
- package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.cc +10 -6
- package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.h +4 -2
- package/deps/rocksdb/rocksdb/util/slice_test.cc +136 -0
- package/deps/rocksdb/rocksdb/util/status.cc +1 -0
- package/deps/rocksdb/rocksdb/util/string_util.cc +2 -16
- package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.cc +1 -1
- package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.h +1 -1
- package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.cc +7 -4
- package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.h +35 -14
- package/deps/rocksdb/rocksdb/utilities/persistent_cache/hash_table_test.cc +2 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/lock_manager.cc +5 -2
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/any_lock_manager_test.h +244 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_bench.cc +18 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_bench_tool.cc +159 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager.cc +1244 -161
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager.h +66 -12
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_stress_test.cc +103 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test.cc +1275 -8
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test.h +40 -262
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test_common.h +78 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_validation_test_runner.h +469 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_locking_test.cc +2 -6
- package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.cc +4 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.h +9 -1
- package/deps/rocksdb/rocksdb/utilities/transactions/timestamped_snapshot_test.cc +18 -9
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_base.h +2 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_db_mutex_impl.cc +2 -1
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +72 -44
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.h +92 -15
- package/deps/rocksdb/rocksdb/utilities/transactions/write_committed_transaction_ts_test.cc +6 -20
- package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_transaction_test.cc +143 -112
- package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_transaction_test.cc +23 -16
- package/index.js +3 -3
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
- package/prebuilds/linux-x64/@nxtedition+rocksdb.node +0 -0
- package/util.h +38 -12
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_stat.cc +0 -17
package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_validation_test_runner.h
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
//
|
|
3
|
+
// This source code is licensed under both the GPLv2 (found in the
|
|
4
|
+
// COPYING file in the root directory) and Apache 2.0 License
|
|
5
|
+
// (found in the LICENSE.Apache file in the root directory).
|
|
6
|
+
|
|
7
|
+
#pragma once
|
|
8
|
+
|
|
9
|
+
#include <cinttypes>
|
|
10
|
+
#include <cstddef>
|
|
11
|
+
#include <cstdio>
|
|
12
|
+
#include <iostream>
|
|
13
|
+
#include <memory>
|
|
14
|
+
|
|
15
|
+
#include "rocksdb/convenience.h"
|
|
16
|
+
#include "rocksdb/db.h"
|
|
17
|
+
#include "rocksdb/env.h"
|
|
18
|
+
#include "rocksdb/utilities/transaction_db.h"
|
|
19
|
+
#include "utilities/transactions/lock/lock_manager.h"
|
|
20
|
+
#include "utilities/transactions/lock/point/point_lock_manager_test_common.h"
|
|
21
|
+
#include "utilities/transactions/pessimistic_transaction.h"
|
|
22
|
+
|
|
23
|
+
namespace ROCKSDB_NAMESPACE {
|
|
24
|
+
|
|
25
|
+
constexpr bool kDebugLog = false;
|
|
26
|
+
|
|
27
|
+
// Since this code is executed both with and without gtest, it supports assert
|
|
28
|
+
// with different ways.
|
|
29
|
+
#ifdef ASSERT_TRUE
|
|
30
|
+
#define ASSERT_TRUE_WITH_MSG(expr, errmsg) ASSERT_TRUE(expr) << (errmsg)
|
|
31
|
+
#else
|
|
32
|
+
#define ASSERT_TRUE_WITH_MSG(expr, errmsg) \
|
|
33
|
+
if (!(expr)) { \
|
|
34
|
+
std::cerr << "Assert true failed with error message: " << (errmsg) \
|
|
35
|
+
<< std::endl; \
|
|
36
|
+
abort(); \
|
|
37
|
+
}
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
#ifndef ASSERT_OK
|
|
41
|
+
#define ASSERT_OK(s) \
|
|
42
|
+
ASSERT_TRUE_WITH_MSG(s.ok(), "Failed with " + s.ToString());
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
#define ASSERT_TRUE_WITH_INFO(X) \
|
|
46
|
+
ASSERT_TRUE_WITH_MSG( \
|
|
47
|
+
(X), " Txn " + std::to_string(txn_id) + " key " + std::to_string(key))
|
|
48
|
+
|
|
49
|
+
#define ASSERT_EQ_WITH_INFO(X, Y) ASSERT_TRUE_WITH_INFO((X) == (Y))
|
|
50
|
+
|
|
51
|
+
#define DEBUG_LOG(...) \
|
|
52
|
+
if (kDebugLog) { \
|
|
53
|
+
fprintf(stderr, __VA_ARGS__); \
|
|
54
|
+
fflush(stderr); \
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#define DEBUG_LOG_WITH_PREFIX(format, ...) \
|
|
58
|
+
DEBUG_LOG("Txn %" PRIu64 " " format, txn_id, ##__VA_ARGS__);
|
|
59
|
+
|
|
60
|
+
enum class LockTypeToTest : int8_t {
|
|
61
|
+
EXCLUSIVE_ONLY = 0,
|
|
62
|
+
SHARED_ONLY = 1,
|
|
63
|
+
EXCLUSIVE_AND_SHARED = 2,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
struct KeyStatus {
|
|
67
|
+
KeyStatus(uint32_t k, bool ex, int v) : key(k), exclusive(ex), value(v) {}
|
|
68
|
+
uint32_t key;
|
|
69
|
+
bool exclusive;
|
|
70
|
+
int value;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
class PointLockValidationTestRunner {
|
|
74
|
+
public:
|
|
75
|
+
PointLockValidationTestRunner(
|
|
76
|
+
Env* env, TransactionDBOptions txndb_opt,
|
|
77
|
+
std::shared_ptr<LockManager> locker, TransactionDB* db,
|
|
78
|
+
TransactionOptions txn_opt, uint32_t thd_cnt, uint32_t key_cnt,
|
|
79
|
+
uint32_t max_num_keys_to_lock_per_txn, uint32_t execution_time_sec,
|
|
80
|
+
LockTypeToTest lock_type, bool allow_non_deadlock_error,
|
|
81
|
+
uint32_t max_sleep_after_lock_acquisition_ms,
|
|
82
|
+
bool enable_per_thread_lock_count_assertion = false)
|
|
83
|
+
: env_(env),
|
|
84
|
+
txndb_opt_(std::move(txndb_opt)),
|
|
85
|
+
locker_(std::move(locker)),
|
|
86
|
+
db_(db),
|
|
87
|
+
txn_opt_(std::move(txn_opt)),
|
|
88
|
+
thread_count_(thd_cnt),
|
|
89
|
+
key_count_(key_cnt),
|
|
90
|
+
max_num_keys_to_lock_per_txn_(max_num_keys_to_lock_per_txn),
|
|
91
|
+
execution_time_sec_(execution_time_sec),
|
|
92
|
+
lock_type_(lock_type),
|
|
93
|
+
allow_non_deadlock_error_(allow_non_deadlock_error),
|
|
94
|
+
max_sleep_after_lock_acquisition_ms_(
|
|
95
|
+
max_sleep_after_lock_acquisition_ms),
|
|
96
|
+
enable_per_thread_lock_count_assertion_(
|
|
97
|
+
enable_per_thread_lock_count_assertion),
|
|
98
|
+
shutdown_(false) {
|
|
99
|
+
// Only enable lock status validation when lock expiration/stealing isk
|
|
100
|
+
// disabled.
|
|
101
|
+
enable_lock_status_validation_ = txn_opt_.expiration == -1;
|
|
102
|
+
values_.resize(key_count_, 0);
|
|
103
|
+
exclusive_lock_status_.resize(key_count_, 0);
|
|
104
|
+
|
|
105
|
+
// init counters and values
|
|
106
|
+
for (size_t i = 0; i < key_count_; i++) {
|
|
107
|
+
counters_.emplace_back(std::make_unique<std::atomic_int>(0));
|
|
108
|
+
shared_lock_count_.emplace_back(std::make_unique<std::atomic_int>(0));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
for (size_t i = 0; i < thread_count_; i++) {
|
|
112
|
+
num_of_locks_acquired_per_thread_.emplace_back(
|
|
113
|
+
std::make_unique<std::atomic_int64_t>(0));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Decide which lock type to acquire
|
|
118
|
+
// If the key is already locked and only one type of locks to be tested,
|
|
119
|
+
// return false, so caller could try to lock a different key.
|
|
120
|
+
// Otherwise, return true.
|
|
121
|
+
bool DecideLockType(
|
|
122
|
+
bool& acquire_exclusive_lock, uint32_t key,
|
|
123
|
+
std::unordered_map<uint32_t, KeyStatus>& locked_key_status,
|
|
124
|
+
bool& isUpgrade, bool& isDowngrade) {
|
|
125
|
+
// Decide lock type
|
|
126
|
+
acquire_exclusive_lock = Random::GetTLSInstance()->OneIn(2);
|
|
127
|
+
|
|
128
|
+
// check whether a lock on the same key is already held
|
|
129
|
+
auto it = locked_key_status.find(key);
|
|
130
|
+
if (it != locked_key_status.end()) {
|
|
131
|
+
// a lock on the same key is already held.
|
|
132
|
+
if (lock_type_ == LockTypeToTest::EXCLUSIVE_AND_SHARED) {
|
|
133
|
+
// if test both shared and exclusive locks, switch their type
|
|
134
|
+
if (it->second.exclusive == false) {
|
|
135
|
+
// If it is a shared lock, upgrade to an exclusive lock
|
|
136
|
+
acquire_exclusive_lock = true;
|
|
137
|
+
isUpgrade = true;
|
|
138
|
+
} else {
|
|
139
|
+
// If it is an exclusive lock, downgrade to a shared lock
|
|
140
|
+
acquire_exclusive_lock = false;
|
|
141
|
+
isDowngrade = true;
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
// Only one type of lock to test, and the key is already locked,
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// This is a new key to lock or the lock type is switched.
|
|
150
|
+
if (lock_type_ != LockTypeToTest::EXCLUSIVE_AND_SHARED) {
|
|
151
|
+
// if only one type of locks to be acquired, update its type
|
|
152
|
+
acquire_exclusive_lock = (lock_type_ == LockTypeToTest::EXCLUSIVE_ONLY);
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
void run() {
|
|
158
|
+
// Verify lock guarantee. Exclusive lock provide unique access guarantee.
|
|
159
|
+
// Shared lock provide shared access guarantee.
|
|
160
|
+
// Create multiple threads. Each try to grab a lock with random type on
|
|
161
|
+
// random key.
|
|
162
|
+
|
|
163
|
+
// To validate lock exclusive guarantee, each key has a value and a counter
|
|
164
|
+
// used for tracking the number of exclusive locks have been acquired on it
|
|
165
|
+
// in each test run across all threads.
|
|
166
|
+
|
|
167
|
+
// Every time an exclusive lock is acquired, both the counter and the value
|
|
168
|
+
// are bumped by 1. The difference between the counter and the value is that
|
|
169
|
+
// counter is atomic, so it is guaranteed that it would not lose update,
|
|
170
|
+
// while value is not atomic. Its correctness is only guaranteed by the
|
|
171
|
+
// exclusiveness provided by the lock manager which is being tested. If the
|
|
172
|
+
// lock manager does not guarantee exclusiveness, the value would lose
|
|
173
|
+
// update, and the counter would mismatch with the value, which fails the
|
|
174
|
+
// test.
|
|
175
|
+
|
|
176
|
+
// To validate lock shared guarantee, after a shared lock is acquired, the
|
|
177
|
+
// counter and value are read and stored in a local variable inside the
|
|
178
|
+
// thread. Before the lock is released, the local copy is compared against
|
|
179
|
+
// the counter and value. If they mismatch, it means the shared lock
|
|
180
|
+
// guaranteed is violated.
|
|
181
|
+
|
|
182
|
+
MockColumnFamilyHandle cf(1);
|
|
183
|
+
locker_->AddColumnFamily(&cf);
|
|
184
|
+
|
|
185
|
+
for (uint32_t thd_idx = 0; thd_idx < thread_count_; thd_idx++) {
|
|
186
|
+
threads_.emplace_back([this, thd_idx]() {
|
|
187
|
+
auto txn = static_cast<PessimisticTransaction*>(
|
|
188
|
+
db_->BeginTransaction(WriteOptions(), txn_opt_));
|
|
189
|
+
auto txn_id = txn->GetID();
|
|
190
|
+
DEBUG_LOG_WITH_PREFIX("Thd %" PRIu32 " new txn\n", thd_idx);
|
|
191
|
+
while (!shutdown_) {
|
|
192
|
+
std::unordered_map<uint32_t, KeyStatus> locked_key_status;
|
|
193
|
+
auto num_key_to_lock = max_num_keys_to_lock_per_txn_;
|
|
194
|
+
Status s;
|
|
195
|
+
|
|
196
|
+
for (uint32_t j = 0; j < num_key_to_lock; j++) {
|
|
197
|
+
uint32_t key = 0;
|
|
198
|
+
key = Random::GetTLSInstance()->Uniform(key_count_);
|
|
199
|
+
auto key_str = std::to_string(key);
|
|
200
|
+
bool isUpgrade = false;
|
|
201
|
+
bool isDowngrade = false;
|
|
202
|
+
bool exclusive_lock_type;
|
|
203
|
+
|
|
204
|
+
if (!DecideLockType(exclusive_lock_type, key, locked_key_status,
|
|
205
|
+
isUpgrade, isDowngrade)) {
|
|
206
|
+
// try a different key
|
|
207
|
+
j--;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (enable_lock_status_validation_) {
|
|
212
|
+
if (isDowngrade) {
|
|
213
|
+
// Before downgrade, validate the lock is in exlusive status
|
|
214
|
+
// This could not be done after downgrade, as another thread
|
|
215
|
+
// could take a shared lock and update lock status
|
|
216
|
+
ASSERT_TRUE_WITH_INFO(exclusive_lock_status_[key]);
|
|
217
|
+
ASSERT_EQ_WITH_INFO(*shared_lock_count_[key], 0);
|
|
218
|
+
// for downgrade, update the lock status before acquiring the
|
|
219
|
+
// lock, as afterwards, it will not have exclusive access to it
|
|
220
|
+
exclusive_lock_status_[key] = 0;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// try to acquire the lock
|
|
225
|
+
DEBUG_LOG_WITH_PREFIX("try to acquire lock %" PRIu32 " type %s\n",
|
|
226
|
+
key,
|
|
227
|
+
exclusive_lock_type ? "exclusive" : "shared");
|
|
228
|
+
s = locker_->TryLock(txn, 1, key_str, env_, exclusive_lock_type);
|
|
229
|
+
|
|
230
|
+
if (s.ok()) {
|
|
231
|
+
DEBUG_LOG_WITH_PREFIX(
|
|
232
|
+
"acquired lock %" PRIu32 " type %s\n", key,
|
|
233
|
+
exclusive_lock_type ? "exclusive" : "shared");
|
|
234
|
+
|
|
235
|
+
auto it = locked_key_status.find(key);
|
|
236
|
+
if (isUpgrade || isDowngrade) {
|
|
237
|
+
// If it is either upgrade or downgrade, the key should exist
|
|
238
|
+
// already.
|
|
239
|
+
ASSERT_TRUE_WITH_INFO(it != locked_key_status.end());
|
|
240
|
+
} else {
|
|
241
|
+
locked_key_status.emplace(
|
|
242
|
+
std::piecewise_construct, std::forward_as_tuple(key),
|
|
243
|
+
std::forward_as_tuple(key, exclusive_lock_type,
|
|
244
|
+
values_[key]));
|
|
245
|
+
}
|
|
246
|
+
// update local lock status
|
|
247
|
+
if (exclusive_lock_type) {
|
|
248
|
+
if (isUpgrade) {
|
|
249
|
+
it->second.exclusive = true;
|
|
250
|
+
}
|
|
251
|
+
num_of_exclusive_locks_acquired_++;
|
|
252
|
+
} else {
|
|
253
|
+
if (isDowngrade) {
|
|
254
|
+
it->second.exclusive = false;
|
|
255
|
+
}
|
|
256
|
+
num_of_shared_locks_acquired_++;
|
|
257
|
+
}
|
|
258
|
+
num_of_locks_acquired_++;
|
|
259
|
+
(*num_of_locks_acquired_per_thread_[thd_idx])++;
|
|
260
|
+
|
|
261
|
+
if (enable_lock_status_validation_) {
|
|
262
|
+
if (exclusive_lock_type) {
|
|
263
|
+
// validate the lock is not in exclusive status
|
|
264
|
+
ASSERT_TRUE_WITH_INFO(!exclusive_lock_status_[key]);
|
|
265
|
+
if (isUpgrade) {
|
|
266
|
+
// validate the lock is in shared status and only had one
|
|
267
|
+
// shared lock
|
|
268
|
+
ASSERT_EQ_WITH_INFO(*shared_lock_count_[key], 1);
|
|
269
|
+
shared_lock_count_[key]->fetch_sub(1);
|
|
270
|
+
} else {
|
|
271
|
+
ASSERT_EQ_WITH_INFO(*shared_lock_count_[key], 0);
|
|
272
|
+
}
|
|
273
|
+
// update the lock status
|
|
274
|
+
exclusive_lock_status_[key] = 1;
|
|
275
|
+
} else {
|
|
276
|
+
shared_lock_count_[key]->fetch_add(1);
|
|
277
|
+
ASSERT_TRUE_WITH_INFO(!exclusive_lock_status_[key]);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
if (!allow_non_deadlock_error_) {
|
|
282
|
+
ASSERT_TRUE_WITH_INFO(s.IsDeadlock());
|
|
283
|
+
}
|
|
284
|
+
if (s.IsDeadlock()) {
|
|
285
|
+
DEBUG_LOG_WITH_PREFIX(
|
|
286
|
+
"detected deadlock on key %" PRIu32 ", abort\n", key);
|
|
287
|
+
num_of_deadlock_detected_++;
|
|
288
|
+
// for deadlock, release all locks acquired
|
|
289
|
+
break;
|
|
290
|
+
} else {
|
|
291
|
+
// for other errors, try again
|
|
292
|
+
DEBUG_LOG_WITH_PREFIX("failed to acquire lock on key %" PRIu32
|
|
293
|
+
", due to "
|
|
294
|
+
"%s, "
|
|
295
|
+
"abort\n",
|
|
296
|
+
key, s.ToString().c_str());
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// After all of the locks are acquired, try to sleep a bit to simulate
|
|
302
|
+
// some useful work to be done
|
|
303
|
+
if (max_sleep_after_lock_acquisition_ms_ != 0 && s.ok()) {
|
|
304
|
+
auto sleep_time_us = Random::GetTLSInstance()->Uniform(
|
|
305
|
+
static_cast<uint32_t>(max_sleep_after_lock_acquisition_ms_));
|
|
306
|
+
std::this_thread::sleep_for(
|
|
307
|
+
std::chrono::milliseconds(sleep_time_us));
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// release all locks
|
|
311
|
+
for (const auto& pair : locked_key_status) {
|
|
312
|
+
auto key_status = pair.second;
|
|
313
|
+
auto key = key_status.key;
|
|
314
|
+
ASSERT_TRUE_WITH_INFO(key < key_count_);
|
|
315
|
+
if (enable_lock_status_validation_) {
|
|
316
|
+
ASSERT_EQ_WITH_INFO(counters_[key]->load(), values_[key]);
|
|
317
|
+
auto exclusive = key_status.exclusive;
|
|
318
|
+
if (exclusive) {
|
|
319
|
+
// for exclusive lock, bump the value by 1
|
|
320
|
+
(*counters_[key])++;
|
|
321
|
+
values_[key]++;
|
|
322
|
+
DEBUG_LOG_WITH_PREFIX("bump key %" PRIu32 " by 1 to %d\n", key,
|
|
323
|
+
values_[key]);
|
|
324
|
+
ASSERT_EQ_WITH_INFO(counters_[key]->load(), values_[key]);
|
|
325
|
+
} else {
|
|
326
|
+
// shared lock, validate the value has not changed since it was
|
|
327
|
+
// read
|
|
328
|
+
ASSERT_EQ_WITH_INFO(counters_[key]->load(), key_status.value);
|
|
329
|
+
ASSERT_EQ_WITH_INFO(values_[key], key_status.value);
|
|
330
|
+
}
|
|
331
|
+
if (exclusive) {
|
|
332
|
+
ASSERT_TRUE_WITH_INFO(exclusive_lock_status_[key]);
|
|
333
|
+
ASSERT_EQ_WITH_INFO(*shared_lock_count_[key], 0);
|
|
334
|
+
exclusive_lock_status_[key] = 0;
|
|
335
|
+
} else {
|
|
336
|
+
ASSERT_TRUE_WITH_INFO(!exclusive_lock_status_[key]);
|
|
337
|
+
ASSERT_TRUE_WITH_INFO(shared_lock_count_[key]->fetch_sub(1) >=
|
|
338
|
+
1);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
DEBUG_LOG_WITH_PREFIX("release lock %" PRIu32 "\n", key);
|
|
342
|
+
locker_->UnLock(txn, 1, std::to_string(key), env_);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
delete txn;
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// run test for a few seconds
|
|
350
|
+
// print progress
|
|
351
|
+
auto prev_num_of_locks_acquired = num_of_locks_acquired_.load();
|
|
352
|
+
std::vector<int64_t> prev_num_of_locks_acquired_per_thread(thread_count_,
|
|
353
|
+
0);
|
|
354
|
+
int64_t measured_locks_acquired = 0;
|
|
355
|
+
for (uint32_t i = 0; i < execution_time_sec_; i++) {
|
|
356
|
+
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
357
|
+
auto num_of_locks_acquired = num_of_locks_acquired_.load();
|
|
358
|
+
DEBUG_LOG("num_of_locks_acquired: %" PRId64 "\n", num_of_locks_acquired);
|
|
359
|
+
DEBUG_LOG("num_of_exclusive_locks_acquired: %" PRId64 "\n",
|
|
360
|
+
num_of_exclusive_locks_acquired_.load());
|
|
361
|
+
DEBUG_LOG("num_of_shared_locks_acquired: %" PRId64 "\n",
|
|
362
|
+
num_of_shared_locks_acquired_.load());
|
|
363
|
+
DEBUG_LOG("num_of_deadlock_detected: %" PRId64 "\n",
|
|
364
|
+
num_of_deadlock_detected_.load());
|
|
365
|
+
ASSERT_TRUE_WITH_MSG(num_of_locks_acquired > prev_num_of_locks_acquired,
|
|
366
|
+
"No locks were acquired in the last 1 second");
|
|
367
|
+
for (uint32_t thd_idx = 0; thd_idx < thread_count_; thd_idx++) {
|
|
368
|
+
auto num_of_locks_acquired_per_thread =
|
|
369
|
+
num_of_locks_acquired_per_thread_[thd_idx]->load();
|
|
370
|
+
DEBUG_LOG("thread: %" PRIu32 " acquired %" PRId64 " locks\n", thd_idx,
|
|
371
|
+
num_of_locks_acquired_per_thread);
|
|
372
|
+
if (enable_per_thread_lock_count_assertion_) {
|
|
373
|
+
ASSERT_TRUE_WITH_MSG(
|
|
374
|
+
num_of_locks_acquired_per_thread >
|
|
375
|
+
prev_num_of_locks_acquired_per_thread[thd_idx],
|
|
376
|
+
"No locks were acquired in the last 1 second on thread " +
|
|
377
|
+
std::to_string(thd_idx));
|
|
378
|
+
}
|
|
379
|
+
prev_num_of_locks_acquired_per_thread[thd_idx] =
|
|
380
|
+
num_of_locks_acquired_per_thread;
|
|
381
|
+
}
|
|
382
|
+
prev_num_of_locks_acquired = num_of_locks_acquired;
|
|
383
|
+
if (i == 0) {
|
|
384
|
+
measured_locks_acquired = num_of_locks_acquired;
|
|
385
|
+
}
|
|
386
|
+
if (i == execution_time_sec_ - 1) {
|
|
387
|
+
measured_locks_acquired =
|
|
388
|
+
num_of_locks_acquired - measured_locks_acquired;
|
|
389
|
+
// Skip the first second, as threads are warming up
|
|
390
|
+
auto measured_execution_time_sec = execution_time_sec_ - 1;
|
|
391
|
+
if (measured_execution_time_sec > 0) {
|
|
392
|
+
printf("measured_num_of_locks_acquired: %" PRId64 "\n",
|
|
393
|
+
measured_locks_acquired / (measured_execution_time_sec));
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
shutdown_ = true;
|
|
399
|
+
for (auto& t : threads_) {
|
|
400
|
+
t.join();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// validate values against counters
|
|
404
|
+
for (uint32_t i = 0; i < key_count_; i++) {
|
|
405
|
+
ASSERT_TRUE_WITH_MSG(counters_[i]->load() == values_[i],
|
|
406
|
+
"Exclusive lock guarantee is violated.");
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
ASSERT_TRUE_WITH_MSG(num_of_locks_acquired_.load() >= 0,
|
|
410
|
+
"No lock were acquired at all");
|
|
411
|
+
printf("num_of_locks_acquired: %" PRId64 "\n",
|
|
412
|
+
num_of_locks_acquired_.load());
|
|
413
|
+
|
|
414
|
+
std::string errmsg;
|
|
415
|
+
auto no_lock_held = verifyNoLocksHeld(locker_, errmsg);
|
|
416
|
+
ASSERT_TRUE_WITH_MSG(no_lock_held, errmsg);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
private:
|
|
420
|
+
// test configuration
|
|
421
|
+
Env* env_;
|
|
422
|
+
TransactionDBOptions txndb_opt_;
|
|
423
|
+
std::shared_ptr<LockManager> locker_;
|
|
424
|
+
|
|
425
|
+
TransactionDB* db_;
|
|
426
|
+
TransactionOptions txn_opt_;
|
|
427
|
+
|
|
428
|
+
uint32_t thread_count_;
|
|
429
|
+
uint32_t key_count_;
|
|
430
|
+
uint32_t max_num_keys_to_lock_per_txn_;
|
|
431
|
+
uint32_t execution_time_sec_;
|
|
432
|
+
LockTypeToTest lock_type_;
|
|
433
|
+
bool allow_non_deadlock_error_;
|
|
434
|
+
uint32_t max_sleep_after_lock_acquisition_ms_;
|
|
435
|
+
|
|
436
|
+
// In some of the test run, due to debug or ASAN build and short lock timeout,
|
|
437
|
+
// a thread may not be able to acquire any lock within a second. So skip this
|
|
438
|
+
// assertion by default. However, this could be useful for quickly detecting
|
|
439
|
+
// stuck thread, when running locally with longer timeout.
|
|
440
|
+
bool enable_per_thread_lock_count_assertion_;
|
|
441
|
+
|
|
442
|
+
// Internal test variables
|
|
443
|
+
|
|
444
|
+
bool enable_lock_status_validation_;
|
|
445
|
+
std::vector<std::thread> threads_;
|
|
446
|
+
std::vector<std::unique_ptr<std::atomic_int>> counters_;
|
|
447
|
+
std::vector<int> values_;
|
|
448
|
+
|
|
449
|
+
// track whether the lock is in exclusive status or
|
|
450
|
+
// not. vector<bool> does something special underneath, causing consistency
|
|
451
|
+
// issue. Therefore int64_t is used.
|
|
452
|
+
std::vector<int64_t> exclusive_lock_status_;
|
|
453
|
+
|
|
454
|
+
// A counter to track number of shared locks for tracking shared lock status
|
|
455
|
+
std::vector<std::unique_ptr<std::atomic_int>> shared_lock_count_;
|
|
456
|
+
|
|
457
|
+
// shutdown flag to signal threads to exit
|
|
458
|
+
std::atomic_bool shutdown_ = false;
|
|
459
|
+
|
|
460
|
+
// test statistics
|
|
461
|
+
std::atomic_int64_t num_of_locks_acquired_ = 0;
|
|
462
|
+
std::atomic_int64_t num_of_shared_locks_acquired_ = 0;
|
|
463
|
+
std::atomic_int64_t num_of_exclusive_locks_acquired_ = 0;
|
|
464
|
+
std::atomic_int64_t num_of_deadlock_detected_ = 0;
|
|
465
|
+
std::vector<std::unique_ptr<std::atomic_int64_t>>
|
|
466
|
+
num_of_locks_acquired_per_thread_;
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
} // namespace ROCKSDB_NAMESPACE
|
|
@@ -5,22 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
#ifndef OS_WIN
|
|
7
7
|
|
|
8
|
-
#include <algorithm>
|
|
9
8
|
#include <functional>
|
|
10
9
|
#include <iomanip>
|
|
11
10
|
#include <string>
|
|
12
11
|
#include <thread>
|
|
13
12
|
|
|
14
13
|
#include "db/db_impl/db_impl.h"
|
|
15
|
-
#include "port/port.h"
|
|
16
14
|
#include "rocksdb/db.h"
|
|
17
15
|
#include "rocksdb/options.h"
|
|
18
|
-
#include "rocksdb/perf_context.h"
|
|
19
16
|
#include "rocksdb/utilities/transaction.h"
|
|
20
17
|
#include "rocksdb/utilities/transaction_db.h"
|
|
21
|
-
#include "utilities/transactions/lock/point/
|
|
22
|
-
#include "utilities/transactions/
|
|
23
|
-
#include "utilities/transactions/transaction_test.h"
|
|
18
|
+
#include "utilities/transactions/lock/point/any_lock_manager_test.h"
|
|
19
|
+
#include "utilities/transactions/transaction_db_mutex_impl.h"
|
|
24
20
|
|
|
25
21
|
using std::string;
|
|
26
22
|
|
|
@@ -84,6 +84,10 @@ void PessimisticTransaction::Initialize(const TransactionOptions& txn_options) {
|
|
|
84
84
|
txn_db_impl_->GetTxnDBOptions().transaction_lock_timeout * 1000;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
// deadlock timeout should be lower than lock timeout
|
|
88
|
+
deadlock_timeout_us_ =
|
|
89
|
+
std::min(txn_options.deadlock_timeout_us, lock_timeout_);
|
|
90
|
+
|
|
87
91
|
if (txn_options.expiration >= 0) {
|
|
88
92
|
expiration_time_ = start_time_ + txn_options.expiration * 1000;
|
|
89
93
|
} else {
|
|
@@ -81,7 +81,7 @@ class PessimisticTransaction : public TransactionBaseImpl {
|
|
|
81
81
|
return ids;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
void SetWaitingTxn(autovector<TransactionID
|
|
84
|
+
void SetWaitingTxn(autovector<TransactionID>& ids, uint32_t column_family_id,
|
|
85
85
|
const std::string* key, bool is_timed_out = false) {
|
|
86
86
|
std::lock_guard<std::mutex> lock(wait_mutex_);
|
|
87
87
|
waiting_txn_ids_ = ids;
|
|
@@ -114,6 +114,10 @@ class PessimisticTransaction : public TransactionBaseImpl {
|
|
|
114
114
|
void SetLockTimeout(int64_t timeout) override {
|
|
115
115
|
lock_timeout_ = timeout * 1000;
|
|
116
116
|
}
|
|
117
|
+
int64_t GetDeadlockTimeout() const { return deadlock_timeout_us_; }
|
|
118
|
+
void SetDeadlockTimeout(int64_t timeout_ms) override {
|
|
119
|
+
deadlock_timeout_us_ = timeout_ms * 1000;
|
|
120
|
+
}
|
|
117
121
|
|
|
118
122
|
// Returns true if locks were stolen successfully, false otherwise.
|
|
119
123
|
bool TryStealingLocks();
|
|
@@ -213,6 +217,10 @@ class PessimisticTransaction : public TransactionBaseImpl {
|
|
|
213
217
|
// Timeout in microseconds when locking a key or -1 if there is no timeout.
|
|
214
218
|
int64_t lock_timeout_;
|
|
215
219
|
|
|
220
|
+
// Timeout in microseconds before perform dead lock detection.
|
|
221
|
+
// If 0, deadlock detection will be performed immediately.
|
|
222
|
+
int64_t deadlock_timeout_us_;
|
|
223
|
+
|
|
216
224
|
// Whether to perform deadlock detection or not.
|
|
217
225
|
bool deadlock_detect_;
|
|
218
226
|
|
|
@@ -9,17 +9,26 @@
|
|
|
9
9
|
#include "utilities/transactions/transaction_test.h"
|
|
10
10
|
|
|
11
11
|
namespace ROCKSDB_NAMESPACE {
|
|
12
|
+
|
|
13
|
+
constexpr std::array TimestampedSnapshotWithTsSanityCheck_Params = {
|
|
14
|
+
std::make_tuple(false, false, WRITE_PREPARED, kOrderedWrite),
|
|
15
|
+
std::make_tuple(false, true, WRITE_PREPARED, kUnorderedWrite),
|
|
16
|
+
std::make_tuple(false, false, WRITE_UNPREPARED, kOrderedWrite)};
|
|
17
|
+
|
|
12
18
|
INSTANTIATE_TEST_CASE_P(
|
|
13
19
|
Unsupported, TimestampedSnapshotWithTsSanityCheck,
|
|
14
|
-
::testing::
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
::testing::ValuesIn(WRAP_PARAM_WITH_PER_KEY_POINT_LOCK_MANAGER_PARAMS(
|
|
21
|
+
WRAP_PARAM(bool, bool, TxnDBWritePolicy, WriteOrdering),
|
|
22
|
+
TimestampedSnapshotWithTsSanityCheck_Params)));
|
|
23
|
+
|
|
24
|
+
INSTANTIATE_TEST_CASE_P(
|
|
25
|
+
WriteCommitted, TransactionTest,
|
|
26
|
+
::testing::Combine(/*use_stackable_db=*/::testing::Bool(),
|
|
27
|
+
/*two_write_queue=*/::testing::Bool(),
|
|
28
|
+
::testing::Values(WRITE_COMMITTED),
|
|
29
|
+
::testing::Values(kOrderedWrite),
|
|
30
|
+
/*use_per_key_point_lock_mgr=*/::testing::Bool(),
|
|
31
|
+
/*deadlock_timeout_us=*/::testing::Values(0, 1000)));
|
|
23
32
|
|
|
24
33
|
namespace {
|
|
25
34
|
// Not thread-safe. Caller needs to provide external synchronization.
|
|
@@ -250,6 +250,8 @@ class TransactionBaseImpl : public Transaction {
|
|
|
250
250
|
|
|
251
251
|
void SetLockTimeout(int64_t /*timeout*/) override { /* Do nothing */ }
|
|
252
252
|
|
|
253
|
+
void SetDeadlockTimeout(int64_t /*timeout*/) override { /* Do nothing */ }
|
|
254
|
+
|
|
253
255
|
const Snapshot* GetSnapshot() const override {
|
|
254
256
|
// will return nullptr when there is no snapshot
|
|
255
257
|
return snapshot_.get();
|