cf_options.cc 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322
  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. #include "options/cf_options.h"
  6. #include <cassert>
  7. #include <cinttypes>
  8. #include <iostream>
  9. #include <limits>
  10. #include <string>
  11. #include "logging/logging.h"
  12. #include "options/configurable_helper.h"
  13. #include "options/db_options.h"
  14. #include "options/options_helper.h"
  15. #include "options/options_parser.h"
  16. #include "port/port.h"
  17. #include "rocksdb/advanced_cache.h"
  18. #include "rocksdb/compaction_filter.h"
  19. #include "rocksdb/concurrent_task_limiter.h"
  20. #include "rocksdb/configurable.h"
  21. #include "rocksdb/convenience.h"
  22. #include "rocksdb/env.h"
  23. #include "rocksdb/file_system.h"
  24. #include "rocksdb/merge_operator.h"
  25. #include "rocksdb/options.h"
  26. #include "rocksdb/table.h"
  27. #include "rocksdb/utilities/object_registry.h"
  28. #include "rocksdb/utilities/options_type.h"
  29. #include "util/cast_util.h"
  30. // NOTE: in this file, many option flags that were deprecated
  31. // and removed from the rest of the code have to be kept here
  32. // and marked as kDeprecated in order to be able to read old
  33. // OPTIONS files.
  34. namespace ROCKSDB_NAMESPACE {
  35. static Status ParseCompressionOptions(const std::string& value,
  36. const std::string& name,
  37. CompressionOptions& compression_opts) {
  38. const char kDelimiter = ':';
  39. std::istringstream field_stream(value);
  40. std::string field;
  41. if (!std::getline(field_stream, field, kDelimiter)) {
  42. return Status::InvalidArgument("unable to parse the specified CF option " +
  43. name);
  44. }
  45. compression_opts.window_bits = ParseInt(field);
  46. if (!std::getline(field_stream, field, kDelimiter)) {
  47. return Status::InvalidArgument("unable to parse the specified CF option " +
  48. name);
  49. }
  50. compression_opts.level = ParseInt(field);
  51. if (!std::getline(field_stream, field, kDelimiter)) {
  52. return Status::InvalidArgument("unable to parse the specified CF option " +
  53. name);
  54. }
  55. compression_opts.strategy = ParseInt(field);
  56. // max_dict_bytes is optional for backwards compatibility
  57. if (!field_stream.eof()) {
  58. if (!std::getline(field_stream, field, kDelimiter)) {
  59. return Status::InvalidArgument(
  60. "unable to parse the specified CF option " + name);
  61. }
  62. compression_opts.max_dict_bytes = ParseInt(field);
  63. }
  64. // zstd_max_train_bytes is optional for backwards compatibility
  65. if (!field_stream.eof()) {
  66. if (!std::getline(field_stream, field, kDelimiter)) {
  67. return Status::InvalidArgument(
  68. "unable to parse the specified CF option " + name);
  69. }
  70. compression_opts.zstd_max_train_bytes = ParseInt(field);
  71. }
  72. // parallel_threads is optional for backwards compatibility
  73. if (!field_stream.eof()) {
  74. if (!std::getline(field_stream, field, kDelimiter)) {
  75. return Status::InvalidArgument(
  76. "unable to parse the specified CF option " + name);
  77. }
  78. // Since parallel_threads comes before enabled but was added optionally
  79. // later, we need to check if this is the final token (meaning it is the
  80. // enabled bit), or if there are more tokens (meaning this one is
  81. // parallel_threads).
  82. if (!field_stream.eof()) {
  83. compression_opts.parallel_threads = ParseInt(field);
  84. } else {
  85. // parallel_threads is not serialized with this format, but enabled is
  86. compression_opts.enabled = ParseBoolean("", field);
  87. }
  88. }
  89. // enabled is optional for backwards compatibility
  90. if (!field_stream.eof()) {
  91. if (!std::getline(field_stream, field, kDelimiter)) {
  92. return Status::InvalidArgument(
  93. "unable to parse the specified CF option " + name);
  94. }
  95. compression_opts.enabled = ParseBoolean("", field);
  96. }
  97. // max_dict_buffer_bytes is optional for backwards compatibility
  98. if (!field_stream.eof()) {
  99. if (!std::getline(field_stream, field, kDelimiter)) {
  100. return Status::InvalidArgument(
  101. "unable to parse the specified CF option " + name);
  102. }
  103. compression_opts.max_dict_buffer_bytes = ParseUint64(field);
  104. }
  105. // use_zstd_dict_trainer is optional for backwards compatibility
  106. if (!field_stream.eof()) {
  107. if (!std::getline(field_stream, field, kDelimiter)) {
  108. return Status::InvalidArgument(
  109. "unable to parse the specified CF option " + name);
  110. }
  111. compression_opts.use_zstd_dict_trainer = ParseBoolean("", field);
  112. }
  113. if (!field_stream.eof()) {
  114. return Status::InvalidArgument("unable to parse the specified CF option " +
  115. name);
  116. }
  117. return Status::OK();
  118. }
  119. static Status TableFactoryParseFn(const ConfigOptions& opts,
  120. const std::string& name,
  121. const std::string& value, void* addr) {
  122. assert(addr);
  123. auto table_factory = static_cast<std::shared_ptr<TableFactory>*>(addr);
  124. // The general approach to mutating a table factory is to clone it, then
  125. // mutate and save the clone. This avoids race conditions between SetOptions
  126. // and consumers of table_factory/table options by leveraging
  127. // MutableCFOptions infrastructure to track the table_factory pointer.
  128. // However, in the atypical case of setting an option that is safely mutable
  129. // under something pointed to by the table factory, we should avoid cloning.
  130. // The simple way to detect that case is to try with "mutable_options_only"
  131. // and see if it works. If it does, we are finished. If not, we proceed to
  132. // cloning etc.
  133. //
  134. // The canonical example of what is handled here is
  135. // table_factory.filter_policy.bloom_before_level for RibbonFilterPolicy.
  136. if (table_factory->get() != nullptr && !EndsWith(name, "table_factory")) {
  137. ConfigOptions opts_mutable_only{opts};
  138. opts_mutable_only.mutable_options_only = true;
  139. Status s =
  140. table_factory->get()->ConfigureOption(opts_mutable_only, name, value);
  141. if (s.ok()) {
  142. return s;
  143. }
  144. s.PermitUncheckedError();
  145. }
  146. std::shared_ptr<TableFactory> new_factory;
  147. Status s;
  148. if (name == "block_based_table_factory") {
  149. if (table_factory->get() != nullptr) {
  150. std::string factory_name = table_factory->get()->Name();
  151. if (factory_name == TableFactory::kBlockBasedTableName()) {
  152. new_factory = table_factory->get()->Clone();
  153. } else {
  154. s = Status::InvalidArgument("Cannot modify " + factory_name + " as " +
  155. name);
  156. return s;
  157. }
  158. } else {
  159. new_factory.reset(NewBlockBasedTableFactory());
  160. }
  161. // Passing an object string to configure/instantiate a table factory
  162. s = new_factory->ConfigureFromString(opts, value);
  163. } else if (name == "plain_table_factory") {
  164. if (table_factory->get() != nullptr) {
  165. std::string factory_name = table_factory->get()->Name();
  166. if (factory_name == TableFactory::kPlainTableName()) {
  167. new_factory = table_factory->get()->Clone();
  168. } else {
  169. s = Status::InvalidArgument("Cannot modify " + factory_name + " as " +
  170. name);
  171. return s;
  172. }
  173. } else {
  174. new_factory.reset(NewPlainTableFactory());
  175. }
  176. // Passing an object string to configure/instantiate a table factory
  177. s = new_factory->ConfigureFromString(opts, value);
  178. } else if (name == "table_factory" || name == OptionTypeInfo::kIdPropName()) {
  179. // Related to OptionTypeInfo::AsCustomSharedPtr
  180. if (value.empty()) {
  181. new_factory = nullptr;
  182. } else {
  183. s = TableFactory::CreateFromString(opts, value, &new_factory);
  184. }
  185. } else if (table_factory->get() != nullptr) {
  186. new_factory = table_factory->get()->Clone();
  187. // Presumably passing a value for a specific field of the table factory
  188. s = new_factory->ConfigureOption(opts, name, value);
  189. } else {
  190. s = Status::NotFound("Unable to instantiate a table factory from option: ",
  191. name);
  192. return s;
  193. }
  194. // Only keep the modified clone if everything went OK
  195. if (s.ok()) {
  196. *table_factory = std::move(new_factory);
  197. }
  198. return s;
  199. }
  200. const std::string kOptNameBMCompOpts = "bottommost_compression_opts";
  201. const std::string kOptNameCompOpts = "compression_opts";
  202. // OptionTypeInfo map for CompressionOptions
  203. static std::unordered_map<std::string, OptionTypeInfo>
  204. compression_options_type_info = {
  205. {"window_bits",
  206. {offsetof(struct CompressionOptions, window_bits), OptionType::kInt,
  207. OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
  208. {"level",
  209. {offsetof(struct CompressionOptions, level), OptionType::kInt,
  210. OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
  211. {"strategy",
  212. {offsetof(struct CompressionOptions, strategy), OptionType::kInt,
  213. OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
  214. {"max_compressed_bytes_per_kb",
  215. {offsetof(struct CompressionOptions, max_compressed_bytes_per_kb),
  216. OptionType::kInt, OptionVerificationType::kNormal,
  217. OptionTypeFlags::kMutable}},
  218. {"max_dict_bytes",
  219. {offsetof(struct CompressionOptions, max_dict_bytes), OptionType::kInt,
  220. OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
  221. {"zstd_max_train_bytes",
  222. {offsetof(struct CompressionOptions, zstd_max_train_bytes),
  223. OptionType::kUInt32T, OptionVerificationType::kNormal,
  224. OptionTypeFlags::kMutable}},
  225. {"parallel_threads",
  226. {offsetof(struct CompressionOptions, parallel_threads),
  227. OptionType::kUInt32T, OptionVerificationType::kNormal,
  228. OptionTypeFlags::kMutable}},
  229. {"enabled",
  230. {offsetof(struct CompressionOptions, enabled), OptionType::kBoolean,
  231. OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
  232. {"max_dict_buffer_bytes",
  233. {offsetof(struct CompressionOptions, max_dict_buffer_bytes),
  234. OptionType::kUInt64T, OptionVerificationType::kNormal,
  235. OptionTypeFlags::kMutable}},
  236. {"use_zstd_dict_trainer",
  237. {offsetof(struct CompressionOptions, use_zstd_dict_trainer),
  238. OptionType::kBoolean, OptionVerificationType::kNormal,
  239. OptionTypeFlags::kMutable}},
  240. {"checksum",
  241. {offsetof(struct CompressionOptions, checksum), OptionType::kBoolean,
  242. OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
  243. };
  244. static std::unordered_map<std::string, OptionTypeInfo>
  245. file_temperature_age_type_info = {
  246. {"temperature",
  247. {offsetof(struct FileTemperatureAge, temperature),
  248. OptionType::kTemperature, OptionVerificationType::kNormal,
  249. OptionTypeFlags::kMutable}},
  250. {"age",
  251. {offsetof(struct FileTemperatureAge, age), OptionType::kUInt64T,
  252. OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
  253. };
  254. static std::unordered_map<std::string, OptionTypeInfo>
  255. fifo_compaction_options_type_info = {
  256. {"max_table_files_size",
  257. {offsetof(struct CompactionOptionsFIFO, max_table_files_size),
  258. OptionType::kUInt64T, OptionVerificationType::kNormal,
  259. OptionTypeFlags::kMutable}},
  260. {"age_for_warm",
  261. {offsetof(struct CompactionOptionsFIFO, age_for_warm),
  262. OptionType::kUInt64T, OptionVerificationType::kNormal,
  263. OptionTypeFlags::kMutable}},
  264. {"ttl",
  265. {0, OptionType::kUInt64T, OptionVerificationType::kDeprecated,
  266. OptionTypeFlags::kNone}},
  267. {"allow_compaction",
  268. {offsetof(struct CompactionOptionsFIFO, allow_compaction),
  269. OptionType::kBoolean, OptionVerificationType::kNormal,
  270. OptionTypeFlags::kMutable}},
  271. {"file_temperature_age_thresholds",
  272. OptionTypeInfo::Vector<struct FileTemperatureAge>(
  273. offsetof(struct CompactionOptionsFIFO,
  274. file_temperature_age_thresholds),
  275. OptionVerificationType::kNormal, OptionTypeFlags::kMutable,
  276. OptionTypeInfo::Struct("file_temperature_age_thresholds",
  277. &file_temperature_age_type_info, 0,
  278. OptionVerificationType::kNormal,
  279. OptionTypeFlags::kMutable))},
  280. {"allow_trivial_copy_when_change_temperature",
  281. {offsetof(struct CompactionOptionsFIFO,
  282. allow_trivial_copy_when_change_temperature),
  283. OptionType::kBoolean, OptionVerificationType::kNormal,
  284. OptionTypeFlags::kMutable}},
  285. {"trivial_copy_buffer_size",
  286. {offsetof(struct CompactionOptionsFIFO, trivial_copy_buffer_size),
  287. OptionType::kUInt64T, OptionVerificationType::kNormal,
  288. OptionTypeFlags::kMutable}}};
  289. static std::unordered_map<std::string, OptionTypeInfo>
  290. universal_compaction_options_type_info = {
  291. {"size_ratio",
  292. {offsetof(class CompactionOptionsUniversal, size_ratio),
  293. OptionType::kUInt, OptionVerificationType::kNormal,
  294. OptionTypeFlags::kMutable}},
  295. {"min_merge_width",
  296. {offsetof(class CompactionOptionsUniversal, min_merge_width),
  297. OptionType::kUInt, OptionVerificationType::kNormal,
  298. OptionTypeFlags::kMutable}},
  299. {"max_merge_width",
  300. {offsetof(class CompactionOptionsUniversal, max_merge_width),
  301. OptionType::kUInt, OptionVerificationType::kNormal,
  302. OptionTypeFlags::kMutable}},
  303. {"max_size_amplification_percent",
  304. {offsetof(class CompactionOptionsUniversal,
  305. max_size_amplification_percent),
  306. OptionType::kUInt, OptionVerificationType::kNormal,
  307. OptionTypeFlags::kMutable}},
  308. {"compression_size_percent",
  309. {offsetof(class CompactionOptionsUniversal, compression_size_percent),
  310. OptionType::kInt, OptionVerificationType::kNormal,
  311. OptionTypeFlags::kMutable}},
  312. {"max_read_amp",
  313. {offsetof(class CompactionOptionsUniversal, max_read_amp),
  314. OptionType::kInt, OptionVerificationType::kNormal,
  315. OptionTypeFlags::kMutable}},
  316. {"stop_style",
  317. {offsetof(class CompactionOptionsUniversal, stop_style),
  318. OptionType::kCompactionStopStyle, OptionVerificationType::kNormal,
  319. OptionTypeFlags::kMutable}},
  320. {"incremental",
  321. {offsetof(class CompactionOptionsUniversal, incremental),
  322. OptionType::kBoolean, OptionVerificationType::kNormal,
  323. OptionTypeFlags::kMutable}},
  324. {"allow_trivial_move",
  325. {offsetof(class CompactionOptionsUniversal, allow_trivial_move),
  326. OptionType::kBoolean, OptionVerificationType::kNormal,
  327. OptionTypeFlags::kMutable}},
  328. {"reduce_file_locking",
  329. {offsetof(class CompactionOptionsUniversal, reduce_file_locking),
  330. OptionType::kBoolean, OptionVerificationType::kNormal,
  331. OptionTypeFlags::kMutable}}};
  332. static std::unordered_map<std::string, OptionTypeInfo>
  333. cf_mutable_options_type_info = {
  334. {"report_bg_io_stats",
  335. {offsetof(struct MutableCFOptions, report_bg_io_stats),
  336. OptionType::kBoolean, OptionVerificationType::kNormal,
  337. OptionTypeFlags::kMutable}},
  338. {"disable_auto_compactions",
  339. {offsetof(struct MutableCFOptions, disable_auto_compactions),
  340. OptionType::kBoolean, OptionVerificationType::kNormal,
  341. OptionTypeFlags::kMutable}},
  342. {"table_factory",
  343. {offsetof(struct MutableCFOptions, table_factory),
  344. OptionType::kCustomizable, OptionVerificationType::kByName,
  345. OptionTypeFlags::kShared | OptionTypeFlags::kCompareLoose |
  346. OptionTypeFlags::kStringNameOnly | OptionTypeFlags::kDontPrepare |
  347. OptionTypeFlags::kMutable,
  348. TableFactoryParseFn}},
  349. {"block_based_table_factory",
  350. {offsetof(struct MutableCFOptions, table_factory),
  351. OptionType::kCustomizable, OptionVerificationType::kAlias,
  352. OptionTypeFlags::kShared | OptionTypeFlags::kCompareLoose |
  353. OptionTypeFlags::kMutable,
  354. TableFactoryParseFn}},
  355. {"plain_table_factory",
  356. {offsetof(struct MutableCFOptions, table_factory),
  357. OptionType::kCustomizable, OptionVerificationType::kAlias,
  358. OptionTypeFlags::kShared | OptionTypeFlags::kCompareLoose |
  359. OptionTypeFlags::kMutable,
  360. TableFactoryParseFn}},
  361. {"filter_deletes",
  362. {0, OptionType::kBoolean, OptionVerificationType::kDeprecated,
  363. OptionTypeFlags::kMutable}},
  364. {"check_flush_compaction_key_order",
  365. {0, OptionType::kBoolean, OptionVerificationType::kDeprecated,
  366. OptionTypeFlags::kMutable}},
  367. {"paranoid_file_checks",
  368. {offsetof(struct MutableCFOptions, paranoid_file_checks),
  369. OptionType::kBoolean, OptionVerificationType::kNormal,
  370. OptionTypeFlags::kMutable}},
  371. {"verify_checksums_in_compaction",
  372. {0, OptionType::kBoolean, OptionVerificationType::kDeprecated,
  373. OptionTypeFlags::kMutable}},
  374. {"soft_pending_compaction_bytes_limit",
  375. {offsetof(struct MutableCFOptions,
  376. soft_pending_compaction_bytes_limit),
  377. OptionType::kUInt64T, OptionVerificationType::kNormal,
  378. OptionTypeFlags::kMutable}},
  379. {"hard_pending_compaction_bytes_limit",
  380. {offsetof(struct MutableCFOptions,
  381. hard_pending_compaction_bytes_limit),
  382. OptionType::kUInt64T, OptionVerificationType::kNormal,
  383. OptionTypeFlags::kMutable}},
  384. {"hard_rate_limit",
  385. {0, OptionType::kDouble, OptionVerificationType::kDeprecated,
  386. OptionTypeFlags::kMutable}},
  387. {"soft_rate_limit",
  388. {0, OptionType::kDouble, OptionVerificationType::kDeprecated,
  389. OptionTypeFlags::kMutable}},
  390. {"max_compaction_bytes",
  391. {offsetof(struct MutableCFOptions, max_compaction_bytes),
  392. OptionType::kUInt64T, OptionVerificationType::kNormal,
  393. OptionTypeFlags::kMutable}},
  394. {"ignore_max_compaction_bytes_for_input",
  395. {0, OptionType::kBoolean, OptionVerificationType::kDeprecated,
  396. OptionTypeFlags::kMutable}},
  397. {"expanded_compaction_factor",
  398. {0, OptionType::kInt, OptionVerificationType::kDeprecated,
  399. OptionTypeFlags::kMutable}},
  400. {"level0_file_num_compaction_trigger",
  401. {offsetof(struct MutableCFOptions, level0_file_num_compaction_trigger),
  402. OptionType::kInt, OptionVerificationType::kNormal,
  403. OptionTypeFlags::kMutable}},
  404. {"level0_slowdown_writes_trigger",
  405. {offsetof(struct MutableCFOptions, level0_slowdown_writes_trigger),
  406. OptionType::kInt, OptionVerificationType::kNormal,
  407. OptionTypeFlags::kMutable}},
  408. {"level0_stop_writes_trigger",
  409. {offsetof(struct MutableCFOptions, level0_stop_writes_trigger),
  410. OptionType::kInt, OptionVerificationType::kNormal,
  411. OptionTypeFlags::kMutable}},
  412. {"max_grandparent_overlap_factor",
  413. {0, OptionType::kInt, OptionVerificationType::kDeprecated,
  414. OptionTypeFlags::kMutable}},
  415. {"max_write_buffer_number",
  416. {offsetof(struct MutableCFOptions, max_write_buffer_number),
  417. OptionType::kInt, OptionVerificationType::kNormal,
  418. OptionTypeFlags::kMutable}},
  419. {"source_compaction_factor",
  420. {0, OptionType::kInt, OptionVerificationType::kDeprecated,
  421. OptionTypeFlags::kMutable}},
  422. {"target_file_size_multiplier",
  423. {offsetof(struct MutableCFOptions, target_file_size_multiplier),
  424. OptionType::kInt, OptionVerificationType::kNormal,
  425. OptionTypeFlags::kMutable}},
  426. {"arena_block_size",
  427. {offsetof(struct MutableCFOptions, arena_block_size),
  428. OptionType::kSizeT, OptionVerificationType::kNormal,
  429. OptionTypeFlags::kMutable}},
  430. {"inplace_update_num_locks",
  431. {offsetof(struct MutableCFOptions, inplace_update_num_locks),
  432. OptionType::kSizeT, OptionVerificationType::kNormal,
  433. OptionTypeFlags::kMutable}},
  434. {"max_successive_merges",
  435. {offsetof(struct MutableCFOptions, max_successive_merges),
  436. OptionType::kSizeT, OptionVerificationType::kNormal,
  437. OptionTypeFlags::kMutable}},
  438. {"strict_max_successive_merges",
  439. {offsetof(struct MutableCFOptions, strict_max_successive_merges),
  440. OptionType::kBoolean, OptionVerificationType::kNormal,
  441. OptionTypeFlags::kMutable}},
  442. {"memtable_huge_page_size",
  443. {offsetof(struct MutableCFOptions, memtable_huge_page_size),
  444. OptionType::kSizeT, OptionVerificationType::kNormal,
  445. OptionTypeFlags::kMutable}},
  446. {"memtable_prefix_bloom_huge_page_tlb_size",
  447. {0, OptionType::kSizeT, OptionVerificationType::kDeprecated,
  448. OptionTypeFlags::kMutable}},
  449. {"write_buffer_size",
  450. {offsetof(struct MutableCFOptions, write_buffer_size),
  451. OptionType::kSizeT, OptionVerificationType::kNormal,
  452. OptionTypeFlags::kMutable}},
  453. {"memtable_prefix_bloom_bits",
  454. {0, OptionType::kUInt32T, OptionVerificationType::kDeprecated,
  455. OptionTypeFlags::kMutable}},
  456. {"memtable_prefix_bloom_size_ratio",
  457. {offsetof(struct MutableCFOptions, memtable_prefix_bloom_size_ratio),
  458. OptionType::kDouble, OptionVerificationType::kNormal,
  459. OptionTypeFlags::kMutable}},
  460. {"memtable_prefix_bloom_probes",
  461. {0, OptionType::kUInt32T, OptionVerificationType::kDeprecated,
  462. OptionTypeFlags::kMutable}},
  463. {"memtable_whole_key_filtering",
  464. {offsetof(struct MutableCFOptions, memtable_whole_key_filtering),
  465. OptionType::kBoolean, OptionVerificationType::kNormal,
  466. OptionTypeFlags::kMutable}},
  467. {"min_partial_merge_operands",
  468. {0, OptionType::kUInt32T, OptionVerificationType::kDeprecated,
  469. OptionTypeFlags::kMutable}},
  470. {"max_bytes_for_level_base",
  471. {offsetof(struct MutableCFOptions, max_bytes_for_level_base),
  472. OptionType::kUInt64T, OptionVerificationType::kNormal,
  473. OptionTypeFlags::kMutable}},
  474. {"snap_refresh_nanos",
  475. {0, OptionType::kUInt64T, OptionVerificationType::kDeprecated,
  476. OptionTypeFlags::kMutable}},
  477. {"max_bytes_for_level_multiplier",
  478. {offsetof(struct MutableCFOptions, max_bytes_for_level_multiplier),
  479. OptionType::kDouble, OptionVerificationType::kNormal,
  480. OptionTypeFlags::kMutable}},
  481. {"max_bytes_for_level_multiplier_additional",
  482. OptionTypeInfo::Vector<int>(
  483. offsetof(struct MutableCFOptions,
  484. max_bytes_for_level_multiplier_additional),
  485. OptionVerificationType::kNormal, OptionTypeFlags::kMutable,
  486. {0, OptionType::kInt})},
  487. {"max_sequential_skip_in_iterations",
  488. {offsetof(struct MutableCFOptions, max_sequential_skip_in_iterations),
  489. OptionType::kUInt64T, OptionVerificationType::kNormal,
  490. OptionTypeFlags::kMutable}},
  491. {"target_file_size_base",
  492. {offsetof(struct MutableCFOptions, target_file_size_base),
  493. OptionType::kUInt64T, OptionVerificationType::kNormal,
  494. OptionTypeFlags::kMutable}},
  495. {"compression",
  496. {offsetof(struct MutableCFOptions, compression),
  497. OptionType::kCompressionType, OptionVerificationType::kNormal,
  498. OptionTypeFlags::kMutable}},
  499. {"prefix_extractor",
  500. OptionTypeInfo::AsCustomSharedPtr<const SliceTransform>(
  501. offsetof(struct MutableCFOptions, prefix_extractor),
  502. OptionVerificationType::kByNameAllowNull,
  503. (OptionTypeFlags::kMutable | OptionTypeFlags::kAllowNull))},
  504. {"compaction_options_fifo",
  505. OptionTypeInfo::Struct(
  506. "compaction_options_fifo", &fifo_compaction_options_type_info,
  507. offsetof(struct MutableCFOptions, compaction_options_fifo),
  508. OptionVerificationType::kNormal, OptionTypeFlags::kMutable)
  509. .SetParseFunc([](const ConfigOptions& opts,
  510. const std::string& name, const std::string& value,
  511. void* addr) {
  512. // This is to handle backward compatibility, where
  513. // compaction_options_fifo could be assigned a single scalar
  514. // value, say, like "23", which would be assigned to
  515. // max_table_files_size.
  516. if (name == "compaction_options_fifo" &&
  517. value.find('=') == std::string::npos) {
  518. // Old format. Parse just a single uint64_t value.
  519. auto options = static_cast<CompactionOptionsFIFO*>(addr);
  520. options->max_table_files_size = ParseUint64(value);
  521. return Status::OK();
  522. } else {
  523. return OptionTypeInfo::ParseStruct(
  524. opts, "compaction_options_fifo",
  525. &fifo_compaction_options_type_info, name, value, addr);
  526. }
  527. })},
  528. {"compaction_options_universal",
  529. OptionTypeInfo::Struct(
  530. "compaction_options_universal",
  531. &universal_compaction_options_type_info,
  532. offsetof(struct MutableCFOptions, compaction_options_universal),
  533. OptionVerificationType::kNormal, OptionTypeFlags::kMutable)},
  534. {"ttl",
  535. {offsetof(struct MutableCFOptions, ttl), OptionType::kUInt64T,
  536. OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
  537. {"periodic_compaction_seconds",
  538. {offsetof(struct MutableCFOptions, periodic_compaction_seconds),
  539. OptionType::kUInt64T, OptionVerificationType::kNormal,
  540. OptionTypeFlags::kMutable}},
  541. {"preclude_last_level_data_seconds",
  542. {offsetof(struct MutableCFOptions, preclude_last_level_data_seconds),
  543. OptionType::kUInt64T, OptionVerificationType::kNormal,
  544. OptionTypeFlags::kMutable}},
  545. {"preserve_internal_time_seconds",
  546. {offsetof(struct MutableCFOptions, preserve_internal_time_seconds),
  547. OptionType::kUInt64T, OptionVerificationType::kNormal,
  548. OptionTypeFlags::kMutable}},
  549. {"bottommost_temperature",
  550. {0, OptionType::kTemperature, OptionVerificationType::kDeprecated,
  551. OptionTypeFlags::kMutable}},
  552. {"last_level_temperature",
  553. {offsetof(struct MutableCFOptions, last_level_temperature),
  554. OptionType::kTemperature, OptionVerificationType::kNormal,
  555. OptionTypeFlags::kMutable}},
  556. {"default_write_temperature",
  557. {offsetof(struct MutableCFOptions, default_write_temperature),
  558. OptionType::kTemperature, OptionVerificationType::kNormal,
  559. OptionTypeFlags::kMutable}},
  560. {"enable_blob_files",
  561. {offsetof(struct MutableCFOptions, enable_blob_files),
  562. OptionType::kBoolean, OptionVerificationType::kNormal,
  563. OptionTypeFlags::kMutable}},
  564. {"min_blob_size",
  565. {offsetof(struct MutableCFOptions, min_blob_size),
  566. OptionType::kUInt64T, OptionVerificationType::kNormal,
  567. OptionTypeFlags::kMutable}},
  568. {"blob_file_size",
  569. {offsetof(struct MutableCFOptions, blob_file_size),
  570. OptionType::kUInt64T, OptionVerificationType::kNormal,
  571. OptionTypeFlags::kMutable}},
  572. {"blob_compression_type",
  573. {offsetof(struct MutableCFOptions, blob_compression_type),
  574. OptionType::kCompressionType, OptionVerificationType::kNormal,
  575. OptionTypeFlags::kMutable}},
  576. {"enable_blob_garbage_collection",
  577. {offsetof(struct MutableCFOptions, enable_blob_garbage_collection),
  578. OptionType::kBoolean, OptionVerificationType::kNormal,
  579. OptionTypeFlags::kMutable}},
  580. {"blob_garbage_collection_age_cutoff",
  581. {offsetof(struct MutableCFOptions, blob_garbage_collection_age_cutoff),
  582. OptionType::kDouble, OptionVerificationType::kNormal,
  583. OptionTypeFlags::kMutable}},
  584. {"blob_garbage_collection_force_threshold",
  585. {offsetof(struct MutableCFOptions,
  586. blob_garbage_collection_force_threshold),
  587. OptionType::kDouble, OptionVerificationType::kNormal,
  588. OptionTypeFlags::kMutable}},
  589. {"blob_compaction_readahead_size",
  590. {offsetof(struct MutableCFOptions, blob_compaction_readahead_size),
  591. OptionType::kUInt64T, OptionVerificationType::kNormal,
  592. OptionTypeFlags::kMutable}},
  593. {"blob_file_starting_level",
  594. {offsetof(struct MutableCFOptions, blob_file_starting_level),
  595. OptionType::kInt, OptionVerificationType::kNormal,
  596. OptionTypeFlags::kMutable}},
  597. {"prepopulate_blob_cache",
  598. OptionTypeInfo::Enum<PrepopulateBlobCache>(
  599. offsetof(struct MutableCFOptions, prepopulate_blob_cache),
  600. &prepopulate_blob_cache_string_map, OptionTypeFlags::kMutable)},
  601. {"sample_for_compression",
  602. {offsetof(struct MutableCFOptions, sample_for_compression),
  603. OptionType::kUInt64T, OptionVerificationType::kNormal,
  604. OptionTypeFlags::kMutable}},
  605. {"bottommost_compression",
  606. {offsetof(struct MutableCFOptions, bottommost_compression),
  607. OptionType::kCompressionType, OptionVerificationType::kNormal,
  608. OptionTypeFlags::kMutable}},
  609. {"compression_per_level",
  610. OptionTypeInfo::Vector<CompressionType>(
  611. offsetof(struct MutableCFOptions, compression_per_level),
  612. OptionVerificationType::kNormal, OptionTypeFlags::kMutable,
  613. {0, OptionType::kCompressionType})},
  614. {"experimental_mempurge_threshold",
  615. {offsetof(struct MutableCFOptions, experimental_mempurge_threshold),
  616. OptionType::kDouble, OptionVerificationType::kNormal,
  617. OptionTypeFlags::kMutable}},
  618. {"memtable_protection_bytes_per_key",
  619. {offsetof(struct MutableCFOptions, memtable_protection_bytes_per_key),
  620. OptionType::kUInt32T, OptionVerificationType::kNormal,
  621. OptionTypeFlags::kMutable}},
  622. {"bottommost_file_compaction_delay",
  623. {offsetof(struct MutableCFOptions, bottommost_file_compaction_delay),
  624. OptionType::kUInt32T, OptionVerificationType::kNormal,
  625. OptionTypeFlags::kMutable}},
  626. {"uncache_aggressiveness",
  627. {offsetof(struct MutableCFOptions, uncache_aggressiveness),
  628. OptionType::kUInt32T, OptionVerificationType::kNormal,
  629. OptionTypeFlags::kMutable}},
  630. {"block_protection_bytes_per_key",
  631. {offsetof(struct MutableCFOptions, block_protection_bytes_per_key),
  632. OptionType::kUInt8T, OptionVerificationType::kNormal,
  633. OptionTypeFlags::kMutable}},
  634. {"paranoid_memory_checks",
  635. {offsetof(struct MutableCFOptions, paranoid_memory_checks),
  636. OptionType::kBoolean, OptionVerificationType::kNormal,
  637. OptionTypeFlags::kMutable}},
  638. {"memtable_veirfy_per_key_checksum_on_seek",
  639. {offsetof(struct MutableCFOptions,
  640. memtable_veirfy_per_key_checksum_on_seek),
  641. OptionType::kBoolean, OptionVerificationType::kNormal,
  642. OptionTypeFlags::kMutable}},
  643. {kOptNameCompOpts,
  644. OptionTypeInfo::Struct(
  645. kOptNameCompOpts, &compression_options_type_info,
  646. offsetof(struct MutableCFOptions, compression_opts),
  647. OptionVerificationType::kNormal,
  648. (OptionTypeFlags::kMutable | OptionTypeFlags::kCompareNever),
  649. [](const ConfigOptions& opts, const std::string& name,
  650. const std::string& value, void* addr) {
  651. // This is to handle backward compatibility, where
  652. // compression_options was a ":" separated list.
  653. if (name == kOptNameCompOpts &&
  654. value.find('=') == std::string::npos) {
  655. auto* compression = static_cast<CompressionOptions*>(addr);
  656. return ParseCompressionOptions(value, name, *compression);
  657. } else {
  658. return OptionTypeInfo::ParseStruct(
  659. opts, kOptNameCompOpts, &compression_options_type_info,
  660. name, value, addr);
  661. }
  662. })},
  663. {kOptNameBMCompOpts,
  664. OptionTypeInfo::Struct(
  665. kOptNameBMCompOpts, &compression_options_type_info,
  666. offsetof(struct MutableCFOptions, bottommost_compression_opts),
  667. OptionVerificationType::kNormal,
  668. (OptionTypeFlags::kMutable | OptionTypeFlags::kCompareNever),
  669. [](const ConfigOptions& opts, const std::string& name,
  670. const std::string& value, void* addr) {
  671. // This is to handle backward compatibility, where
  672. // compression_options was a ":" separated list.
  673. if (name == kOptNameBMCompOpts &&
  674. value.find('=') == std::string::npos) {
  675. auto* compression = static_cast<CompressionOptions*>(addr);
  676. return ParseCompressionOptions(value, name, *compression);
  677. } else {
  678. return OptionTypeInfo::ParseStruct(
  679. opts, kOptNameBMCompOpts, &compression_options_type_info,
  680. name, value, addr);
  681. }
  682. })},
  683. {"compression_manager",
  684. OptionTypeInfo::AsCustomSharedPtr<CompressionManager>(
  685. offsetof(struct MutableCFOptions, compression_manager),
  686. OptionVerificationType::kByNameAllowNull,
  687. (OptionTypeFlags::kMutable | OptionTypeFlags::kAllowNull))},
  688. // End special case properties
  689. {"memtable_max_range_deletions",
  690. {offsetof(struct MutableCFOptions, memtable_max_range_deletions),
  691. OptionType::kUInt32T, OptionVerificationType::kNormal,
  692. OptionTypeFlags::kMutable}},
  693. {"memtable_op_scan_flush_trigger",
  694. {offsetof(struct MutableCFOptions, memtable_op_scan_flush_trigger),
  695. OptionType::kUInt32T, OptionVerificationType::kNormal,
  696. OptionTypeFlags::kMutable}},
  697. {"memtable_avg_op_scan_flush_trigger",
  698. {offsetof(struct MutableCFOptions, memtable_avg_op_scan_flush_trigger),
  699. OptionType::kUInt32T, OptionVerificationType::kNormal,
  700. OptionTypeFlags::kMutable}},
  701. };
  702. static std::unordered_map<std::string, OptionTypeInfo>
  703. cf_immutable_options_type_info = {
  704. /* not yet supported
  705. CompressionOptions compression_opts;
  706. TablePropertiesCollectorFactories table_properties_collector_factories;
  707. using TablePropertiesCollectorFactories =
  708. std::vector<std::shared_ptr<TablePropertiesCollectorFactory>>;
  709. UpdateStatus (*inplace_callback)(char* existing_value,
  710. uint34_t* existing_value_size,
  711. Slice delta_value,
  712. std::string* merged_value);
  713. std::vector<DbPath> cf_paths;
  714. */
  715. {"compaction_measure_io_stats",
  716. {0, OptionType::kBoolean, OptionVerificationType::kDeprecated,
  717. OptionTypeFlags::kNone}},
  718. {"purge_redundant_kvs_while_flush",
  719. {0, OptionType::kBoolean, OptionVerificationType::kDeprecated,
  720. OptionTypeFlags::kNone}},
  721. {"inplace_update_support",
  722. {offsetof(struct ImmutableCFOptions, inplace_update_support),
  723. OptionType::kBoolean, OptionVerificationType::kNormal,
  724. OptionTypeFlags::kNone}},
  725. {"level_compaction_dynamic_level_bytes",
  726. {offsetof(struct ImmutableCFOptions,
  727. level_compaction_dynamic_level_bytes),
  728. OptionType::kBoolean, OptionVerificationType::kNormal,
  729. OptionTypeFlags::kNone}},
  730. {"level_compaction_dynamic_file_size",
  731. {0, OptionType::kBoolean, OptionVerificationType::kDeprecated,
  732. OptionTypeFlags::kNone}},
  733. {"optimize_filters_for_hits",
  734. {offsetof(struct ImmutableCFOptions, optimize_filters_for_hits),
  735. OptionType::kBoolean, OptionVerificationType::kNormal,
  736. OptionTypeFlags::kNone}},
  737. {"force_consistency_checks",
  738. {offsetof(struct ImmutableCFOptions, force_consistency_checks),
  739. OptionType::kBoolean, OptionVerificationType::kNormal,
  740. OptionTypeFlags::kNone}},
  741. {"disallow_memtable_writes",
  742. {offsetof(struct ImmutableCFOptions, disallow_memtable_writes),
  743. OptionType::kBoolean, OptionVerificationType::kNormal,
  744. OptionTypeFlags::kNone}},
  745. {"default_temperature",
  746. {offsetof(struct ImmutableCFOptions, default_temperature),
  747. OptionType::kTemperature, OptionVerificationType::kNormal,
  748. OptionTypeFlags::kCompareNever}},
  749. // Need to keep this around to be able to read old OPTIONS files.
  750. {"max_mem_compaction_level",
  751. {0, OptionType::kInt, OptionVerificationType::kDeprecated,
  752. OptionTypeFlags::kNone}},
  753. {"max_write_buffer_number_to_maintain",
  754. {0, OptionType::kInt, OptionVerificationType::kDeprecated,
  755. OptionTypeFlags::kNone, nullptr}},
  756. {"max_write_buffer_size_to_maintain",
  757. {offsetof(struct ImmutableCFOptions,
  758. max_write_buffer_size_to_maintain),
  759. OptionType::kInt64T, OptionVerificationType::kNormal,
  760. OptionTypeFlags::kNone}},
  761. {"min_write_buffer_number_to_merge",
  762. {offsetof(struct ImmutableCFOptions, min_write_buffer_number_to_merge),
  763. OptionType::kInt, OptionVerificationType::kNormal,
  764. OptionTypeFlags::kNone, nullptr}},
  765. {"num_levels",
  766. {offsetof(struct ImmutableCFOptions, num_levels), OptionType::kInt,
  767. OptionVerificationType::kNormal, OptionTypeFlags::kNone}},
  768. {"bloom_locality",
  769. {offsetof(struct ImmutableCFOptions, bloom_locality),
  770. OptionType::kUInt32T, OptionVerificationType::kNormal,
  771. OptionTypeFlags::kNone}},
  772. {"rate_limit_delay_max_milliseconds",
  773. {0, OptionType::kUInt, OptionVerificationType::kDeprecated,
  774. OptionTypeFlags::kNone}},
  775. {"comparator",
  776. OptionTypeInfo::AsCustomRawPtr<const Comparator>(
  777. offsetof(struct ImmutableCFOptions, user_comparator),
  778. OptionVerificationType::kByName, OptionTypeFlags::kCompareLoose)
  779. .SetSerializeFunc(
  780. // Serializes a Comparator
  781. [](const ConfigOptions& opts, const std::string&,
  782. const void* addr, std::string* value) {
  783. // it's a const pointer of const Comparator*
  784. const auto* ptr =
  785. static_cast<const Comparator* const*>(addr);
  786. if (*ptr == nullptr) {
  787. *value = kNullptrString;
  788. } else if (opts.mutable_options_only) {
  789. *value = "";
  790. } else {
  791. *value = (*ptr)->ToString(opts);
  792. }
  793. return Status::OK();
  794. })},
  795. {"memtable_insert_with_hint_prefix_extractor",
  796. OptionTypeInfo::AsCustomSharedPtr<const SliceTransform>(
  797. offsetof(struct ImmutableCFOptions,
  798. memtable_insert_with_hint_prefix_extractor),
  799. OptionVerificationType::kByNameAllowNull, OptionTypeFlags::kNone)},
  800. {"memtable_factory",
  801. {offsetof(struct ImmutableCFOptions, memtable_factory),
  802. OptionType::kCustomizable, OptionVerificationType::kByName,
  803. OptionTypeFlags::kShared,
  804. [](const ConfigOptions& opts, const std::string&,
  805. const std::string& value, void* addr) {
  806. std::unique_ptr<MemTableRepFactory> factory;
  807. auto* shared =
  808. static_cast<std::shared_ptr<MemTableRepFactory>*>(addr);
  809. Status s =
  810. MemTableRepFactory::CreateFromString(opts, value, shared);
  811. return s;
  812. }}},
  813. {"memtable",
  814. {offsetof(struct ImmutableCFOptions, memtable_factory),
  815. OptionType::kCustomizable, OptionVerificationType::kAlias,
  816. OptionTypeFlags::kShared,
  817. [](const ConfigOptions& opts, const std::string&,
  818. const std::string& value, void* addr) {
  819. std::unique_ptr<MemTableRepFactory> factory;
  820. auto* shared =
  821. static_cast<std::shared_ptr<MemTableRepFactory>*>(addr);
  822. Status s =
  823. MemTableRepFactory::CreateFromString(opts, value, shared);
  824. return s;
  825. }}},
  826. {"table_properties_collectors",
  827. OptionTypeInfo::Vector<
  828. std::shared_ptr<TablePropertiesCollectorFactory>>(
  829. offsetof(struct ImmutableCFOptions,
  830. table_properties_collector_factories),
  831. OptionVerificationType::kByName, OptionTypeFlags::kNone,
  832. OptionTypeInfo::AsCustomSharedPtr<TablePropertiesCollectorFactory>(
  833. 0, OptionVerificationType::kByName, OptionTypeFlags::kNone))},
  834. {"compaction_filter",
  835. OptionTypeInfo::AsCustomRawPtr<const CompactionFilter>(
  836. offsetof(struct ImmutableCFOptions, compaction_filter),
  837. OptionVerificationType::kByName, OptionTypeFlags::kAllowNull)},
  838. {"compaction_filter_factory",
  839. OptionTypeInfo::AsCustomSharedPtr<CompactionFilterFactory>(
  840. offsetof(struct ImmutableCFOptions, compaction_filter_factory),
  841. OptionVerificationType::kByName, OptionTypeFlags::kAllowNull)},
  842. {"merge_operator",
  843. OptionTypeInfo::AsCustomSharedPtr<MergeOperator>(
  844. offsetof(struct ImmutableCFOptions, merge_operator),
  845. OptionVerificationType::kByNameAllowFromNull,
  846. OptionTypeFlags::kCompareLoose | OptionTypeFlags::kAllowNull)},
  847. {"compaction_style",
  848. {offsetof(struct ImmutableCFOptions, compaction_style),
  849. OptionType::kCompactionStyle, OptionVerificationType::kNormal,
  850. OptionTypeFlags::kNone}},
  851. {"compaction_pri",
  852. {offsetof(struct ImmutableCFOptions, compaction_pri),
  853. OptionType::kCompactionPri, OptionVerificationType::kNormal,
  854. OptionTypeFlags::kNone}},
  855. {"sst_partitioner_factory",
  856. OptionTypeInfo::AsCustomSharedPtr<SstPartitionerFactory>(
  857. offsetof(struct ImmutableCFOptions, sst_partitioner_factory),
  858. OptionVerificationType::kByName, OptionTypeFlags::kAllowNull)},
  859. {"blob_cache",
  860. {offsetof(struct ImmutableCFOptions, blob_cache), OptionType::kUnknown,
  861. OptionVerificationType::kNormal,
  862. (OptionTypeFlags::kCompareNever | OptionTypeFlags::kDontSerialize),
  863. // Parses the input value as a Cache
  864. [](const ConfigOptions& opts, const std::string&,
  865. const std::string& value, void* addr) {
  866. auto* cache = static_cast<std::shared_ptr<Cache>*>(addr);
  867. return Cache::CreateFromString(opts, value, cache);
  868. }}},
  869. {"persist_user_defined_timestamps",
  870. {offsetof(struct ImmutableCFOptions, persist_user_defined_timestamps),
  871. OptionType::kBoolean, OptionVerificationType::kNormal,
  872. OptionTypeFlags::kCompareLoose}},
  873. {"cf_allow_ingest_behind",
  874. {offsetof(struct ImmutableCFOptions, cf_allow_ingest_behind),
  875. OptionType::kBoolean, OptionVerificationType::kNormal,
  876. OptionTypeFlags::kNone}},
  877. };
  878. const std::string OptionsHelper::kCFOptionsName = "ColumnFamilyOptions";
  879. class ConfigurableMutableCFOptions : public Configurable {
  880. public:
  881. explicit ConfigurableMutableCFOptions(const MutableCFOptions& mcf) {
  882. mutable_ = mcf;
  883. RegisterOptions(&mutable_, &cf_mutable_options_type_info);
  884. }
  885. protected:
  886. MutableCFOptions mutable_;
  887. };
  888. class ConfigurableCFOptions : public ConfigurableMutableCFOptions {
  889. public:
  890. ConfigurableCFOptions(const ColumnFamilyOptions& opts,
  891. const std::unordered_map<std::string, std::string>* map)
  892. : ConfigurableMutableCFOptions(MutableCFOptions(opts)),
  893. immutable_(opts),
  894. cf_options_(opts),
  895. opt_map_(map) {
  896. RegisterOptions(&immutable_, &cf_immutable_options_type_info);
  897. }
  898. protected:
  899. Status ConfigureOptions(
  900. const ConfigOptions& config_options,
  901. const std::unordered_map<std::string, std::string>& opts_map,
  902. std::unordered_map<std::string, std::string>* unused) override {
  903. Status s = Configurable::ConfigureOptions(config_options, opts_map, unused);
  904. if (s.ok()) {
  905. UpdateColumnFamilyOptions(mutable_, &cf_options_);
  906. UpdateColumnFamilyOptions(immutable_, &cf_options_);
  907. s = PrepareOptions(config_options);
  908. }
  909. return s;
  910. }
  911. const void* GetOptionsPtr(const std::string& name) const override {
  912. if (name == OptionsHelper::kCFOptionsName) {
  913. return &cf_options_;
  914. } else {
  915. return ConfigurableMutableCFOptions::GetOptionsPtr(name);
  916. }
  917. }
  918. bool OptionsAreEqual(const ConfigOptions& config_options,
  919. const OptionTypeInfo& opt_info,
  920. const std::string& opt_name, const void* const this_ptr,
  921. const void* const that_ptr,
  922. std::string* mismatch) const override {
  923. bool equals = opt_info.AreEqual(config_options, opt_name, this_ptr,
  924. that_ptr, mismatch);
  925. if (!equals && opt_info.IsByName()) {
  926. if (opt_map_ == nullptr) {
  927. equals = true;
  928. } else {
  929. const auto& iter = opt_map_->find(opt_name);
  930. if (iter == opt_map_->end()) {
  931. equals = true;
  932. } else {
  933. equals = opt_info.AreEqualByName(config_options, opt_name, this_ptr,
  934. iter->second);
  935. }
  936. }
  937. if (equals) { // False alarm, clear mismatch
  938. *mismatch = "";
  939. }
  940. }
  941. if (equals && opt_info.IsConfigurable() && opt_map_ != nullptr) {
  942. const auto* this_config = opt_info.AsRawPointer<Configurable>(this_ptr);
  943. if (this_config == nullptr) {
  944. const auto& iter = opt_map_->find(opt_name);
  945. // If the name exists in the map and is not empty/null,
  946. // then the this_config should be set.
  947. if (iter != opt_map_->end() && !iter->second.empty() &&
  948. iter->second != kNullptrString) {
  949. *mismatch = opt_name;
  950. equals = false;
  951. }
  952. }
  953. }
  954. return equals;
  955. }
  956. private:
  957. ImmutableCFOptions immutable_;
  958. ColumnFamilyOptions cf_options_;
  959. const std::unordered_map<std::string, std::string>* opt_map_;
  960. };
  961. std::unique_ptr<Configurable> CFOptionsAsConfigurable(
  962. const MutableCFOptions& opts) {
  963. std::unique_ptr<Configurable> ptr(new ConfigurableMutableCFOptions(opts));
  964. return ptr;
  965. }
  966. std::unique_ptr<Configurable> CFOptionsAsConfigurable(
  967. const ColumnFamilyOptions& opts,
  968. const std::unordered_map<std::string, std::string>* opt_map) {
  969. std::unique_ptr<Configurable> ptr(new ConfigurableCFOptions(opts, opt_map));
  970. return ptr;
  971. }
  972. ImmutableCFOptions::ImmutableCFOptions() : ImmutableCFOptions(Options()) {}
  973. ImmutableCFOptions::ImmutableCFOptions(const ColumnFamilyOptions& cf_options)
  974. : compaction_style(cf_options.compaction_style),
  975. compaction_pri(cf_options.compaction_pri),
  976. user_comparator(cf_options.comparator),
  977. internal_comparator(InternalKeyComparator(cf_options.comparator)),
  978. merge_operator(cf_options.merge_operator),
  979. compaction_filter(cf_options.compaction_filter),
  980. compaction_filter_factory(cf_options.compaction_filter_factory),
  981. min_write_buffer_number_to_merge(
  982. cf_options.min_write_buffer_number_to_merge),
  983. max_write_buffer_size_to_maintain(
  984. cf_options.max_write_buffer_size_to_maintain),
  985. inplace_update_support(cf_options.inplace_update_support),
  986. inplace_callback(cf_options.inplace_callback),
  987. memtable_factory(cf_options.memtable_factory),
  988. table_properties_collector_factories(
  989. cf_options.table_properties_collector_factories),
  990. bloom_locality(cf_options.bloom_locality),
  991. level_compaction_dynamic_level_bytes(
  992. cf_options.level_compaction_dynamic_level_bytes),
  993. num_levels(cf_options.num_levels),
  994. optimize_filters_for_hits(cf_options.optimize_filters_for_hits),
  995. force_consistency_checks(cf_options.force_consistency_checks),
  996. disallow_memtable_writes(cf_options.disallow_memtable_writes),
  997. default_temperature(cf_options.default_temperature),
  998. memtable_insert_with_hint_prefix_extractor(
  999. cf_options.memtable_insert_with_hint_prefix_extractor),
  1000. cf_paths(cf_options.cf_paths),
  1001. compaction_thread_limiter(cf_options.compaction_thread_limiter),
  1002. sst_partitioner_factory(cf_options.sst_partitioner_factory),
  1003. blob_cache(cf_options.blob_cache),
  1004. persist_user_defined_timestamps(
  1005. cf_options.persist_user_defined_timestamps),
  1006. cf_allow_ingest_behind(cf_options.cf_allow_ingest_behind) {}
  1007. ImmutableOptions::ImmutableOptions() : ImmutableOptions(Options()) {}
  1008. ImmutableOptions::ImmutableOptions(const Options& options)
  1009. : ImmutableOptions(options, options) {}
  1010. ImmutableOptions::ImmutableOptions(const DBOptions& db_options,
  1011. const ColumnFamilyOptions& cf_options)
  1012. : ImmutableDBOptions(db_options), ImmutableCFOptions(cf_options) {}
  1013. ImmutableOptions::ImmutableOptions(const DBOptions& db_options,
  1014. const ImmutableCFOptions& cf_options)
  1015. : ImmutableDBOptions(db_options), ImmutableCFOptions(cf_options) {}
  1016. ImmutableOptions::ImmutableOptions(const ImmutableDBOptions& db_options,
  1017. const ColumnFamilyOptions& cf_options)
  1018. : ImmutableDBOptions(db_options), ImmutableCFOptions(cf_options) {}
  1019. ImmutableOptions::ImmutableOptions(const ImmutableDBOptions& db_options,
  1020. const ImmutableCFOptions& cf_options)
  1021. : ImmutableDBOptions(db_options), ImmutableCFOptions(cf_options) {}
  1022. // Multiple two operands. If they overflow, return op1.
  1023. uint64_t MultiplyCheckOverflow(uint64_t op1, double op2) {
  1024. if (op1 == 0 || op2 <= 0) {
  1025. return 0;
  1026. }
  1027. if (std::numeric_limits<uint64_t>::max() / op1 < op2) {
  1028. return op1;
  1029. }
  1030. return static_cast<uint64_t>(op1 * op2);
  1031. }
  1032. // when level_compaction_dynamic_level_bytes is true and leveled compaction
  1033. // is used, the base level is not always L1, so precomupted max_file_size can
  1034. // no longer be used. Recompute file_size_for_level from base level.
  1035. uint64_t MaxFileSizeForLevel(const MutableCFOptions& cf_options, int level,
  1036. CompactionStyle compaction_style, int base_level,
  1037. bool level_compaction_dynamic_level_bytes) {
  1038. if (!level_compaction_dynamic_level_bytes || level < base_level ||
  1039. compaction_style != kCompactionStyleLevel) {
  1040. assert(level >= 0);
  1041. assert(level < (int)cf_options.max_file_size.size());
  1042. return cf_options.max_file_size[level];
  1043. } else {
  1044. assert(level >= 0 && base_level >= 0);
  1045. assert(level - base_level < (int)cf_options.max_file_size.size());
  1046. return cf_options.max_file_size[level - base_level];
  1047. }
  1048. }
  1049. size_t MaxFileSizeForL0MetaPin(const MutableCFOptions& cf_options) {
  1050. // We do not want to pin meta-blocks that almost certainly came from intra-L0
  1051. // or a former larger `write_buffer_size` value to avoid surprising users with
  1052. // pinned memory usage. We use a factor of 1.5 to account for overhead
  1053. // introduced during flush in most cases.
  1054. if (std::numeric_limits<size_t>::max() / 3 <
  1055. cf_options.write_buffer_size / 2) {
  1056. return std::numeric_limits<size_t>::max();
  1057. }
  1058. return cf_options.write_buffer_size / 2 * 3;
  1059. }
  1060. void MutableCFOptions::RefreshDerivedOptions(int num_levels,
  1061. CompactionStyle compaction_style) {
  1062. max_file_size.resize(num_levels);
  1063. for (int i = 0; i < num_levels; ++i) {
  1064. if (i == 0 && compaction_style == kCompactionStyleUniversal) {
  1065. max_file_size[i] = ULLONG_MAX;
  1066. } else if (i > 1) {
  1067. max_file_size[i] = MultiplyCheckOverflow(max_file_size[i - 1],
  1068. target_file_size_multiplier);
  1069. } else {
  1070. max_file_size[i] = target_file_size_base;
  1071. }
  1072. }
  1073. }
  1074. void MutableCFOptions::Dump(Logger* log) const {
  1075. // Memtable related options
  1076. ROCKS_LOG_INFO(log,
  1077. " write_buffer_size: %" ROCKSDB_PRIszt,
  1078. write_buffer_size);
  1079. ROCKS_LOG_INFO(log, " max_write_buffer_number: %d",
  1080. max_write_buffer_number);
  1081. ROCKS_LOG_INFO(log,
  1082. " arena_block_size: %" ROCKSDB_PRIszt,
  1083. arena_block_size);
  1084. ROCKS_LOG_INFO(log, " memtable_prefix_bloom_ratio: %f",
  1085. memtable_prefix_bloom_size_ratio);
  1086. ROCKS_LOG_INFO(log, " memtable_whole_key_filtering: %d",
  1087. memtable_whole_key_filtering);
  1088. ROCKS_LOG_INFO(log,
  1089. " memtable_huge_page_size: %" ROCKSDB_PRIszt,
  1090. memtable_huge_page_size);
  1091. ROCKS_LOG_INFO(log,
  1092. " max_successive_merges: %" ROCKSDB_PRIszt,
  1093. max_successive_merges);
  1094. ROCKS_LOG_INFO(log, " strict_max_successive_merges: %d",
  1095. strict_max_successive_merges);
  1096. ROCKS_LOG_INFO(log,
  1097. " inplace_update_num_locks: %" ROCKSDB_PRIszt,
  1098. inplace_update_num_locks);
  1099. ROCKS_LOG_INFO(log, " prefix_extractor: %s",
  1100. prefix_extractor == nullptr
  1101. ? "nullptr"
  1102. : prefix_extractor->GetId().c_str());
  1103. ROCKS_LOG_INFO(log, " disable_auto_compactions: %d",
  1104. disable_auto_compactions);
  1105. ROCKS_LOG_INFO(log, " soft_pending_compaction_bytes_limit: %" PRIu64,
  1106. soft_pending_compaction_bytes_limit);
  1107. ROCKS_LOG_INFO(log, " hard_pending_compaction_bytes_limit: %" PRIu64,
  1108. hard_pending_compaction_bytes_limit);
  1109. ROCKS_LOG_INFO(log, " level0_file_num_compaction_trigger: %d",
  1110. level0_file_num_compaction_trigger);
  1111. ROCKS_LOG_INFO(log, " level0_slowdown_writes_trigger: %d",
  1112. level0_slowdown_writes_trigger);
  1113. ROCKS_LOG_INFO(log, " level0_stop_writes_trigger: %d",
  1114. level0_stop_writes_trigger);
  1115. ROCKS_LOG_INFO(log, " max_compaction_bytes: %" PRIu64,
  1116. max_compaction_bytes);
  1117. ROCKS_LOG_INFO(log, " target_file_size_base: %" PRIu64,
  1118. target_file_size_base);
  1119. ROCKS_LOG_INFO(log, " target_file_size_multiplier: %d",
  1120. target_file_size_multiplier);
  1121. ROCKS_LOG_INFO(log, " max_bytes_for_level_base: %" PRIu64,
  1122. max_bytes_for_level_base);
  1123. ROCKS_LOG_INFO(log, " max_bytes_for_level_multiplier: %f",
  1124. max_bytes_for_level_multiplier);
  1125. ROCKS_LOG_INFO(log, " ttl: %" PRIu64,
  1126. ttl);
  1127. ROCKS_LOG_INFO(log, " periodic_compaction_seconds: %" PRIu64,
  1128. periodic_compaction_seconds);
  1129. ROCKS_LOG_INFO(log,
  1130. " preclude_last_level_data_seconds: %" PRIu64,
  1131. preclude_last_level_data_seconds);
  1132. ROCKS_LOG_INFO(log, " preserve_internal_time_seconds: %" PRIu64,
  1133. preserve_internal_time_seconds);
  1134. ROCKS_LOG_INFO(log, " paranoid_memory_checks: %d",
  1135. paranoid_memory_checks);
  1136. ROCKS_LOG_INFO(log, "memtable_veirfy_per_key_checksum_on_seek: %d",
  1137. memtable_veirfy_per_key_checksum_on_seek);
  1138. std::string result;
  1139. char buf[10];
  1140. for (const auto m : max_bytes_for_level_multiplier_additional) {
  1141. snprintf(buf, sizeof(buf), "%d, ", m);
  1142. result += buf;
  1143. }
  1144. if (result.size() >= 2) {
  1145. result.resize(result.size() - 2);
  1146. } else {
  1147. result = "";
  1148. }
  1149. ROCKS_LOG_INFO(log, "max_bytes_for_level_multiplier_additional: %s",
  1150. result.c_str());
  1151. ROCKS_LOG_INFO(log, " max_sequential_skip_in_iterations: %" PRIu64,
  1152. max_sequential_skip_in_iterations);
  1153. ROCKS_LOG_INFO(log, " paranoid_file_checks: %d",
  1154. paranoid_file_checks);
  1155. ROCKS_LOG_INFO(log, " report_bg_io_stats: %d",
  1156. report_bg_io_stats);
  1157. ROCKS_LOG_INFO(log, " compression: %d",
  1158. static_cast<int>(compression));
  1159. ROCKS_LOG_INFO(log, " experimental_mempurge_threshold: %f",
  1160. experimental_mempurge_threshold);
  1161. ROCKS_LOG_INFO(log, " bottommost_file_compaction_delay: %" PRIu32,
  1162. bottommost_file_compaction_delay);
  1163. ROCKS_LOG_INFO(log, " uncache_aggressiveness: %" PRIu32,
  1164. uncache_aggressiveness);
  1165. ROCKS_LOG_INFO(log, " memtable_op_scan_flush_trigger: %" PRIu32,
  1166. memtable_op_scan_flush_trigger);
  1167. ROCKS_LOG_INFO(log, " memtable_avg_op_scan_flush_trigger: %" PRIu32,
  1168. memtable_avg_op_scan_flush_trigger);
  1169. // Universal Compaction Options
  1170. ROCKS_LOG_INFO(log, "compaction_options_universal.size_ratio : %d",
  1171. compaction_options_universal.size_ratio);
  1172. ROCKS_LOG_INFO(log, "compaction_options_universal.min_merge_width : %d",
  1173. compaction_options_universal.min_merge_width);
  1174. ROCKS_LOG_INFO(log, "compaction_options_universal.max_merge_width : %d",
  1175. compaction_options_universal.max_merge_width);
  1176. ROCKS_LOG_INFO(
  1177. log, "compaction_options_universal.max_size_amplification_percent : %d",
  1178. compaction_options_universal.max_size_amplification_percent);
  1179. ROCKS_LOG_INFO(log,
  1180. "compaction_options_universal.compression_size_percent : %d",
  1181. compaction_options_universal.compression_size_percent);
  1182. ROCKS_LOG_INFO(log, "compaction_options_universal.max_read_amp: %d",
  1183. compaction_options_universal.max_read_amp);
  1184. ROCKS_LOG_INFO(log, "compaction_options_universal.stop_style : %d",
  1185. compaction_options_universal.stop_style);
  1186. ROCKS_LOG_INFO(
  1187. log, "compaction_options_universal.allow_trivial_move : %d",
  1188. static_cast<int>(compaction_options_universal.allow_trivial_move));
  1189. ROCKS_LOG_INFO(log, "compaction_options_universal.incremental : %d",
  1190. static_cast<int>(compaction_options_universal.incremental));
  1191. ROCKS_LOG_INFO(log, "compaction_options_universal.reduce_file_locking : %d",
  1192. compaction_options_universal.reduce_file_locking);
  1193. // FIFO Compaction Options
  1194. ROCKS_LOG_INFO(log, "compaction_options_fifo.max_table_files_size : %" PRIu64,
  1195. compaction_options_fifo.max_table_files_size);
  1196. ROCKS_LOG_INFO(log, "compaction_options_fifo.allow_compaction : %d",
  1197. compaction_options_fifo.allow_compaction);
  1198. // Blob file related options
  1199. ROCKS_LOG_INFO(log, " enable_blob_files: %s",
  1200. enable_blob_files ? "true" : "false");
  1201. ROCKS_LOG_INFO(log, " min_blob_size: %" PRIu64,
  1202. min_blob_size);
  1203. ROCKS_LOG_INFO(log, " blob_file_size: %" PRIu64,
  1204. blob_file_size);
  1205. ROCKS_LOG_INFO(log, " blob_compression_type: %s",
  1206. CompressionTypeToString(blob_compression_type).c_str());
  1207. ROCKS_LOG_INFO(log, " enable_blob_garbage_collection: %s",
  1208. enable_blob_garbage_collection ? "true" : "false");
  1209. ROCKS_LOG_INFO(log, " blob_garbage_collection_age_cutoff: %f",
  1210. blob_garbage_collection_age_cutoff);
  1211. ROCKS_LOG_INFO(log, " blob_garbage_collection_force_threshold: %f",
  1212. blob_garbage_collection_force_threshold);
  1213. ROCKS_LOG_INFO(log, " blob_compaction_readahead_size: %" PRIu64,
  1214. blob_compaction_readahead_size);
  1215. ROCKS_LOG_INFO(log, " blob_file_starting_level: %d",
  1216. blob_file_starting_level);
  1217. ROCKS_LOG_INFO(log, " prepopulate_blob_cache: %s",
  1218. prepopulate_blob_cache == PrepopulateBlobCache::kFlushOnly
  1219. ? "flush only"
  1220. : "disable");
  1221. ROCKS_LOG_INFO(log, " last_level_temperature: %d",
  1222. static_cast<int>(last_level_temperature));
  1223. }
  1224. MutableCFOptions::MutableCFOptions(const Options& options)
  1225. : MutableCFOptions(ColumnFamilyOptions(options)) {}
  1226. Status GetMutableOptionsFromStrings(
  1227. const MutableCFOptions& base_options,
  1228. const std::unordered_map<std::string, std::string>& options_map,
  1229. Logger* /*info_log*/, MutableCFOptions* new_options) {
  1230. assert(new_options);
  1231. *new_options = base_options;
  1232. ConfigOptions config_options;
  1233. Status s = OptionTypeInfo::ParseType(
  1234. config_options, options_map, cf_mutable_options_type_info, new_options);
  1235. if (!s.ok()) {
  1236. *new_options = base_options;
  1237. }
  1238. return s;
  1239. }
  1240. Status GetStringFromMutableCFOptions(const ConfigOptions& config_options,
  1241. const MutableCFOptions& mutable_opts,
  1242. std::string* opt_string) {
  1243. assert(opt_string);
  1244. opt_string->clear();
  1245. return OptionTypeInfo::SerializeType(
  1246. config_options, cf_mutable_options_type_info, &mutable_opts, opt_string);
  1247. }
  1248. #ifndef NDEBUG
  1249. std::vector<std::string> TEST_GetImmutableInMutableCFOptions() {
  1250. std::vector<std::string> result;
  1251. for (const auto& opt : cf_mutable_options_type_info) {
  1252. if (!opt.second.IsMutable()) {
  1253. result.emplace_back(opt.first);
  1254. }
  1255. }
  1256. if (result.size() > 0) {
  1257. std::cerr << "Warning: " << result.size() << " immutable options in "
  1258. << "MutableCFOptions" << std::endl;
  1259. }
  1260. return result;
  1261. }
  1262. bool TEST_allowSetOptionsImmutableInMutable = false;
  1263. #endif // !NDEBUG
  1264. } // namespace ROCKSDB_NAMESPACE