]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/utilities/option_change_migration/option_change_migration.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rocksdb / utilities / option_change_migration / option_change_migration.cc
CommitLineData
7c673cae 1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
11fdf7f2
TL
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).
7c673cae
FG
5
6#include "rocksdb/utilities/option_change_migration.h"
7
8#ifndef ROCKSDB_LITE
9#include "rocksdb/db.h"
10
11namespace rocksdb {
12namespace {
13// Return a version of Options `opts` that allow us to open/write into a DB
14// without triggering an automatic compaction or stalling. This is guaranteed
15// by disabling automatic compactions and using huge values for stalling
16// triggers.
17Options GetNoCompactionOptions(const Options& opts) {
18 Options ret_opts = opts;
19 ret_opts.disable_auto_compactions = true;
20 ret_opts.level0_slowdown_writes_trigger = 999999;
21 ret_opts.level0_stop_writes_trigger = 999999;
22 ret_opts.soft_pending_compaction_bytes_limit = 0;
23 ret_opts.hard_pending_compaction_bytes_limit = 0;
24 return ret_opts;
25}
26
27Status OpenDb(const Options& options, const std::string& dbname,
28 std::unique_ptr<DB>* db) {
29 db->reset();
30 DB* tmpdb;
31 Status s = DB::Open(options, dbname, &tmpdb);
32 if (s.ok()) {
33 db->reset(tmpdb);
34 }
35 return s;
36}
37
38Status CompactToLevel(const Options& options, const std::string& dbname,
39 int dest_level, bool need_reopen) {
40 std::unique_ptr<DB> db;
41 Options no_compact_opts = GetNoCompactionOptions(options);
42 if (dest_level == 0) {
43 // L0 has strict sequenceID requirements to files to it. It's safer
44 // to only put one compacted file to there.
45 // This is only used for converting to universal compaction with
46 // only one level. In this case, compacting to one file is also
47 // optimal.
48 no_compact_opts.target_file_size_base = 999999999999999;
49 no_compact_opts.max_compaction_bytes = 999999999999999;
50 }
51 Status s = OpenDb(no_compact_opts, dbname, &db);
52 if (!s.ok()) {
53 return s;
54 }
55 CompactRangeOptions cro;
56 cro.change_level = true;
57 cro.target_level = dest_level;
58 if (dest_level == 0) {
59 cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
60 }
61 db->CompactRange(cro, nullptr, nullptr);
62
63 if (need_reopen) {
64 // Need to restart DB to rewrite the manifest file.
65 // In order to open a DB with specific num_levels, the manifest file should
66 // contain no record that mentiones any level beyond num_levels. Issuing a
67 // full compaction will move all the data to a level not exceeding
68 // num_levels, but the manifest may still contain previous record mentioning
69 // a higher level. Reopening the DB will force the manifest to be rewritten
70 // so that those records will be cleared.
71 db.reset();
72 s = OpenDb(no_compact_opts, dbname, &db);
73 }
74 return s;
75}
76
77Status MigrateToUniversal(std::string dbname, const Options& old_opts,
78 const Options& new_opts) {
79 if (old_opts.num_levels <= new_opts.num_levels ||
80 old_opts.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
81 return Status::OK();
82 } else {
83 bool need_compact = false;
84 {
85 std::unique_ptr<DB> db;
86 Options opts = GetNoCompactionOptions(old_opts);
87 Status s = OpenDb(opts, dbname, &db);
88 if (!s.ok()) {
89 return s;
90 }
91 ColumnFamilyMetaData metadata;
92 db->GetColumnFamilyMetaData(&metadata);
93 if (!metadata.levels.empty() &&
94 metadata.levels.back().level >= new_opts.num_levels) {
95 need_compact = true;
96 }
97 }
98 if (need_compact) {
99 return CompactToLevel(old_opts, dbname, new_opts.num_levels - 1, true);
100 }
101 return Status::OK();
102 }
103}
104
105Status MigrateToLevelBase(std::string dbname, const Options& old_opts,
106 const Options& new_opts) {
107 if (!new_opts.level_compaction_dynamic_level_bytes) {
108 if (old_opts.num_levels == 1) {
109 return Status::OK();
110 }
111 // Compact everything to level 1 to guarantee it can be safely opened.
112 Options opts = old_opts;
113 opts.target_file_size_base = new_opts.target_file_size_base;
114 // Although sometimes we can open the DB with the new option without error,
115 // We still want to compact the files to avoid the LSM tree to stuck
116 // in bad shape. For example, if the user changed the level size
117 // multiplier from 4 to 8, with the same data, we will have fewer
118 // levels. Unless we issue a full comaction, the LSM tree may stuck
119 // with more levels than needed and it won't recover automatically.
120 return CompactToLevel(opts, dbname, 1, true);
121 } else {
122 // Compact everything to the last level to guarantee it can be safely
123 // opened.
124 if (old_opts.num_levels == 1) {
125 return Status::OK();
126 } else if (new_opts.num_levels > old_opts.num_levels) {
127 // Dynamic level mode requires data to be put in the last level first.
128 return CompactToLevel(new_opts, dbname, new_opts.num_levels - 1, false);
129 } else {
130 Options opts = old_opts;
131 opts.target_file_size_base = new_opts.target_file_size_base;
132 return CompactToLevel(opts, dbname, new_opts.num_levels - 1, true);
133 }
134 }
135}
136} // namespace
137
138Status OptionChangeMigration(std::string dbname, const Options& old_opts,
139 const Options& new_opts) {
140 if (old_opts.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
141 // LSM generated by FIFO compation can be opened by any compaction.
142 return Status::OK();
143 } else if (new_opts.compaction_style ==
144 CompactionStyle::kCompactionStyleUniversal) {
145 return MigrateToUniversal(dbname, old_opts, new_opts);
146 } else if (new_opts.compaction_style ==
147 CompactionStyle::kCompactionStyleLevel) {
148 return MigrateToLevelBase(dbname, old_opts, new_opts);
149 } else if (new_opts.compaction_style ==
150 CompactionStyle::kCompactionStyleFIFO) {
151 return CompactToLevel(old_opts, dbname, 0, true);
152 } else {
153 return Status::NotSupported(
154 "Do not how to migrate to this compaction style");
155 }
156}
157} // namespace rocksdb
158#else
159namespace rocksdb {
11fdf7f2
TL
160Status OptionChangeMigration(std::string /*dbname*/,
161 const Options& /*old_opts*/,
162 const Options& /*new_opts*/) {
7c673cae
FG
163 return Status::NotSupported();
164}
165} // namespace rocksdb
166#endif // ROCKSDB_LITE