// ---------------------------------------------------------------------- // File: RecoveryEditor.cc // Author: Georgios Bitzes - CERN // ---------------------------------------------------------------------- /************************************************************************ * quarkdb - a redis-like highly available key-value store * * Copyright (C) 2016 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ #include "recovery/RecoveryEditor.hh" #include "storage/KeyConstants.hh" #include "Utils.hh" #include "utils/StringUtils.hh" #include "storage/InternalKeyParsing.hh" #include #include #include #include #include #include using namespace quarkdb; RecoveryEditor::RecoveryEditor(std::string_view path_) : path(path_) { qdb_event("RECOVERY EDITOR: Opening rocksdb database at " << quotes(path)); rocksdb::DB *tmpdb; rocksdb::Options options; options.create_if_missing = false; options.disable_auto_compactions = true; rocksdb::Status status = rocksdb::DB::Open(options, path, &tmpdb); if(!status.ok()) qdb_throw("Cannot open " << quotes(path) << ":" << status.ToString()); db.reset(tmpdb); } RecoveryEditor::~RecoveryEditor() { if(db) { qdb_event("RECOVERY EDITOR: Closing rocksdb database at " << quotes(path)); db.reset(); } } std::vector RecoveryEditor::retrieveMagicValues() { std::vector results; for(auto it = KeyConstants::allKeys.begin(); it != KeyConstants::allKeys.end(); it++) { std::string tmp; rocksdb::Status st = db->Get(rocksdb::ReadOptions(), *it, &tmp); if(st.ok()) { results.emplace_back(*it); results.emplace_back(tmp); } else { results.emplace_back(SSTR(*it << ": " << st.ToString())); } } return results; } rocksdb::Status RecoveryEditor::get(std::string_view key, std::string &value) { return db->Get(rocksdb::ReadOptions(), key, &value); } rocksdb::Status RecoveryEditor::set(std::string_view key, std::string_view value) { return db->Put(rocksdb::WriteOptions(), key, value); } rocksdb::Status RecoveryEditor::del(std::string_view key) { std::string tmp; rocksdb::Status st = db->Get(rocksdb::ReadOptions(), key, &tmp); if(st.IsNotFound()) { rocksdb::Status st2 = db->Delete(rocksdb::WriteOptions(), key); return rocksdb::Status::InvalidArgument("key not found, but I inserted a tombstone anyway. Deletion status: " + st2.ToString()); } if(!st.ok()) { return st; } return db->Delete(rocksdb::WriteOptions(), key); } using IteratorPtr = std::unique_ptr; rocksdb::Status RecoveryEditor::scan(std::string_view key, size_t count, std::string &nextCursor, std::vector &elements) { rocksdb::ReadOptions opts; // Iterate also over tombstones opts.iter_start_ts = new rocksdb::Slice(""); IteratorPtr iter(db->NewIterator(opts)); iter->Seek(key); size_t processed = 0; while(iter->Valid()) { std::string_view currentKey = iter->key().ToStringView(); std::string internalKeyType = getInternalKeyType(currentKey); currentKey.remove_suffix(8u); if(processed >= count) { nextCursor = currentKey; break; } elements.emplace_back(SSTR("TYPE: " << internalKeyType)); elements.emplace_back(SSTR("KEY: " << currentKey)); elements.emplace_back(SSTR("VALUE: " << iter->value().ToStringView())); processed++; iter->Next(); } delete opts.iter_start_ts; return rocksdb::Status::OK(); } rocksdb::Status RecoveryEditor::getAllVersions(std::string_view key, std::vector &output) { std::vector versions; rocksdb::GetAllKeyVersions(db.get(), key, key, std::numeric_limits::max(), &versions); for(const rocksdb::KeyVersion& ver : versions) { output.emplace_back(SSTR("KEY: " << ver.user_key)); output.emplace_back(SSTR("VALUE: " << ver.value)); output.emplace_back(SSTR("SEQUENCE: " << ver.sequence)); output.emplace_back(SSTR("TYPE: " << ver.type)); } return rocksdb::Status::OK(); }