sstables: handle unrecognized sstable component
As in C*, unrecognized sstable components should be ignored when loading a sstable. At the moment, Scylla fails to do so and will not boot as a result. In addition, unknown components should be remembered when moving a sstable or changing its generation. Fixes #1780. Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com> Message-Id: <b7af0c28e5b574fd577a7a1d28fb006ac197aa0a.1478025930.git.raphaelsc@scylladb.com>
This commit is contained in:
committed by
Avi Kivity
parent
72c2982260
commit
53b7b7def3
@@ -741,10 +741,10 @@ future<> sstable::read_toc() {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
_components.insert(reverse_map(c, _component_map));
|
||||
_components.insert(reverse_map(c, _component_map));
|
||||
} catch (std::out_of_range& oor) {
|
||||
_components.clear(); // so subsequent read_toc will be forced to fail again
|
||||
throw malformed_sstable_exception("Unrecognized TOC component: " + c, file_path);
|
||||
_unrecognized_components.push_back(c);
|
||||
sstlog.info("Unrecognized TOC component was found: {} in sstable {}", c, file_path);
|
||||
}
|
||||
}
|
||||
if (!_components.size()) {
|
||||
@@ -1958,6 +1958,28 @@ const sstring sstable::filename(sstring dir, sstring ks, sstring cf, version_typ
|
||||
return dir + "/" + strmap[version](entry_descriptor(ks, cf, version, generation, format, component));
|
||||
}
|
||||
|
||||
const sstring sstable::filename(sstring dir, sstring ks, sstring cf, version_types version, int64_t generation,
|
||||
format_types format, sstring component) {
|
||||
static std::unordered_map<version_types, const char*, enum_hash<version_types>> fmtmap = {
|
||||
{ sstable::version_types::ka, "{0}-{1}-{2}-{3}-{5}" },
|
||||
{ sstable::version_types::la, "{2}-{3}-{4}-{5}" }
|
||||
};
|
||||
|
||||
return dir + "/" + seastar::format(fmtmap[version], ks, cf, _version_string.at(version), to_sstring(generation), _format_string.at(format), component);
|
||||
}
|
||||
|
||||
std::vector<std::pair<sstable::component_type, sstring>> sstable::all_components() const {
|
||||
std::vector<std::pair<component_type, sstring>> all;
|
||||
all.reserve(_components.size() + _unrecognized_components.size());
|
||||
for (auto& c : _components) {
|
||||
all.push_back(std::make_pair(c, _component_map.at(c)));
|
||||
}
|
||||
for (auto& c : _unrecognized_components) {
|
||||
all.push_back(std::make_pair(component_type::Unknown, c));
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
future<> sstable::create_links(sstring dir, int64_t generation) const {
|
||||
// TemporaryTOC is always first, TOC is always last
|
||||
auto dst = sstable::filename(dir, _schema->ks_name(), _schema->cf_name(), _version, generation, _format, component_type::TemporaryTOC);
|
||||
@@ -1965,12 +1987,13 @@ future<> sstable::create_links(sstring dir, int64_t generation) const {
|
||||
return sstable_write_io_check(sync_directory, dir);
|
||||
}).then([this, dir, generation] {
|
||||
// FIXME: Should clean already-created links if we failed midway.
|
||||
return parallel_for_each(_components, [this, dir, generation] (auto comp) {
|
||||
if (comp == component_type::TOC) {
|
||||
return parallel_for_each(all_components(), [this, dir, generation] (auto p) {
|
||||
if (p.first == component_type::TOC) {
|
||||
return make_ready_future<>();
|
||||
}
|
||||
auto dst = sstable::filename(dir, _schema->ks_name(), _schema->cf_name(), _version, generation, _format, comp);
|
||||
return this->sstable_write_io_check(::link_file, this->filename(comp), dst);
|
||||
auto src = sstable::filename(_dir, _schema->ks_name(), _schema->cf_name(), _version, _generation, _format, p.second);
|
||||
auto dst = sstable::filename(dir, _schema->ks_name(), _schema->cf_name(), _version, generation, _format, p.second);
|
||||
return this->sstable_write_io_check(::link_file, std::move(src), std::move(dst));
|
||||
});
|
||||
}).then([this, dir] {
|
||||
return sstable_write_io_check(sync_directory, dir);
|
||||
@@ -1990,11 +2013,11 @@ future<> sstable::set_generation(int64_t new_generation) {
|
||||
return remove_file(filename(component_type::TOC)).then([this] {
|
||||
return sstable_write_io_check(sync_directory, _dir);
|
||||
}).then([this] {
|
||||
return parallel_for_each(_components, [this] (auto comp) {
|
||||
if (comp == component_type::TOC) {
|
||||
return parallel_for_each(all_components(), [this] (auto p) {
|
||||
if (p.first == component_type::TOC) {
|
||||
return make_ready_future<>();
|
||||
}
|
||||
return remove_file(this->filename(comp));
|
||||
return remove_file(sstable::filename(_dir, _schema->ks_name(), _schema->cf_name(), _version, _generation, _format, p.second));
|
||||
});
|
||||
});
|
||||
}).then([this, new_generation] {
|
||||
|
||||
@@ -131,6 +131,7 @@ public:
|
||||
Statistics,
|
||||
TemporaryTOC,
|
||||
TemporaryStatistics,
|
||||
Unknown,
|
||||
};
|
||||
enum class version_types { ka, la };
|
||||
enum class format_types { big };
|
||||
@@ -225,6 +226,8 @@ public:
|
||||
static format_types format_from_sstring(sstring& s);
|
||||
static const sstring filename(sstring dir, sstring ks, sstring cf, version_types version, int64_t generation,
|
||||
format_types format, component_type component);
|
||||
static const sstring filename(sstring dir, sstring ks, sstring cf, version_types version, int64_t generation,
|
||||
format_types format, sstring component);
|
||||
// WARNING: it should only be called to remove components of a sstable with
|
||||
// a temporary TOC file.
|
||||
static future<> remove_sstable_with_temp_toc(sstring ks, sstring cf, sstring dir, int64_t generation,
|
||||
@@ -362,6 +365,8 @@ public:
|
||||
return _collector;
|
||||
}
|
||||
|
||||
std::vector<std::pair<component_type, sstring>> all_components() const;
|
||||
|
||||
future<> create_links(sstring dir, int64_t generation) const;
|
||||
|
||||
future<> create_links(sstring dir) const {
|
||||
@@ -405,6 +410,7 @@ private:
|
||||
static std::unordered_map<component_type, sstring, enum_hash<component_type>> _component_map;
|
||||
|
||||
std::unordered_set<component_type, enum_hash<component_type>> _components;
|
||||
std::vector<sstring> _unrecognized_components;
|
||||
|
||||
bool _shared = true; // across shards; safe default
|
||||
compression _compression;
|
||||
|
||||
@@ -3031,3 +3031,22 @@ SEASTAR_TEST_CASE(test_partition_skipping) {
|
||||
.produces_end_of_stream();
|
||||
});
|
||||
}
|
||||
|
||||
SEASTAR_TEST_CASE(test_unknown_component) {
|
||||
return seastar::async([] {
|
||||
auto tmp = make_lw_shared<tmpdir>();
|
||||
auto sstp = reusable_sst(uncompressed_schema(), "tests/sstables/unknown_component", 1).get0();
|
||||
sstp->create_links(tmp->path).get();
|
||||
// check that create_links() moved unknown component to new dir
|
||||
BOOST_REQUIRE(file_exists(tmp->path + "/la-1-big-UNKNOWN.txt").get0());
|
||||
|
||||
sstp = reusable_sst(uncompressed_schema(), tmp->path, 1).get0();
|
||||
sstp->set_generation(2).get();
|
||||
BOOST_REQUIRE(!file_exists(tmp->path + "/la-1-big-UNKNOWN.txt").get0());
|
||||
BOOST_REQUIRE(file_exists(tmp->path + "/la-2-big-UNKNOWN.txt").get0());
|
||||
|
||||
sstables::delete_atomically({sstp}).get();
|
||||
// assure unknown component is deleted
|
||||
BOOST_REQUIRE(!file_exists(tmp->path + "/la-2-big-UNKNOWN.txt").get0());
|
||||
});
|
||||
}
|
||||
|
||||
BIN
tests/sstables/unknown_component/la-1-big-CRC.db
Normal file
BIN
tests/sstables/unknown_component/la-1-big-CRC.db
Normal file
Binary file not shown.
BIN
tests/sstables/unknown_component/la-1-big-Data.db
Normal file
BIN
tests/sstables/unknown_component/la-1-big-Data.db
Normal file
Binary file not shown.
1
tests/sstables/unknown_component/la-1-big-Digest.sha1
Normal file
1
tests/sstables/unknown_component/la-1-big-Digest.sha1
Normal file
@@ -0,0 +1 @@
|
||||
748507322
|
||||
BIN
tests/sstables/unknown_component/la-1-big-Filter.db
Normal file
BIN
tests/sstables/unknown_component/la-1-big-Filter.db
Normal file
Binary file not shown.
BIN
tests/sstables/unknown_component/la-1-big-Index.db
Normal file
BIN
tests/sstables/unknown_component/la-1-big-Index.db
Normal file
Binary file not shown.
BIN
tests/sstables/unknown_component/la-1-big-Statistics.db
Normal file
BIN
tests/sstables/unknown_component/la-1-big-Statistics.db
Normal file
Binary file not shown.
BIN
tests/sstables/unknown_component/la-1-big-Summary.db
Normal file
BIN
tests/sstables/unknown_component/la-1-big-Summary.db
Normal file
Binary file not shown.
9
tests/sstables/unknown_component/la-1-big-TOC.txt
Normal file
9
tests/sstables/unknown_component/la-1-big-TOC.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
Data.db
|
||||
Filter.db
|
||||
CRC.db
|
||||
Statistics.db
|
||||
Summary.db
|
||||
Digest.sha1
|
||||
Index.db
|
||||
TOC.txt
|
||||
UNKNOWN.txt
|
||||
Reference in New Issue
Block a user