50 icmp_(options.comparator),
51 ipolicy_(options.filter_policy),
53 owns_info_log_(options_.info_log != options.info_log),
54 owns_cache_(options_.block_cache != options.block_cache),
55 next_file_number_(1) {
57 table_cache_ =
new TableCache(dbname_, &options_, 10);
63 delete options_.info_log;
66 delete options_.block_cache;
71 Status status = FindFiles();
73 ConvertLogFilesToTables();
75 status = WriteDescriptor();
78 unsigned long long bytes = 0;
79 for (
size_t i = 0; i < tables_.size(); i++) {
80 bytes += tables_[i].meta.file_size;
82 Log(options_.info_log,
83 "**** Repaired leveldb %s; " 84 "recovered %d files; %llu bytes. " 85 "Some data may have been lost. " 88 static_cast<int>(tables_.size()),
117 std::vector<std::string> filenames;
122 if (filenames.empty()) {
128 for (
size_t i = 0; i < filenames.size(); i++) {
131 manifests_.push_back(filenames[i]);
133 if (number + 1 > next_file_number_) {
134 next_file_number_ = number + 1;
137 logs_.push_back(number);
139 table_numbers_.push_back(number);
150 for (
size_t i = 0; i < logs_.size(); i++) {
151 std::string logname =
LogFileName(dbname_, logs_[i]);
152 Status status = ConvertLogToTable(logs_[i]);
154 Log(options_.
info_log,
"Log #%llu: ignoring conversion error: %s",
155 (
unsigned long long) logs_[i],
158 ArchiveFile(logname);
167 virtual void Corruption(
size_t bytes,
const Status& s) {
169 Log(info_log,
"Log #%llu: dropping %d bytes; %s",
170 (
unsigned long long) lognum,
171 static_cast<int>(bytes),
185 LogReporter reporter;
187 reporter.info_log = options_.
info_log;
188 reporter.lognum = log;
203 while (reader.
ReadRecord(&record, &scratch)) {
204 if (record.
size() < 12) {
215 (
unsigned long long) log,
225 meta.
number = next_file_number_++;
227 status =
BuildTable(dbname_, env_, options_, table_cache_, iter, &meta);
233 table_numbers_.push_back(meta.
number);
236 Log(options_.
info_log,
"Log #%llu: %d ops saved to Table #%llu %s",
237 (
unsigned long long) log,
239 (
unsigned long long) meta.
number,
245 for (
size_t i = 0; i < table_numbers_.size(); i++) {
246 ScanTable(table_numbers_[i]);
289 Log(options_.
info_log,
"Table #%llu: unparsable key %s",
309 Log(options_.
info_log,
"Table #%llu: %d entries %s",
315 tables_.push_back(t);
317 RepairTable(fname, t);
326 std::string copy =
TableFileName(dbname_, next_file_number_++);
361 if (counter > 0 && s.
ok()) {
365 Log(options_.
info_log,
"Table #%llu: %d entries repaired",
367 tables_.push_back(t);
384 for (
size_t i = 0; i < tables_.size(); i++) {
385 if (max_sequence < tables_[i].max_sequence) {
386 max_sequence = tables_[i].max_sequence;
395 for (
size_t i = 0; i < tables_.size(); i++) {
410 status = file->
Close();
419 for (
size_t i = 0; i < manifests_.size(); i++) {
420 ArchiveFile(dbname_ +
"/" + manifests_[i]);
439 const char* slash = strrchr(fname.c_str(),
'/');
442 new_dir.assign(fname.data(), slash - fname.data());
444 new_dir.append(
"/lost");
446 std::string new_file = new_dir;
447 new_file.append(
"/");
448 new_file.append((slash == NULL) ? fname.c_str() : slash + 1);
451 fname.c_str(), s.
ToString().c_str());
457 Repairer repairer(dbname, options);
458 return repairer.Run();
std::string const dbname_
Status ConvertLogToTable(uint64_t log)
void ConvertLogFilesToTables()
virtual Status status() const =0
void ArchiveFile(const std::string &fname)
std::vector< TableInfo > tables_
bool ParseFileName(const std::string &fname, uint64_t *number, FileType *type)
void SetLastSequence(SequenceNumber seq)
void SetLogNumber(uint64_t num)
void SetComparatorName(const Slice &name)
virtual Slice key() const =0
virtual Slice value() const =0
void ScanTable(uint64_t number)
void SetNextFile(uint64_t num)
static Status InsertInto(const WriteBatch *batch, MemTable *memtable)
const Comparator * user_comparator() const
virtual void SeekToFirst()=0
std::string TempFileName(const std::string &dbname, uint64_t number)
void Log(Logger *info_log, const char *format,...)
virtual Status GetFileSize(const std::string &fname, uint64_t *file_size)=0
virtual Status NewWritableFile(const std::string &fname, WritableFile **result)=0
bool ParseInternalKey(const Slice &internal_key, ParsedInternalKey *result)
Status RepairDB(const std::string &dbname, const Options &options)
InternalFilterPolicy const ipolicy_
virtual const char * Name() const =0
std::string TableFileName(const std::string &name, uint64_t number)
static Status Corruption(const Slice &msg, const Slice &msg2=Slice())
virtual Status CreateDir(const std::string &dirname)=0
std::string ToString() const
bool ReadRecord(Slice *record, std::string *scratch)
std::string DescriptorFileName(const std::string &dbname, uint64_t number)
uint64_t FileSize() const
static void SetContents(WriteBatch *batch, const Slice &contents)
void DecodeFrom(const Slice &s)
std::string EscapeString(const Slice &value)
Status SetCurrentFile(Env *env, const std::string &dbname, uint64_t descriptor_number)
void EncodeTo(std::string *dst) const
InternalKeyComparator const icmp_
virtual Status RenameFile(const std::string &src, const std::string &target)=0
TableCache * table_cache_
Iterator * NewTableIterator(const FileMetaData &meta)
void RepairTable(const std::string &src, TableInfo t)
SequenceNumber max_sequence
std::string SSTTableFileName(const std::string &name, uint64_t number)
Iterator * NewIterator(const ReadOptions &options, uint64_t file_number, uint64_t file_size, Table **tableptr=NULL)
static int Count(const WriteBatch *batch)
std::vector< uint64_t > table_numbers_
Repairer(const std::string &dbname, const Options &options)
virtual Status NewSequentialFile(const std::string &fname, SequentialFile **result)=0
std::string LogFileName(const std::string &name, uint64_t number)
Status AddRecord(const Slice &slice)
Options SanitizeOptions(const std::string &dbname, const InternalKeyComparator *icmp, const InternalFilterPolicy *ipolicy, const Options &src)
Status BuildTable(const std::string &dbname, Env *env, const Options &options, TableCache *table_cache, Iterator *iter, FileMetaData *meta)
void AddFile(int level, uint64_t file, uint64_t file_size, const InternalKey &smallest, const InternalKey &largest)
std::vector< uint64_t > logs_
std::vector< std::string > manifests_
virtual Status DeleteFile(const std::string &fname)=0
static Status IOError(const Slice &msg, const Slice &msg2=Slice())
virtual bool Valid() const =0
uint64_t next_file_number_
virtual Status GetChildren(const std::string &dir, std::vector< std::string > *result)=0
void Add(const Slice &key, const Slice &value)