45 double result = 10. * 1048576.0;
60 for (
size_t i = 0; i < files.size(); i++) {
61 sum += files[i]->file_size;
75 for (
size_t i = 0; i <
files_[level].size(); i++) {
87 const std::vector<FileMetaData*>& files,
90 uint32_t right = files.size();
91 while (left < right) {
92 uint32_t mid = (left + right) / 2;
94 if (icmp.InternalKeyComparator::Compare(f->
largest.
Encode(), key) < 0) {
110 return (user_key != NULL &&
117 return (user_key != NULL &&
123 bool disjoint_sorted_files,
124 const std::vector<FileMetaData*>& files,
125 const Slice* smallest_user_key,
126 const Slice* largest_user_key) {
128 if (!disjoint_sorted_files) {
130 for (
size_t i = 0; i < files.size(); i++) {
132 if (
AfterFile(ucmp, smallest_user_key, f) ||
144 if (smallest_user_key != NULL) {
150 if (index >= files.size()) {
155 return !
BeforeFile(ucmp, largest_user_key, files[index]);
166 const std::vector<FileMetaData*>* flist)
169 index_(flist->size()) {
172 return index_ < flist_->size();
175 index_ =
FindFile(icmp_, *flist_, target);
179 index_ = flist_->empty() ? 0 : flist_->size() - 1;
188 index_ = flist_->size();
195 return (*flist_)[index_]->largest.Encode();
201 return Slice(value_buf_,
sizeof(value_buf_));
206 const std::vector<FileMetaData*>*
const flist_;
210 mutable char value_buf_[16];
215 const Slice& file_value) {
217 if (file_value.
size() != 16) {
235 std::vector<Iterator*>* iters) {
237 for (
size_t i = 0; i <
files_[0].size(); i++) {
240 options,
files_[0][i]->number,
files_[0][i]->file_size));
247 if (!
files_[level].empty()) {
269 Saver* s =
reinterpret_cast<Saver*
>(arg);
274 if (s->ucmp->Compare(parsed_key.
user_key, s->user_key) == 0) {
277 s->value->assign(v.
data(), v.
size());
294 std::vector<FileMetaData*> tmp;
295 tmp.reserve(
files_[0].size());
296 for (uint32_t i = 0; i <
files_[0].size(); i++) {
305 for (uint32_t i = 0; i < tmp.size(); i++) {
306 if (!(*func)(arg, 0, tmp[i])) {
314 size_t num_files =
files_[level].size();
315 if (num_files == 0)
continue;
319 if (index < num_files) {
324 if (!(*func)(arg, level, f)) {
344 int last_file_read_level = -1;
349 std::vector<FileMetaData*> tmp;
352 size_t num_files =
files_[level].size();
353 if (num_files == 0)
continue;
360 tmp.reserve(num_files);
361 for (uint32_t i = 0; i < num_files; i++) {
368 if (tmp.empty())
continue;
372 num_files = tmp.size();
376 if (index >= num_files) {
392 for (uint32_t i = 0; i < num_files; ++i) {
393 if (last_file_read != NULL && stats->
seek_file == NULL) {
401 last_file_read_level = level;
406 saver.user_key = user_key;
413 switch (saver.state) {
454 static bool Match(
void* arg,
int level,
FileMetaData* f) {
457 if (state->matches == 1) {
459 state->stats.seek_file = f;
460 state->stats.seek_file_level = level;
463 return state->matches < 2;
475 if (state.matches >= 2) {
496 const Slice* smallest_user_key,
497 const Slice* largest_user_key) {
499 smallest_user_key, largest_user_key);
503 const Slice& smallest_user_key,
504 const Slice& largest_user_key) {
510 InternalKey limit(largest_user_key, 0, static_cast<ValueType>(0));
511 std::vector<FileMetaData*> overlaps;
513 if (
OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) {
535 std::vector<FileMetaData*>* inputs) {
539 Slice user_begin, user_end;
547 for (
size_t i = 0; i <
files_[level].size(); ) {
551 if (begin != NULL && user_cmp->
Compare(file_limit, user_begin) < 0) {
553 }
else if (end != NULL && user_cmp->
Compare(file_start, user_end) > 0) {
556 inputs->push_back(f);
560 if (begin != NULL && user_cmp->
Compare(file_start, user_begin) < 0) {
561 user_begin = file_start;
564 }
else if (end != NULL && user_cmp->
Compare(file_limit, user_end) > 0) {
565 user_end = file_limit;
581 r.append(
"--- level ");
584 const std::vector<FileMetaData*>& files =
files_[level];
585 for (
size_t i = 0; i < files.size(); i++) {
591 r.append(files[i]->smallest.DebugString());
593 r.append(files[i]->largest.DebugString());
620 typedef std::set<FileMetaData*, BySmallestKey>
FileSet;
646 std::vector<FileMetaData*> to_unref;
647 to_unref.reserve(added->size());
648 for (FileSet::const_iterator it = added->begin();
649 it != added->end(); ++it) {
650 to_unref.push_back(*it);
653 for (uint32_t i = 0; i < to_unref.size(); i++) {
675 for (VersionEdit::DeletedFileSet::const_iterator iter = del.begin();
678 const int level = iter->first;
679 const uint64_t number = iter->second;
684 for (
size_t i = 0; i < edit->
new_files_.size(); i++) {
717 const std::vector<FileMetaData*>& base_files = base_->
files_[level];
718 std::vector<FileMetaData*>::const_iterator base_iter = base_files.begin();
719 std::vector<FileMetaData*>::const_iterator base_end = base_files.end();
721 v->
files_[level].reserve(base_files.size() + added->size());
722 for (FileSet::const_iterator added_iter = added->begin();
723 added_iter != added->end();
726 for (std::vector<FileMetaData*>::const_iterator bpos
727 = std::upper_bound(base_iter, base_end, *added_iter, cmp);
730 MaybeAddFile(v, level, *base_iter);
733 MaybeAddFile(v, level, *added_iter);
737 for (; base_iter != base_end; ++base_iter) {
738 MaybeAddFile(v, level, *base_iter);
744 for (uint32_t i = 1; i < v->
files_[level].size(); i++) {
748 fprintf(stderr,
"overlapping ranges in same level %s vs. %s\n",
760 if (levels_[level].deleted_files.count(f->
number) > 0) {
763 std::vector<FileMetaData*>* files = &v->
files_[level];
764 if (level > 0 && !files->empty()) {
766 assert(vset_->
icmp_.
Compare((*files)[files->size()-1]->largest,
779 : env_(options->env),
782 table_cache_(table_cache),
784 next_file_number_(2),
785 manifest_file_number_(0),
789 descriptor_file_(NULL),
790 descriptor_log_(NULL),
791 dummy_versions_(this),
805 assert(v->
refs_ == 0);
845 std::string new_manifest_file;
879 if (s.
ok() && !new_manifest_file.empty()) {
893 if (!new_manifest_file.empty()) {
908 virtual void Corruption(
size_t bytes,
const Status& s) {
909 if (this->status->
ok()) *this->status = s;
919 if (current.empty() || current[current.size()-1] !=
'\n') {
922 current.resize(current.size() - 1);
931 bool have_log_number =
false;
932 bool have_prev_log_number =
false;
933 bool have_next_file =
false;
934 bool have_last_sequence =
false;
935 uint64_t next_file = 0;
936 uint64_t last_sequence = 0;
937 uint64_t log_number = 0;
938 uint64_t prev_log_number = 0;
942 LogReporter reporter;
943 reporter.status = &s;
947 while (reader.
ReadRecord(&record, &scratch) && s.
ok()) {
954 edit.
comparator_ +
" does not match existing comparator ",
960 builder.
Apply(&edit);
965 have_log_number =
true;
970 have_prev_log_number =
true;
975 have_next_file =
true;
980 have_last_sequence =
true;
988 if (!have_next_file) {
990 }
else if (!have_log_number) {
992 }
else if (!have_last_sequence) {
996 if (!have_prev_log_number) {
1020 *save_manifest =
true;
1028 const std::string& dscbase) {
1033 uint64_t manifest_number;
1034 uint64_t manifest_size;
1035 if (!
ParseFileName(dscbase, &manifest_number, &manifest_type) ||
1066 int best_level = -1;
1067 double best_score = -1;
1083 score = v->
files_[level].size() /
1092 if (score > best_score) {
1120 const std::vector<FileMetaData*>& files =
current_->
files_[level];
1121 for (
size_t i = 0; i < files.size(); i++) {
1142 "files[ %d %d %d %d %d %d %d ]",
1154 uint64_t result = 0;
1156 const std::vector<FileMetaData*>& files = v->
files_[level];
1157 for (
size_t i = 0; i < files.size(); i++) {
1160 result += files[i]->file_size;
1161 }
else if (
icmp_.
Compare(files[i]->smallest, ikey) > 0) {
1174 ReadOptions(), files[i]->number, files[i]->file_size, &tableptr);
1175 if (tableptr != NULL) {
1190 const std::vector<FileMetaData*>& files = v->files_[level];
1191 for (
size_t i = 0; i < files.size(); i++) {
1192 live->insert(files[i]->number);
1206 std::vector<FileMetaData*> overlaps;
1227 assert(!inputs.empty());
1230 for (
size_t i = 0; i < inputs.size(); i++) {
1250 const std::vector<FileMetaData*>& inputs2,
1253 std::vector<FileMetaData*> all = inputs1;
1254 all.insert(all.end(), inputs2.begin(), inputs2.end());
1266 const int space = (c->
level() == 0 ? c->
inputs_[0].size() + 1 : 2);
1269 for (
int which = 0; which < 2; which++) {
1270 if (!c->
inputs_[which].empty()) {
1271 if (c->
level() + which == 0) {
1272 const std::vector<FileMetaData*>& files = c->
inputs_[which];
1273 for (
size_t i = 0; i < files.size(); i++) {
1275 options, files[i]->number, files[i]->file_size);
1285 assert(num <= space);
1299 if (size_compaction) {
1318 }
else if (seek_compaction) {
1337 assert(!c->
inputs_[0].empty());
1346 const int level = c->
level();
1359 std::vector<FileMetaData*> expanded0;
1364 if (expanded0.size() > c->
inputs_[0].size() &&
1365 inputs1_size + expanded0_size <
1368 GetRange(expanded0, &new_start, &new_limit);
1369 std::vector<FileMetaData*> expanded1;
1372 if (expanded1.size() == c->
inputs_[1].size()) {
1374 "Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n",
1378 long(inputs0_size), long(inputs1_size),
1379 int(expanded0.size()),
1380 int(expanded1.size()),
1381 long(expanded0_size), long(inputs1_size));
1382 smallest = new_start;
1383 largest = new_limit;
1417 std::vector<FileMetaData*> inputs;
1419 if (inputs.empty()) {
1430 for (
size_t i = 0; i < inputs.size(); i++) {
1431 uint64_t s = inputs[i]->file_size;
1433 if (total >= limit) {
1434 inputs.resize(i + 1);
1451 input_version_(NULL),
1452 grandparent_index_(0),
1454 overlapped_bytes_(0) {
1477 for (
int which = 0; which < 2; which++) {
1478 for (
size_t i = 0; i <
inputs_[which].size(); i++) {
uint64_t ApproximateOffsetOf(Version *v, const InternalKey &key)
void GetRange(const std::vector< FileMetaData *> &inputs, InternalKey *smallest, InternalKey *largest)
virtual int Compare(const Slice &a, const Slice &b) const
size_t level_ptrs_[config::kNumLevels]
std::vector< FileMetaData * > files_[config::kNumLevels]
static const SequenceNumber kMaxSequenceNumber
static int TargetFileSize(const Options *options)
WritableFile * descriptor_file_
TableCache *const table_cache_
std::set< uint64_t > deleted_files
Version * current() const
void SetPrevLogNumber(uint64_t num)
bool ShouldStopBefore(const Slice &internal_key)
int PickLevelForMemTableOutput(const Slice &smallest_user_key, const Slice &largest_user_key)
bool ParseFileName(const std::string &fname, uint64_t *number, FileType *type)
uint64_t DecodeFixed64(const char *ptr)
static Status NotFound(const Slice &msg, const Slice &msg2=Slice())
void SetLastSequence(SequenceNumber seq)
std::set< FileMetaData *, BySmallestKey > FileSet
Iterator * NewConcatenatingIterator(const ReadOptions &, int level) const
const std::string dbname_
static const int kNumLevels
int FindFile(const InternalKeyComparator &icmp, const std::vector< FileMetaData *> &files, const Slice &key)
void SetLogNumber(uint64_t num)
DeletedFileSet deleted_files_
void SetComparatorName(const Slice &name)
virtual void Seek(const Slice &target)
void DeleteFile(int level, uint64_t file)
bool UpdateStats(const GetStats &stats)
void SetNextFile(uint64_t num)
Iterator * MakeInputIterator(Compaction *c)
void SetCompactPointer(int level, const InternalKey &key)
Status LogAndApply(VersionEdit *edit, port::Mutex *mu) EXCLUSIVE_LOCKS_REQUIRED(mu)
const Comparator * user_comparator() const
Status WriteSnapshot(log::Writer *log)
void Log(Logger *info_log, const char *format,...)
VersionSet(const std::string &dbname, const Options *options, TableCache *table_cache, const InternalKeyComparator *)
void GetOverlappingInputs(int level, const InternalKey *begin, const InternalKey *end, std::vector< FileMetaData *> *inputs)
std::string ToString() const
std::string DebugString() const
virtual Status GetFileSize(const std::string &fname, uint64_t *file_size)=0
std::set< std::pair< int, uint64_t > > DeletedFileSet
virtual Status NewWritableFile(const std::string &fname, WritableFile **result)=0
bool ParseInternalKey(const Slice &internal_key, ParsedInternalKey *result)
void SetupOtherInputs(Compaction *c)
virtual bool Valid() const
bool SomeFileOverlapsRange(const InternalKeyComparator &icmp, bool disjoint_sorted_files, const std::vector< FileMetaData *> &files, const Slice *smallest_user_key, const Slice *largest_user_key)
void Finalize(Version *v)
virtual const char * Name() const =0
uint64_t next_file_number_
static Status Corruption(const Slice &msg, const Slice &msg2=Slice())
int64_t NumLevelBytes(int level) const
static const int kL0_CompactionTrigger
bool OverlapInLevel(int level, const Slice *smallest_user_key, const Slice *largest_user_key)
void EncodeFixed64(char *buf, uint64_t value)
int file_to_compact_level_
const InternalKeyComparator icmp_
std::string ToString() const
static const ValueType kValueTypeForSeek
FileMetaData * file_to_compact_
bool ReadRecord(Slice *record, std::string *scratch)
std::string DebugString() const
void AddIterators(const ReadOptions &, std::vector< Iterator *> *iters)
std::vector< FileMetaData * > inputs_[2]
std::string DescriptorFileName(const std::string &dbname, uint64_t number)
uint64_t next_file_number_
int NumLevelFiles(int level) const
Compaction(const Options *options, int level)
void MarkFileNumberUsed(uint64_t number)
log::Writer * descriptor_log_
Iterator * NewErrorIterator(const Status &status)
static bool NewestFirst(FileMetaData *a, FileMetaData *b)
bool has_next_file_number_
static bool BeforeFile(const Comparator *ucmp, const Slice *user_key, const FileMetaData *f)
std::string compact_pointer_[config::kNumLevels]
virtual void SeekToLast()
static const int kMaxMemCompactLevel
void DecodeFrom(const Slice &s)
Status SetCurrentFile(Env *env, const std::string &dbname, uint64_t descriptor_number)
std::string CurrentFileName(const std::string &dbname)
Slice internal_key() const
uint64_t prev_log_number_
static void SaveValue(void *arg, const Slice &ikey, const Slice &v)
bool IsTrivialMove() const
void EncodeTo(std::string *dst) const
static bool AfterFile(const Comparator *ucmp, const Slice *user_key, const FileMetaData *f)
static int64_t MaxGrandParentOverlapBytes(const Options *options)
Status Recover(bool *save_manifest)
bool IsBaseLevelForKey(const Slice &user_key)
bool has_prev_log_number_
void ForEachOverlapping(Slice user_key, Slice internal_key, void *arg, bool(*func)(void *, int, FileMetaData *))
virtual Status NewAppendableFile(const std::string &fname, WritableFile **result)
virtual void SeekToFirst()
Iterator * NewMergingIterator(const Comparator *cmp, Iterator **list, int n)
Iterator * NewIterator(const ReadOptions &options, uint64_t file_number, uint64_t file_size, Table **tableptr=NULL)
void AppendVersion(Version *v)
bool RecordReadSample(Slice key)
virtual Status status() const
const char * LevelSummary(LevelSummaryStorage *scratch) const
uint64_t ApproximateOffsetOf(const Slice &key) const
int64_t overlapped_bytes_
static int64_t TotalFileSize(const std::vector< FileMetaData *> &files)
bool ReuseManifest(const std::string &dscname, const std::string &dscbase)
static int64_t ExpandedCompactionByteSizeLimit(const Options *options)
Iterator * NewTwoLevelIterator(Iterator *index_iter, BlockFunction block_function, void *arg, const ReadOptions &options)
Compaction * CompactRange(int level, const InternalKey *begin, const InternalKey *end)
SequenceNumber last_sequence_
static Status InvalidArgument(const Slice &msg, const Slice &msg2=Slice())
virtual Status NewSequentialFile(const std::string &fname, SequentialFile **result)=0
Status DecodeFrom(const Slice &src)
Compaction * PickCompaction()
std::vector< std::pair< int, InternalKey > > compact_pointers_
Status AddRecord(const Slice &slice)
std::vector< std::pair< int, FileMetaData > > new_files_
static uint64_t MaxFileSizeForLevel(const Options *options, int level)
bool operator()(FileMetaData *f1, FileMetaData *f2) const
Status Get(const ReadOptions &options, uint64_t file_number, uint64_t file_size, const Slice &k, void *arg, void(*handle_result)(void *, const Slice &, const Slice &))
void AddFile(int level, uint64_t file, uint64_t file_size, const InternalKey &smallest, const InternalKey &largest)
const InternalKeyComparator * internal_comparator
virtual int Compare(const Slice &a, const Slice &b) const =0
uint64_t manifest_file_number_
const InternalKeyComparator icmp_
void MaybeAddFile(Version *v, int level, FileMetaData *f)
Status Get(const ReadOptions &, const LookupKey &key, std::string *val, GetStats *stats)
static double MaxBytesForLevel(const Options *options, int level)
void AddLiveFiles(std::set< uint64_t > *live)
const char * data() const
LevelFileNumIterator(const InternalKeyComparator &icmp, const std::vector< FileMetaData *> *flist)
virtual Status DeleteFile(const std::string &fname)=0
std::vector< FileMetaData * > grandparents_
uint64_t prev_log_number_
static Iterator * GetFileIterator(void *arg, const ReadOptions &options, const Slice &file_value)
void AddInputDeletions(VersionEdit *edit)
const Options *const options_
void GetRange2(const std::vector< FileMetaData *> &inputs1, const std::vector< FileMetaData *> &inputs2, InternalKey *smallest, InternalKey *largest)
void Apply(VersionEdit *edit)
size_t grandparent_index_
Builder(VersionSet *vset, Version *base)
int64_t MaxNextLevelOverlappingBytes()
int num_input_files(int which) const
void AppendNumberTo(std::string *str, uint64_t num)
Status ReadFileToString(Env *env, const std::string &fname, std::string *data)
const std::vector< FileMetaData * > *const flist_