]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/db_stress_tool/db_stress_common.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / db_stress_tool / db_stress_common.h
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5 //
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9 //
10 // The test uses an array to compare against values written to the database.
11 // Keys written to the array are in 1:1 correspondence to the actual values in
12 // the database according to the formula in the function GenerateValue.
13
14 // Space is reserved in the array from 0 to FLAGS_max_key and values are
15 // randomly written/deleted/read from those positions. During verification we
16 // compare all the positions in the array. To shorten/elongate the running
17 // time, you could change the settings: FLAGS_max_key, FLAGS_ops_per_thread,
18 // (sometimes also FLAGS_threads).
19 //
20 // NOTE that if FLAGS_test_batches_snapshots is set, the test will have
21 // different behavior. See comment of the flag for details.
22
23 #ifdef GFLAGS
24 #pragma once
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29
30 #include <algorithm>
31 #include <array>
32 #include <chrono>
33 #include <cinttypes>
34 #include <exception>
35 #include <queue>
36 #include <thread>
37
38 #include "db/db_impl/db_impl.h"
39 #include "db/version_set.h"
40 #include "db_stress_tool/db_stress_env_wrapper.h"
41 #include "db_stress_tool/db_stress_listener.h"
42 #include "db_stress_tool/db_stress_shared_state.h"
43 #include "db_stress_tool/db_stress_test_base.h"
44 #include "logging/logging.h"
45 #include "monitoring/histogram.h"
46 #include "options/options_helper.h"
47 #include "port/port.h"
48 #include "rocksdb/cache.h"
49 #include "rocksdb/env.h"
50 #include "rocksdb/slice.h"
51 #include "rocksdb/slice_transform.h"
52 #include "rocksdb/statistics.h"
53 #include "rocksdb/utilities/backup_engine.h"
54 #include "rocksdb/utilities/checkpoint.h"
55 #include "rocksdb/utilities/db_ttl.h"
56 #include "rocksdb/utilities/debug.h"
57 #include "rocksdb/utilities/options_util.h"
58 #include "rocksdb/utilities/transaction.h"
59 #include "rocksdb/utilities/transaction_db.h"
60 #include "rocksdb/write_batch.h"
61 #include "test_util/testutil.h"
62 #include "util/coding.h"
63 #include "util/compression.h"
64 #include "util/crc32c.h"
65 #include "util/gflags_compat.h"
66 #include "util/mutexlock.h"
67 #include "util/random.h"
68 #include "util/string_util.h"
69 #include "utilities/blob_db/blob_db.h"
70 #include "utilities/fault_injection_fs.h"
71 #include "utilities/merge_operators.h"
72
73 using GFLAGS_NAMESPACE::ParseCommandLineFlags;
74 using GFLAGS_NAMESPACE::RegisterFlagValidator;
75 using GFLAGS_NAMESPACE::SetUsageMessage;
76
77 DECLARE_uint64(seed);
78 DECLARE_bool(read_only);
79 DECLARE_int64(max_key);
80 DECLARE_double(hot_key_alpha);
81 DECLARE_int32(max_key_len);
82 DECLARE_string(key_len_percent_dist);
83 DECLARE_int32(key_window_scale_factor);
84 DECLARE_int32(column_families);
85 DECLARE_string(options_file);
86 DECLARE_int64(active_width);
87 DECLARE_bool(test_batches_snapshots);
88 DECLARE_bool(atomic_flush);
89 DECLARE_int32(manual_wal_flush_one_in);
90 DECLARE_bool(test_cf_consistency);
91 DECLARE_bool(test_multi_ops_txns);
92 DECLARE_int32(threads);
93 DECLARE_int32(ttl);
94 DECLARE_int32(value_size_mult);
95 DECLARE_int32(compaction_readahead_size);
96 DECLARE_bool(enable_pipelined_write);
97 DECLARE_bool(verify_before_write);
98 DECLARE_bool(histogram);
99 DECLARE_bool(destroy_db_initially);
100 DECLARE_bool(verbose);
101 DECLARE_bool(progress_reports);
102 DECLARE_uint64(db_write_buffer_size);
103 DECLARE_int32(write_buffer_size);
104 DECLARE_int32(max_write_buffer_number);
105 DECLARE_int32(min_write_buffer_number_to_merge);
106 DECLARE_int32(max_write_buffer_number_to_maintain);
107 DECLARE_int64(max_write_buffer_size_to_maintain);
108 DECLARE_double(memtable_prefix_bloom_size_ratio);
109 DECLARE_bool(memtable_whole_key_filtering);
110 DECLARE_int32(open_files);
111 DECLARE_int64(compressed_cache_size);
112 DECLARE_int32(compressed_cache_numshardbits);
113 DECLARE_int32(compaction_style);
114 DECLARE_int32(compaction_pri);
115 DECLARE_int32(num_levels);
116 DECLARE_int32(level0_file_num_compaction_trigger);
117 DECLARE_int32(level0_slowdown_writes_trigger);
118 DECLARE_int32(level0_stop_writes_trigger);
119 DECLARE_int32(block_size);
120 DECLARE_int32(format_version);
121 DECLARE_int32(index_block_restart_interval);
122 DECLARE_bool(disable_auto_compactions);
123 DECLARE_int32(max_background_compactions);
124 DECLARE_int32(num_bottom_pri_threads);
125 DECLARE_int32(compaction_thread_pool_adjust_interval);
126 DECLARE_int32(compaction_thread_pool_variations);
127 DECLARE_int32(max_background_flushes);
128 DECLARE_int32(universal_size_ratio);
129 DECLARE_int32(universal_min_merge_width);
130 DECLARE_int32(universal_max_merge_width);
131 DECLARE_int32(universal_max_size_amplification_percent);
132 DECLARE_int32(clear_column_family_one_in);
133 DECLARE_int32(get_live_files_one_in);
134 DECLARE_int32(get_sorted_wal_files_one_in);
135 DECLARE_int32(get_current_wal_file_one_in);
136 DECLARE_int32(set_options_one_in);
137 DECLARE_int32(set_in_place_one_in);
138 DECLARE_int64(cache_size);
139 DECLARE_int32(cache_numshardbits);
140 DECLARE_bool(cache_index_and_filter_blocks);
141 DECLARE_bool(charge_compression_dictionary_building_buffer);
142 DECLARE_bool(charge_filter_construction);
143 DECLARE_bool(charge_table_reader);
144 DECLARE_bool(charge_file_metadata);
145 DECLARE_bool(charge_blob_cache);
146 DECLARE_int32(top_level_index_pinning);
147 DECLARE_int32(partition_pinning);
148 DECLARE_int32(unpartitioned_pinning);
149 DECLARE_string(cache_type);
150 DECLARE_uint64(subcompactions);
151 DECLARE_uint64(periodic_compaction_seconds);
152 DECLARE_uint64(compaction_ttl);
153 DECLARE_bool(allow_concurrent_memtable_write);
154 DECLARE_double(experimental_mempurge_threshold);
155 DECLARE_bool(enable_write_thread_adaptive_yield);
156 DECLARE_int32(reopen);
157 DECLARE_double(bloom_bits);
158 DECLARE_int32(ribbon_starting_level);
159 DECLARE_bool(partition_filters);
160 DECLARE_bool(optimize_filters_for_memory);
161 DECLARE_bool(detect_filter_construct_corruption);
162 DECLARE_int32(index_type);
163 DECLARE_int32(data_block_index_type);
164 DECLARE_string(db);
165 DECLARE_string(secondaries_base);
166 DECLARE_bool(test_secondary);
167 DECLARE_string(expected_values_dir);
168 DECLARE_bool(verify_checksum);
169 DECLARE_bool(mmap_read);
170 DECLARE_bool(mmap_write);
171 DECLARE_bool(use_direct_reads);
172 DECLARE_bool(use_direct_io_for_flush_and_compaction);
173 DECLARE_bool(mock_direct_io);
174 DECLARE_bool(statistics);
175 DECLARE_bool(sync);
176 DECLARE_bool(use_fsync);
177 DECLARE_uint64(stats_dump_period_sec);
178 DECLARE_uint64(bytes_per_sync);
179 DECLARE_uint64(wal_bytes_per_sync);
180 DECLARE_int32(kill_random_test);
181 DECLARE_string(kill_exclude_prefixes);
182 DECLARE_bool(disable_wal);
183 DECLARE_uint64(recycle_log_file_num);
184 DECLARE_int64(target_file_size_base);
185 DECLARE_int32(target_file_size_multiplier);
186 DECLARE_uint64(max_bytes_for_level_base);
187 DECLARE_double(max_bytes_for_level_multiplier);
188 DECLARE_int32(range_deletion_width);
189 DECLARE_uint64(rate_limiter_bytes_per_sec);
190 DECLARE_bool(rate_limit_bg_reads);
191 DECLARE_bool(rate_limit_user_ops);
192 DECLARE_bool(rate_limit_auto_wal_flush);
193 DECLARE_uint64(sst_file_manager_bytes_per_sec);
194 DECLARE_uint64(sst_file_manager_bytes_per_truncate);
195 DECLARE_bool(use_txn);
196 DECLARE_uint64(txn_write_policy);
197 DECLARE_bool(unordered_write);
198 DECLARE_int32(backup_one_in);
199 DECLARE_uint64(backup_max_size);
200 DECLARE_int32(checkpoint_one_in);
201 DECLARE_int32(ingest_external_file_one_in);
202 DECLARE_int32(ingest_external_file_width);
203 DECLARE_int32(compact_files_one_in);
204 DECLARE_int32(compact_range_one_in);
205 DECLARE_int32(mark_for_compaction_one_file_in);
206 DECLARE_int32(flush_one_in);
207 DECLARE_int32(pause_background_one_in);
208 DECLARE_int32(compact_range_width);
209 DECLARE_int32(acquire_snapshot_one_in);
210 DECLARE_bool(compare_full_db_state_snapshot);
211 DECLARE_uint64(snapshot_hold_ops);
212 DECLARE_bool(long_running_snapshots);
213 DECLARE_bool(use_multiget);
214 DECLARE_int32(readpercent);
215 DECLARE_int32(prefixpercent);
216 DECLARE_int32(writepercent);
217 DECLARE_int32(delpercent);
218 DECLARE_int32(delrangepercent);
219 DECLARE_int32(nooverwritepercent);
220 DECLARE_int32(iterpercent);
221 DECLARE_uint64(num_iterations);
222 DECLARE_int32(customopspercent);
223 DECLARE_string(compression_type);
224 DECLARE_string(bottommost_compression_type);
225 DECLARE_int32(compression_max_dict_bytes);
226 DECLARE_int32(compression_zstd_max_train_bytes);
227 DECLARE_int32(compression_parallel_threads);
228 DECLARE_uint64(compression_max_dict_buffer_bytes);
229 DECLARE_bool(compression_use_zstd_dict_trainer);
230 DECLARE_string(checksum_type);
231 DECLARE_string(env_uri);
232 DECLARE_string(fs_uri);
233 DECLARE_uint64(ops_per_thread);
234 DECLARE_uint64(log2_keys_per_lock);
235 DECLARE_uint64(max_manifest_file_size);
236 DECLARE_bool(in_place_update);
237 DECLARE_string(memtablerep);
238 DECLARE_int32(prefix_size);
239 DECLARE_bool(use_merge);
240 DECLARE_uint32(use_put_entity_one_in);
241 DECLARE_bool(use_full_merge_v1);
242 DECLARE_int32(sync_wal_one_in);
243 DECLARE_bool(avoid_unnecessary_blocking_io);
244 DECLARE_bool(write_dbid_to_manifest);
245 DECLARE_bool(avoid_flush_during_recovery);
246 DECLARE_uint64(max_write_batch_group_size_bytes);
247 DECLARE_bool(level_compaction_dynamic_level_bytes);
248 DECLARE_int32(verify_checksum_one_in);
249 DECLARE_int32(verify_db_one_in);
250 DECLARE_int32(continuous_verification_interval);
251 DECLARE_int32(get_property_one_in);
252 DECLARE_string(file_checksum_impl);
253
254 #ifndef ROCKSDB_LITE
255 // Options for StackableDB-based BlobDB
256 DECLARE_bool(use_blob_db);
257 DECLARE_uint64(blob_db_min_blob_size);
258 DECLARE_uint64(blob_db_bytes_per_sync);
259 DECLARE_uint64(blob_db_file_size);
260 DECLARE_bool(blob_db_enable_gc);
261 DECLARE_double(blob_db_gc_cutoff);
262 #endif // !ROCKSDB_LITE
263
264 // Options for integrated BlobDB
265 DECLARE_bool(allow_setting_blob_options_dynamically);
266 DECLARE_bool(enable_blob_files);
267 DECLARE_uint64(min_blob_size);
268 DECLARE_uint64(blob_file_size);
269 DECLARE_string(blob_compression_type);
270 DECLARE_bool(enable_blob_garbage_collection);
271 DECLARE_double(blob_garbage_collection_age_cutoff);
272 DECLARE_double(blob_garbage_collection_force_threshold);
273 DECLARE_uint64(blob_compaction_readahead_size);
274 DECLARE_int32(blob_file_starting_level);
275 DECLARE_bool(use_blob_cache);
276 DECLARE_bool(use_shared_block_and_blob_cache);
277 DECLARE_uint64(blob_cache_size);
278 DECLARE_int32(blob_cache_numshardbits);
279 DECLARE_int32(prepopulate_blob_cache);
280
281 DECLARE_int32(approximate_size_one_in);
282 DECLARE_bool(sync_fault_injection);
283
284 DECLARE_bool(best_efforts_recovery);
285 DECLARE_bool(skip_verifydb);
286 DECLARE_bool(enable_compaction_filter);
287 DECLARE_bool(paranoid_file_checks);
288 DECLARE_bool(fail_if_options_file_error);
289 DECLARE_uint64(batch_protection_bytes_per_key);
290 DECLARE_uint32(memtable_protection_bytes_per_key);
291
292 DECLARE_uint64(user_timestamp_size);
293 DECLARE_string(secondary_cache_uri);
294 DECLARE_int32(secondary_cache_fault_one_in);
295
296 DECLARE_int32(prepopulate_block_cache);
297
298 DECLARE_bool(two_write_queues);
299 #ifndef ROCKSDB_LITE
300 DECLARE_bool(use_only_the_last_commit_time_batch_for_recovery);
301 DECLARE_uint64(wp_snapshot_cache_bits);
302 DECLARE_uint64(wp_commit_cache_bits);
303 #endif // !ROCKSDB_LITE
304
305 DECLARE_bool(adaptive_readahead);
306 DECLARE_bool(async_io);
307 DECLARE_string(wal_compression);
308 DECLARE_bool(verify_sst_unique_id_in_manifest);
309
310 DECLARE_int32(create_timestamped_snapshot_one_in);
311
312 DECLARE_bool(allow_data_in_errors);
313
314 // Tiered storage
315 DECLARE_bool(enable_tiered_storage); // set last_level_temperature
316 DECLARE_int64(preclude_last_level_data_seconds);
317 DECLARE_int64(preserve_internal_time_seconds);
318
319 DECLARE_int32(verify_iterator_with_expected_state_one_in);
320 DECLARE_bool(preserve_unverified_changes);
321
322 DECLARE_uint64(readahead_size);
323 DECLARE_uint64(initial_auto_readahead_size);
324 DECLARE_uint64(max_auto_readahead_size);
325 DECLARE_uint64(num_file_reads_for_auto_readahead);
326
327 constexpr long KB = 1024;
328 constexpr int kRandomValueMaxFactor = 3;
329 constexpr int kValueMaxLen = 100;
330
331 // wrapped posix environment
332 extern ROCKSDB_NAMESPACE::Env* db_stress_env;
333 extern ROCKSDB_NAMESPACE::Env* db_stress_listener_env;
334 extern std::shared_ptr<ROCKSDB_NAMESPACE::FaultInjectionTestFS> fault_fs_guard;
335
336 extern enum ROCKSDB_NAMESPACE::CompressionType compression_type_e;
337 extern enum ROCKSDB_NAMESPACE::CompressionType bottommost_compression_type_e;
338 extern enum ROCKSDB_NAMESPACE::ChecksumType checksum_type_e;
339
340 enum RepFactory { kSkipList, kHashSkipList, kVectorRep };
341
342 inline enum RepFactory StringToRepFactory(const char* ctype) {
343 assert(ctype);
344
345 if (!strcasecmp(ctype, "skip_list"))
346 return kSkipList;
347 else if (!strcasecmp(ctype, "prefix_hash"))
348 return kHashSkipList;
349 else if (!strcasecmp(ctype, "vector"))
350 return kVectorRep;
351
352 fprintf(stdout, "Cannot parse memreptable %s\n", ctype);
353 return kSkipList;
354 }
355
356 extern enum RepFactory FLAGS_rep_factory;
357
358 namespace ROCKSDB_NAMESPACE {
359 inline enum ROCKSDB_NAMESPACE::CompressionType StringToCompressionType(
360 const char* ctype) {
361 assert(ctype);
362
363 ROCKSDB_NAMESPACE::CompressionType ret_compression_type;
364
365 if (!strcasecmp(ctype, "disable")) {
366 ret_compression_type = ROCKSDB_NAMESPACE::kDisableCompressionOption;
367 } else if (!strcasecmp(ctype, "none")) {
368 ret_compression_type = ROCKSDB_NAMESPACE::kNoCompression;
369 } else if (!strcasecmp(ctype, "snappy")) {
370 ret_compression_type = ROCKSDB_NAMESPACE::kSnappyCompression;
371 } else if (!strcasecmp(ctype, "zlib")) {
372 ret_compression_type = ROCKSDB_NAMESPACE::kZlibCompression;
373 } else if (!strcasecmp(ctype, "bzip2")) {
374 ret_compression_type = ROCKSDB_NAMESPACE::kBZip2Compression;
375 } else if (!strcasecmp(ctype, "lz4")) {
376 ret_compression_type = ROCKSDB_NAMESPACE::kLZ4Compression;
377 } else if (!strcasecmp(ctype, "lz4hc")) {
378 ret_compression_type = ROCKSDB_NAMESPACE::kLZ4HCCompression;
379 } else if (!strcasecmp(ctype, "xpress")) {
380 ret_compression_type = ROCKSDB_NAMESPACE::kXpressCompression;
381 } else if (!strcasecmp(ctype, "zstd")) {
382 ret_compression_type = ROCKSDB_NAMESPACE::kZSTD;
383 } else {
384 fprintf(stderr, "Cannot parse compression type '%s'\n", ctype);
385 ret_compression_type =
386 ROCKSDB_NAMESPACE::kSnappyCompression; // default value
387 }
388 if (ret_compression_type != ROCKSDB_NAMESPACE::kDisableCompressionOption &&
389 !CompressionTypeSupported(ret_compression_type)) {
390 // Use no compression will be more portable but considering this is
391 // only a stress test and snappy is widely available. Use snappy here.
392 ret_compression_type = ROCKSDB_NAMESPACE::kSnappyCompression;
393 }
394 return ret_compression_type;
395 }
396
397 inline enum ROCKSDB_NAMESPACE::ChecksumType StringToChecksumType(
398 const char* ctype) {
399 assert(ctype);
400 auto iter = ROCKSDB_NAMESPACE::checksum_type_string_map.find(ctype);
401 if (iter != ROCKSDB_NAMESPACE::checksum_type_string_map.end()) {
402 return iter->second;
403 }
404 fprintf(stderr, "Cannot parse checksum type '%s'\n", ctype);
405 return ROCKSDB_NAMESPACE::kCRC32c;
406 }
407
408 inline std::string ChecksumTypeToString(ROCKSDB_NAMESPACE::ChecksumType ctype) {
409 auto iter = std::find_if(
410 ROCKSDB_NAMESPACE::checksum_type_string_map.begin(),
411 ROCKSDB_NAMESPACE::checksum_type_string_map.end(),
412 [&](const std::pair<std::string, ROCKSDB_NAMESPACE::ChecksumType>&
413 name_and_enum_val) { return name_and_enum_val.second == ctype; });
414 assert(iter != ROCKSDB_NAMESPACE::checksum_type_string_map.end());
415 return iter->first;
416 }
417
418 inline std::vector<std::string> SplitString(std::string src) {
419 std::vector<std::string> ret;
420 if (src.empty()) {
421 return ret;
422 }
423 size_t pos = 0;
424 size_t pos_comma;
425 while ((pos_comma = src.find(',', pos)) != std::string::npos) {
426 ret.push_back(src.substr(pos, pos_comma - pos));
427 pos = pos_comma + 1;
428 }
429 ret.push_back(src.substr(pos, src.length()));
430 return ret;
431 }
432
433 #ifdef _MSC_VER
434 #pragma warning(push)
435 // truncation of constant value on static_cast
436 #pragma warning(disable : 4309)
437 #endif
438 inline bool GetNextPrefix(const ROCKSDB_NAMESPACE::Slice& src, std::string* v) {
439 std::string ret = src.ToString();
440 for (int i = static_cast<int>(ret.size()) - 1; i >= 0; i--) {
441 if (ret[i] != static_cast<char>(255)) {
442 ret[i] = ret[i] + 1;
443 break;
444 } else if (i != 0) {
445 ret[i] = 0;
446 } else {
447 // all FF. No next prefix
448 return false;
449 }
450 }
451 *v = ret;
452 return true;
453 }
454 #ifdef _MSC_VER
455 #pragma warning(pop)
456 #endif
457
458 // Append `val` to `*key` in fixed-width big-endian format
459 extern inline void AppendIntToString(uint64_t val, std::string* key) {
460 // PutFixed64 uses little endian
461 PutFixed64(key, val);
462 // Reverse to get big endian
463 char* int_data = &((*key)[key->size() - sizeof(uint64_t)]);
464 for (size_t i = 0; i < sizeof(uint64_t) / 2; ++i) {
465 std::swap(int_data[i], int_data[sizeof(uint64_t) - 1 - i]);
466 }
467 }
468
469 // A struct for maintaining the parameters for generating variable length keys
470 struct KeyGenContext {
471 // Number of adjacent keys in one cycle of key lengths
472 uint64_t window;
473 // Number of keys of each possible length in a given window
474 std::vector<uint64_t> weights;
475 };
476 extern KeyGenContext key_gen_ctx;
477
478 // Generate a variable length key string from the given int64 val. The
479 // order of the keys is preserved. The key could be anywhere from 8 to
480 // max_key_len * 8 bytes.
481 // The algorithm picks the length based on the
482 // offset of the val within a configured window and the distribution of the
483 // number of keys of various lengths in that window. For example, if x, y, x are
484 // the weights assigned to each possible key length, the keys generated would be
485 // - {0}...{x-1}
486 // {(x-1),0}..{(x-1),(y-1)},{(x-1),(y-1),0}..{(x-1),(y-1),(z-1)} and so on.
487 // Additionally, a trailer of 0-7 bytes could be appended.
488 extern inline std::string Key(int64_t val) {
489 uint64_t window = key_gen_ctx.window;
490 size_t levels = key_gen_ctx.weights.size();
491 std::string key;
492 // Over-reserve and for now do not bother `shrink_to_fit()` since the key
493 // strings are transient.
494 key.reserve(FLAGS_max_key_len * 8);
495
496 uint64_t window_idx = static_cast<uint64_t>(val) / window;
497 uint64_t offset = static_cast<uint64_t>(val) % window;
498 for (size_t level = 0; level < levels; ++level) {
499 uint64_t weight = key_gen_ctx.weights[level];
500 uint64_t pfx;
501 if (level == 0) {
502 pfx = window_idx * weight;
503 } else {
504 pfx = 0;
505 }
506 pfx += offset >= weight ? weight - 1 : offset;
507 AppendIntToString(pfx, &key);
508 if (offset < weight) {
509 // Use the bottom 3 bits of offset as the number of trailing 'x's in the
510 // key. If the next key is going to be of the next level, then skip the
511 // trailer as it would break ordering. If the key length is already at
512 // max, skip the trailer.
513 if (offset < weight - 1 && level < levels - 1) {
514 size_t trailer_len = offset & 0x7;
515 key.append(trailer_len, 'x');
516 }
517 break;
518 }
519 offset -= weight;
520 }
521
522 return key;
523 }
524
525 // Given a string key, map it to an index into the expected values buffer
526 extern inline bool GetIntVal(std::string big_endian_key, uint64_t* key_p) {
527 size_t size_key = big_endian_key.size();
528 std::vector<uint64_t> prefixes;
529
530 assert(size_key <= key_gen_ctx.weights.size() * sizeof(uint64_t));
531
532 std::string little_endian_key;
533 little_endian_key.resize(size_key);
534 for (size_t start = 0; start + sizeof(uint64_t) <= size_key;
535 start += sizeof(uint64_t)) {
536 size_t end = start + sizeof(uint64_t);
537 for (size_t i = 0; i < sizeof(uint64_t); ++i) {
538 little_endian_key[start + i] = big_endian_key[end - 1 - i];
539 }
540 Slice little_endian_slice =
541 Slice(&little_endian_key[start], sizeof(uint64_t));
542 uint64_t pfx;
543 if (!GetFixed64(&little_endian_slice, &pfx)) {
544 return false;
545 }
546 prefixes.emplace_back(pfx);
547 }
548
549 uint64_t key = 0;
550 for (size_t i = 0; i < prefixes.size(); ++i) {
551 uint64_t pfx = prefixes[i];
552 key += (pfx / key_gen_ctx.weights[i]) * key_gen_ctx.window +
553 pfx % key_gen_ctx.weights[i];
554 if (i < prefixes.size() - 1) {
555 // The encoding writes a `key_gen_ctx.weights[i] - 1` that counts for
556 // `key_gen_ctx.weights[i]` when there are more prefixes to come. So we
557 // need to add back the one here as we're at a non-last prefix.
558 ++key;
559 }
560 }
561 *key_p = key;
562 return true;
563 }
564
565 // Given a string prefix, map it to the first corresponding index in the
566 // expected values buffer.
567 inline bool GetFirstIntValInPrefix(std::string big_endian_prefix,
568 uint64_t* key_p) {
569 size_t size_key = big_endian_prefix.size();
570 // Pad with zeros to make it a multiple of 8. This function may be called
571 // with a prefix, in which case we return the first index that falls
572 // inside or outside that prefix, dependeing on whether the prefix is
573 // the start of upper bound of a scan
574 unsigned int pad = sizeof(uint64_t) - (size_key % sizeof(uint64_t));
575 if (pad < sizeof(uint64_t)) {
576 big_endian_prefix.append(pad, '\0');
577 }
578 return GetIntVal(std::move(big_endian_prefix), key_p);
579 }
580
581 extern inline uint64_t GetPrefixKeyCount(const std::string& prefix,
582 const std::string& ub) {
583 uint64_t start = 0;
584 uint64_t end = 0;
585
586 if (!GetFirstIntValInPrefix(prefix, &start) ||
587 !GetFirstIntValInPrefix(ub, &end)) {
588 return 0;
589 }
590
591 return end - start;
592 }
593
594 extern inline std::string StringToHex(const std::string& str) {
595 std::string result = "0x";
596 result.append(Slice(str).ToString(true));
597 return result;
598 }
599
600 // Unified output format for double parameters
601 extern inline std::string FormatDoubleParam(double param) {
602 return std::to_string(param);
603 }
604
605 // Make sure that double parameter is a value we can reproduce by
606 // re-inputting the value printed.
607 extern inline void SanitizeDoubleParam(double* param) {
608 *param = std::atof(FormatDoubleParam(*param).c_str());
609 }
610
611 extern void PoolSizeChangeThread(void* v);
612
613 extern void DbVerificationThread(void* v);
614
615 extern void TimestampedSnapshotsThread(void* v);
616
617 extern void PrintKeyValue(int cf, uint64_t key, const char* value, size_t sz);
618
619 extern int64_t GenerateOneKey(ThreadState* thread, uint64_t iteration);
620
621 extern std::vector<int64_t> GenerateNKeys(ThreadState* thread, int num_keys,
622 uint64_t iteration);
623
624 extern size_t GenerateValue(uint32_t rand, char* v, size_t max_sz);
625 extern uint32_t GetValueBase(Slice s);
626
627 extern WideColumns GenerateWideColumns(uint32_t value_base, const Slice& slice);
628 extern WideColumns GenerateExpectedWideColumns(uint32_t value_base,
629 const Slice& slice);
630
631 extern StressTest* CreateCfConsistencyStressTest();
632 extern StressTest* CreateBatchedOpsStressTest();
633 extern StressTest* CreateNonBatchedOpsStressTest();
634 extern StressTest* CreateMultiOpsTxnsStressTest();
635 extern void CheckAndSetOptionsForMultiOpsTxnStressTest();
636 extern void InitializeHotKeyGenerator(double alpha);
637 extern int64_t GetOneHotKeyID(double rand_seed, int64_t max_key);
638
639 extern std::string GetNowNanos();
640
641 std::shared_ptr<FileChecksumGenFactory> GetFileChecksumImpl(
642 const std::string& name);
643
644 Status DeleteFilesInDirectory(const std::string& dirname);
645 Status SaveFilesInDirectory(const std::string& src_dirname,
646 const std::string& dst_dirname);
647 Status DestroyUnverifiedSubdir(const std::string& dirname);
648 Status InitUnverifiedSubdir(const std::string& dirname);
649 } // namespace ROCKSDB_NAMESPACE
650 #endif // GFLAGS