leveldb
Classes | Public Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
leveldb::VersionSet Class Reference

#include <version_set.h>

Collaboration diagram for leveldb::VersionSet:
Collaboration graph
[legend]

Classes

class  Builder
 
struct  LevelSummaryStorage
 

Public Member Functions

 VersionSet (const std::string &dbname, const Options *options, TableCache *table_cache, const InternalKeyComparator *)
 
 ~VersionSet ()
 
Status LogAndApply (VersionEdit *edit, port::Mutex *mu) EXCLUSIVE_LOCKS_REQUIRED(mu)
 
Status Recover (bool *save_manifest)
 
Versioncurrent () const
 
uint64_t ManifestFileNumber () const
 
uint64_t NewFileNumber ()
 
void ReuseFileNumber (uint64_t file_number)
 
int NumLevelFiles (int level) const
 
int64_t NumLevelBytes (int level) const
 
uint64_t LastSequence () const
 
void SetLastSequence (uint64_t s)
 
void MarkFileNumberUsed (uint64_t number)
 
uint64_t LogNumber () const
 
uint64_t PrevLogNumber () const
 
CompactionPickCompaction ()
 
CompactionCompactRange (int level, const InternalKey *begin, const InternalKey *end)
 
int64_t MaxNextLevelOverlappingBytes ()
 
IteratorMakeInputIterator (Compaction *c)
 
bool NeedsCompaction () const
 
void AddLiveFiles (std::set< uint64_t > *live)
 
uint64_t ApproximateOffsetOf (Version *v, const InternalKey &key)
 
const char * LevelSummary (LevelSummaryStorage *scratch) const
 

Private Member Functions

bool ReuseManifest (const std::string &dscname, const std::string &dscbase)
 
void Finalize (Version *v)
 
void GetRange (const std::vector< FileMetaData *> &inputs, InternalKey *smallest, InternalKey *largest)
 
void GetRange2 (const std::vector< FileMetaData *> &inputs1, const std::vector< FileMetaData *> &inputs2, InternalKey *smallest, InternalKey *largest)
 
void SetupOtherInputs (Compaction *c)
 
Status WriteSnapshot (log::Writer *log)
 
void AppendVersion (Version *v)
 
 VersionSet (const VersionSet &)
 
void operator= (const VersionSet &)
 

Private Attributes

Env *const env_
 
const std::string dbname_
 
const Options *const options_
 
TableCache *const table_cache_
 
const InternalKeyComparator icmp_
 
uint64_t next_file_number_
 
uint64_t manifest_file_number_
 
uint64_t last_sequence_
 
uint64_t log_number_
 
uint64_t prev_log_number_
 
WritableFiledescriptor_file_
 
log::Writerdescriptor_log_
 
Version dummy_versions_
 
Versioncurrent_
 
std::string compact_pointer_ [config::kNumLevels]
 

Friends

class Compaction
 
class Version
 

Detailed Description

Definition at line 165 of file version_set.h.


Class Documentation

§ leveldb::VersionSet::LevelSummaryStorage

struct leveldb::VersionSet::LevelSummaryStorage

Definition at line 266 of file version_set.h.

Class Members
char buffer[100]

Constructor & Destructor Documentation

§ VersionSet() [1/2]

leveldb::VersionSet::VersionSet ( const std::string &  dbname,
const Options options,
TableCache table_cache,
const InternalKeyComparator cmp 
)

Definition at line 775 of file version_set.cc.

779  : env_(options->env),
780  dbname_(dbname),
781  options_(options),
782  table_cache_(table_cache),
783  icmp_(*cmp),
785  manifest_file_number_(0), // Filled by Recover()
786  last_sequence_(0),
787  log_number_(0),
788  prev_log_number_(0),
789  descriptor_file_(NULL),
790  descriptor_log_(NULL),
791  dummy_versions_(this),
792  current_(NULL) {
793  AppendVersion(new Version(this));
794 }
WritableFile * descriptor_file_
Definition: version_set.h:309
TableCache *const table_cache_
Definition: version_set.h:300
uint64_t last_sequence_
Definition: version_set.h:304
const std::string dbname_
Definition: version_set.h:298
uint64_t next_file_number_
Definition: version_set.h:302
const InternalKeyComparator icmp_
Definition: version_set.h:301
friend class Version
Definition: version_set.h:275
log::Writer * descriptor_log_
Definition: version_set.h:310
static char dbname[200]
Definition: c_test.c:15
void AppendVersion(Version *v)
Definition: version_set.cc:803
uint64_t manifest_file_number_
Definition: version_set.h:303
uint64_t prev_log_number_
Definition: version_set.h:306
const Options *const options_
Definition: version_set.h:299
Here is the call graph for this function:

§ ~VersionSet()

leveldb::VersionSet::~VersionSet ( )

Definition at line 796 of file version_set.cc.

796  {
797  current_->Unref();
798  assert(dummy_versions_.next_ == &dummy_versions_); // List must be empty
799  delete descriptor_log_;
800  delete descriptor_file_;
801 }
Version * next_
Definition: version_set.h:133
WritableFile * descriptor_file_
Definition: version_set.h:309
log::Writer * descriptor_log_
Definition: version_set.h:310
Here is the call graph for this function:

§ VersionSet() [2/2]

leveldb::VersionSet::VersionSet ( const VersionSet )
private

Member Function Documentation

§ AddLiveFiles()

void leveldb::VersionSet::AddLiveFiles ( std::set< uint64_t > *  live)

Definition at line 1185 of file version_set.cc.

1185  {
1186  for (Version* v = dummy_versions_.next_;
1187  v != &dummy_versions_;
1188  v = v->next_) {
1189  for (int level = 0; level < config::kNumLevels; level++) {
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);
1193  }
1194  }
1195  }
1196 }
Version * next_
Definition: version_set.h:133
static const int kNumLevels
Definition: dbformat.h:22
friend class Version
Definition: version_set.h:275
Here is the caller graph for this function:

§ AppendVersion()

void leveldb::VersionSet::AppendVersion ( Version v)
private

Definition at line 803 of file version_set.cc.

803  {
804  // Make "v" current
805  assert(v->refs_ == 0);
806  assert(v != current_);
807  if (current_ != NULL) {
808  current_->Unref();
809  }
810  current_ = v;
811  v->Ref();
812 
813  // Append to linked list
814  v->prev_ = dummy_versions_.prev_;
815  v->next_ = &dummy_versions_;
816  v->prev_->next_ = v;
817  v->next_->prev_ = v;
818 }
Version * next_
Definition: version_set.h:133
Version * prev_
Definition: version_set.h:134
Here is the call graph for this function:
Here is the caller graph for this function:

§ ApproximateOffsetOf()

uint64_t leveldb::VersionSet::ApproximateOffsetOf ( Version v,
const InternalKey key 
)

Definition at line 1153 of file version_set.cc.

1153  {
1154  uint64_t result = 0;
1155  for (int level = 0; level < config::kNumLevels; level++) {
1156  const std::vector<FileMetaData*>& files = v->files_[level];
1157  for (size_t i = 0; i < files.size(); i++) {
1158  if (icmp_.Compare(files[i]->largest, ikey) <= 0) {
1159  // Entire file is before "ikey", so just add the file size
1160  result += files[i]->file_size;
1161  } else if (icmp_.Compare(files[i]->smallest, ikey) > 0) {
1162  // Entire file is after "ikey", so ignore
1163  if (level > 0) {
1164  // Files other than level 0 are sorted by meta->smallest, so
1165  // no further files in this level will contain data for
1166  // "ikey".
1167  break;
1168  }
1169  } else {
1170  // "ikey" falls in the range for this table. Add the
1171  // approximate offset of "ikey" within the table.
1172  Table* tableptr;
1173  Iterator* iter = table_cache_->NewIterator(
1174  ReadOptions(), files[i]->number, files[i]->file_size, &tableptr);
1175  if (tableptr != NULL) {
1176  result += tableptr->ApproximateOffsetOf(ikey.Encode());
1177  }
1178  delete iter;
1179  }
1180  }
1181  }
1182  return result;
1183 }
virtual int Compare(const Slice &a, const Slice &b) const
Definition: dbformat.cc:50
TableCache *const table_cache_
Definition: version_set.h:300
static const int kNumLevels
Definition: dbformat.h:22
const InternalKeyComparator icmp_
Definition: version_set.h:301
Iterator * NewIterator(const ReadOptions &options, uint64_t file_number, uint64_t file_size, Table **tableptr=NULL)
Definition: table_cache.cc:82
Here is the call graph for this function:
Here is the caller graph for this function:

§ CompactRange()

Compaction * leveldb::VersionSet::CompactRange ( int  level,
const InternalKey begin,
const InternalKey end 
)

Definition at line 1413 of file version_set.cc.

1416  {
1417  std::vector<FileMetaData*> inputs;
1418  current_->GetOverlappingInputs(level, begin, end, &inputs);
1419  if (inputs.empty()) {
1420  return NULL;
1421  }
1422 
1423  // Avoid compacting too much in one shot in case the range is large.
1424  // But we cannot do this for level-0 since level-0 files can overlap
1425  // and we must not pick one file and drop another older file if the
1426  // two files overlap.
1427  if (level > 0) {
1428  const uint64_t limit = MaxFileSizeForLevel(options_, level);
1429  uint64_t total = 0;
1430  for (size_t i = 0; i < inputs.size(); i++) {
1431  uint64_t s = inputs[i]->file_size;
1432  total += s;
1433  if (total >= limit) {
1434  inputs.resize(i + 1);
1435  break;
1436  }
1437  }
1438  }
1439 
1440  Compaction* c = new Compaction(options_, level);
1441  c->input_version_ = current_;
1442  c->input_version_->Ref();
1443  c->inputs_[0] = inputs;
1444  SetupOtherInputs(c);
1445  return c;
1446 }
friend class Compaction
Definition: version_set.h:272
void GetOverlappingInputs(int level, const InternalKey *begin, const InternalKey *end, std::vector< FileMetaData *> *inputs)
Definition: version_set.cc:531
void SetupOtherInputs(Compaction *c)
static uint64_t MaxFileSizeForLevel(const Options *options, int level)
Definition: version_set.cc:53
const Options *const options_
Definition: version_set.h:299
Here is the call graph for this function:
Here is the caller graph for this function:

§ current()

Version* leveldb::VersionSet::current ( ) const
inline

Definition at line 185 of file version_set.h.

185 { return current_; }
Here is the caller graph for this function:

§ Finalize()

void leveldb::VersionSet::Finalize ( Version v)
private

Definition at line 1064 of file version_set.cc.

1064  {
1065  // Precomputed best level for next compaction
1066  int best_level = -1;
1067  double best_score = -1;
1068 
1069  for (int level = 0; level < config::kNumLevels-1; level++) {
1070  double score;
1071  if (level == 0) {
1072  // We treat level-0 specially by bounding the number of files
1073  // instead of number of bytes for two reasons:
1074  //
1075  // (1) With larger write-buffer sizes, it is nice not to do too
1076  // many level-0 compactions.
1077  //
1078  // (2) The files in level-0 are merged on every read and
1079  // therefore we wish to avoid too many files when the individual
1080  // file size is small (perhaps because of a small write-buffer
1081  // setting, or very high compression ratios, or lots of
1082  // overwrites/deletions).
1083  score = v->files_[level].size() /
1084  static_cast<double>(config::kL0_CompactionTrigger);
1085  } else {
1086  // Compute the ratio of current size to size limit.
1087  const uint64_t level_bytes = TotalFileSize(v->files_[level]);
1088  score =
1089  static_cast<double>(level_bytes) / MaxBytesForLevel(options_, level);
1090  }
1091 
1092  if (score > best_score) {
1093  best_level = level;
1094  best_score = score;
1095  }
1096  }
1097 
1098  v->compaction_level_ = best_level;
1099  v->compaction_score_ = best_score;
1100 }
static const int kNumLevels
Definition: dbformat.h:22
static const int kL0_CompactionTrigger
Definition: dbformat.h:25
static int64_t TotalFileSize(const std::vector< FileMetaData *> &files)
Definition: version_set.cc:58
static double MaxBytesForLevel(const Options *options, int level)
Definition: version_set.cc:40
const Options *const options_
Definition: version_set.h:299
Here is the call graph for this function:
Here is the caller graph for this function:

§ GetRange()

void leveldb::VersionSet::GetRange ( const std::vector< FileMetaData *> &  inputs,
InternalKey smallest,
InternalKey largest 
)
private

Definition at line 1224 of file version_set.cc.

1226  {
1227  assert(!inputs.empty());
1228  smallest->Clear();
1229  largest->Clear();
1230  for (size_t i = 0; i < inputs.size(); i++) {
1231  FileMetaData* f = inputs[i];
1232  if (i == 0) {
1233  *smallest = f->smallest;
1234  *largest = f->largest;
1235  } else {
1236  if (icmp_.Compare(f->smallest, *smallest) < 0) {
1237  *smallest = f->smallest;
1238  }
1239  if (icmp_.Compare(f->largest, *largest) > 0) {
1240  *largest = f->largest;
1241  }
1242  }
1243  }
1244 }
virtual int Compare(const Slice &a, const Slice &b) const
Definition: dbformat.cc:50
const InternalKeyComparator icmp_
Definition: version_set.h:301
Here is the call graph for this function:
Here is the caller graph for this function:

§ GetRange2()

void leveldb::VersionSet::GetRange2 ( const std::vector< FileMetaData *> &  inputs1,
const std::vector< FileMetaData *> &  inputs2,
InternalKey smallest,
InternalKey largest 
)
private

Definition at line 1249 of file version_set.cc.

1252  {
1253  std::vector<FileMetaData*> all = inputs1;
1254  all.insert(all.end(), inputs2.begin(), inputs2.end());
1255  GetRange(all, smallest, largest);
1256 }
void GetRange(const std::vector< FileMetaData *> &inputs, InternalKey *smallest, InternalKey *largest)
Here is the call graph for this function:
Here is the caller graph for this function:

§ LastSequence()

uint64_t leveldb::VersionSet::LastSequence ( ) const
inline

Definition at line 209 of file version_set.h.

209 { return last_sequence_; }
uint64_t last_sequence_
Definition: version_set.h:304
Here is the caller graph for this function:

§ LevelSummary()

const char * leveldb::VersionSet::LevelSummary ( LevelSummaryStorage scratch) const

Definition at line 1138 of file version_set.cc.

1138  {
1139  // Update code if kNumLevels changes
1140  assert(config::kNumLevels == 7);
1141  snprintf(scratch->buffer, sizeof(scratch->buffer),
1142  "files[ %d %d %d %d %d %d %d ]",
1143  int(current_->files_[0].size()),
1144  int(current_->files_[1].size()),
1145  int(current_->files_[2].size()),
1146  int(current_->files_[3].size()),
1147  int(current_->files_[4].size()),
1148  int(current_->files_[5].size()),
1149  int(current_->files_[6].size()));
1150  return scratch->buffer;
1151 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
static const int kNumLevels
Definition: dbformat.h:22
Here is the caller graph for this function:

§ LogAndApply()

Status leveldb::VersionSet::LogAndApply ( VersionEdit edit,
port::Mutex *  mu 
)

Definition at line 820 of file version_set.cc.

820  {
821  if (edit->has_log_number_) {
822  assert(edit->log_number_ >= log_number_);
823  assert(edit->log_number_ < next_file_number_);
824  } else {
825  edit->SetLogNumber(log_number_);
826  }
827 
828  if (!edit->has_prev_log_number_) {
829  edit->SetPrevLogNumber(prev_log_number_);
830  }
831 
832  edit->SetNextFile(next_file_number_);
833  edit->SetLastSequence(last_sequence_);
834 
835  Version* v = new Version(this);
836  {
837  Builder builder(this, current_);
838  builder.Apply(edit);
839  builder.SaveTo(v);
840  }
841  Finalize(v);
842 
843  // Initialize new descriptor log file if necessary by creating
844  // a temporary file that contains a snapshot of the current version.
845  std::string new_manifest_file;
846  Status s;
847  if (descriptor_log_ == NULL) {
848  // No reason to unlock *mu here since we only hit this path in the
849  // first call to LogAndApply (when opening the database).
850  assert(descriptor_file_ == NULL);
851  new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_);
852  edit->SetNextFile(next_file_number_);
853  s = env_->NewWritableFile(new_manifest_file, &descriptor_file_);
854  if (s.ok()) {
855  descriptor_log_ = new log::Writer(descriptor_file_);
857  }
858  }
859 
860  // Unlock during expensive MANIFEST log write
861  {
862  mu->Unlock();
863 
864  // Write new record to MANIFEST log
865  if (s.ok()) {
866  std::string record;
867  edit->EncodeTo(&record);
868  s = descriptor_log_->AddRecord(record);
869  if (s.ok()) {
870  s = descriptor_file_->Sync();
871  }
872  if (!s.ok()) {
873  Log(options_->info_log, "MANIFEST write: %s\n", s.ToString().c_str());
874  }
875  }
876 
877  // If we just created a new descriptor file, install it by writing a
878  // new CURRENT file that points to it.
879  if (s.ok() && !new_manifest_file.empty()) {
881  }
882 
883  mu->Lock();
884  }
885 
886  // Install the new version
887  if (s.ok()) {
888  AppendVersion(v);
889  log_number_ = edit->log_number_;
890  prev_log_number_ = edit->prev_log_number_;
891  } else {
892  delete v;
893  if (!new_manifest_file.empty()) {
894  delete descriptor_log_;
895  delete descriptor_file_;
896  descriptor_log_ = NULL;
897  descriptor_file_ = NULL;
898  env_->DeleteFile(new_manifest_file);
899  }
900  }
901 
902  return s;
903 }
WritableFile * descriptor_file_
Definition: version_set.h:309
uint64_t last_sequence_
Definition: version_set.h:304
const std::string dbname_
Definition: version_set.h:298
Status WriteSnapshot(log::Writer *log)
void Log(Logger *info_log, const char *format,...)
Definition: env.cc:31
virtual Status NewWritableFile(const std::string &fname, WritableFile **result)=0
void Finalize(Version *v)
uint64_t next_file_number_
Definition: version_set.h:302
friend class Version
Definition: version_set.h:275
std::string DescriptorFileName(const std::string &dbname, uint64_t number)
Definition: filename.cc:42
log::Writer * descriptor_log_
Definition: version_set.h:310
Status SetCurrentFile(Env *env, const std::string &dbname, uint64_t descriptor_number)
Definition: filename.cc:126
Logger * info_log
Definition: options.h:68
void AppendVersion(Version *v)
Definition: version_set.cc:803
Status AddRecord(const Slice &slice)
Definition: log_writer.cc:36
uint64_t manifest_file_number_
Definition: version_set.h:303
virtual Status Sync()=0
virtual Status DeleteFile(const std::string &fname)=0
uint64_t prev_log_number_
Definition: version_set.h:306
const Options *const options_
Definition: version_set.h:299
Here is the call graph for this function:
Here is the caller graph for this function:

§ LogNumber()

uint64_t leveldb::VersionSet::LogNumber ( ) const
inline

Definition at line 221 of file version_set.h.

221 { return log_number_; }
Here is the caller graph for this function:

§ MakeInputIterator()

Iterator * leveldb::VersionSet::MakeInputIterator ( Compaction c)

Definition at line 1258 of file version_set.cc.

1258  {
1259  ReadOptions options;
1260  options.verify_checksums = options_->paranoid_checks;
1261  options.fill_cache = false;
1262 
1263  // Level-0 files have to be merged together. For other levels,
1264  // we will make a concatenating iterator per level.
1265  // TODO(opt): use concatenating iterator for level-0 if there is no overlap
1266  const int space = (c->level() == 0 ? c->inputs_[0].size() + 1 : 2);
1267  Iterator** list = new Iterator*[space];
1268  int num = 0;
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++) {
1274  list[num++] = table_cache_->NewIterator(
1275  options, files[i]->number, files[i]->file_size);
1276  }
1277  } else {
1278  // Create concatenating iterator for the files from this level
1279  list[num++] = NewTwoLevelIterator(
1280  new Version::LevelFileNumIterator(icmp_, &c->inputs_[which]),
1281  &GetFileIterator, table_cache_, options);
1282  }
1283  }
1284  }
1285  assert(num <= space);
1286  Iterator* result = NewMergingIterator(&icmp_, list, num);
1287  delete[] list;
1288  return result;
1289 }
TableCache *const table_cache_
Definition: version_set.h:300
const InternalKeyComparator icmp_
Definition: version_set.h:301
Iterator * NewMergingIterator(const Comparator *cmp, Iterator **list, int n)
Definition: merger.cc:186
Iterator * NewIterator(const ReadOptions &options, uint64_t file_number, uint64_t file_size, Table **tableptr=NULL)
Definition: table_cache.cc:82
bool paranoid_checks
Definition: options.h:57
Iterator * NewTwoLevelIterator(Iterator *index_iter, BlockFunction block_function, void *arg, const ReadOptions &options)
static Iterator * GetFileIterator(void *arg, const ReadOptions &options, const Slice &file_value)
Definition: version_set.cc:213
const Options *const options_
Definition: version_set.h:299
Here is the call graph for this function:
Here is the caller graph for this function:

§ ManifestFileNumber()

uint64_t leveldb::VersionSet::ManifestFileNumber ( ) const
inline

Definition at line 188 of file version_set.h.

188 { return manifest_file_number_; }
uint64_t manifest_file_number_
Definition: version_set.h:303
Here is the caller graph for this function:

§ MarkFileNumberUsed()

void leveldb::VersionSet::MarkFileNumberUsed ( uint64_t  number)

Definition at line 1058 of file version_set.cc.

1058  {
1059  if (next_file_number_ <= number) {
1060  next_file_number_ = number + 1;
1061  }
1062 }
uint64_t next_file_number_
Definition: version_set.h:302
Here is the caller graph for this function:

§ MaxNextLevelOverlappingBytes()

int64_t leveldb::VersionSet::MaxNextLevelOverlappingBytes ( )

Definition at line 1204 of file version_set.cc.

1204  {
1205  int64_t result = 0;
1206  std::vector<FileMetaData*> overlaps;
1207  for (int level = 1; level < config::kNumLevels - 1; level++) {
1208  for (size_t i = 0; i < current_->files_[level].size(); i++) {
1209  const FileMetaData* f = current_->files_[level][i];
1210  current_->GetOverlappingInputs(level+1, &f->smallest, &f->largest,
1211  &overlaps);
1212  const int64_t sum = TotalFileSize(overlaps);
1213  if (sum > result) {
1214  result = sum;
1215  }
1216  }
1217  }
1218  return result;
1219 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
static const int kNumLevels
Definition: dbformat.h:22
void GetOverlappingInputs(int level, const InternalKey *begin, const InternalKey *end, std::vector< FileMetaData *> *inputs)
Definition: version_set.cc:531
static int64_t TotalFileSize(const std::vector< FileMetaData *> &files)
Definition: version_set.cc:58
Here is the call graph for this function:
Here is the caller graph for this function:

§ NeedsCompaction()

bool leveldb::VersionSet::NeedsCompaction ( ) const
inline

Definition at line 251 of file version_set.h.

251  {
252  Version* v = current_;
253  return (v->compaction_score_ >= 1) || (v->file_to_compact_ != NULL);
254  }
friend class Version
Definition: version_set.h:275
Here is the caller graph for this function:

§ NewFileNumber()

uint64_t leveldb::VersionSet::NewFileNumber ( )
inline

Definition at line 191 of file version_set.h.

191 { return next_file_number_++; }
uint64_t next_file_number_
Definition: version_set.h:302
Here is the caller graph for this function:

§ NumLevelBytes()

int64_t leveldb::VersionSet::NumLevelBytes ( int  level) const

Definition at line 1198 of file version_set.cc.

1198  {
1199  assert(level >= 0);
1200  assert(level < config::kNumLevels);
1201  return TotalFileSize(current_->files_[level]);
1202 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
static const int kNumLevels
Definition: dbformat.h:22
static int64_t TotalFileSize(const std::vector< FileMetaData *> &files)
Definition: version_set.cc:58
Here is the call graph for this function:
Here is the caller graph for this function:

§ NumLevelFiles()

int leveldb::VersionSet::NumLevelFiles ( int  level) const

Definition at line 1132 of file version_set.cc.

1132  {
1133  assert(level >= 0);
1134  assert(level < config::kNumLevels);
1135  return current_->files_[level].size();
1136 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
static const int kNumLevels
Definition: dbformat.h:22
Here is the caller graph for this function:

§ operator=()

void leveldb::VersionSet::operator= ( const VersionSet )
private

§ PickCompaction()

Compaction * leveldb::VersionSet::PickCompaction ( )

Definition at line 1291 of file version_set.cc.

1291  {
1292  Compaction* c;
1293  int level;
1294 
1295  // We prefer compactions triggered by too much data in a level over
1296  // the compactions triggered by seeks.
1297  const bool size_compaction = (current_->compaction_score_ >= 1);
1298  const bool seek_compaction = (current_->file_to_compact_ != NULL);
1299  if (size_compaction) {
1300  level = current_->compaction_level_;
1301  assert(level >= 0);
1302  assert(level+1 < config::kNumLevels);
1303  c = new Compaction(options_, level);
1304 
1305  // Pick the first file that comes after compact_pointer_[level]
1306  for (size_t i = 0; i < current_->files_[level].size(); i++) {
1307  FileMetaData* f = current_->files_[level][i];
1308  if (compact_pointer_[level].empty() ||
1309  icmp_.Compare(f->largest.Encode(), compact_pointer_[level]) > 0) {
1310  c->inputs_[0].push_back(f);
1311  break;
1312  }
1313  }
1314  if (c->inputs_[0].empty()) {
1315  // Wrap-around to the beginning of the key space
1316  c->inputs_[0].push_back(current_->files_[level][0]);
1317  }
1318  } else if (seek_compaction) {
1320  c = new Compaction(options_, level);
1321  c->inputs_[0].push_back(current_->file_to_compact_);
1322  } else {
1323  return NULL;
1324  }
1325 
1326  c->input_version_ = current_;
1327  c->input_version_->Ref();
1328 
1329  // Files in level 0 may overlap each other, so pick up all overlapping ones
1330  if (level == 0) {
1331  InternalKey smallest, largest;
1332  GetRange(c->inputs_[0], &smallest, &largest);
1333  // Note that the next call will discard the file we placed in
1334  // c->inputs_[0] earlier and replace it with an overlapping set
1335  // which will include the picked file.
1336  current_->GetOverlappingInputs(0, &smallest, &largest, &c->inputs_[0]);
1337  assert(!c->inputs_[0].empty());
1338  }
1339 
1340  SetupOtherInputs(c);
1341 
1342  return c;
1343 }
void GetRange(const std::vector< FileMetaData *> &inputs, InternalKey *smallest, InternalKey *largest)
virtual int Compare(const Slice &a, const Slice &b) const
Definition: dbformat.cc:50
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
static const int kNumLevels
Definition: dbformat.h:22
friend class Compaction
Definition: version_set.h:272
void GetOverlappingInputs(int level, const InternalKey *begin, const InternalKey *end, std::vector< FileMetaData *> *inputs)
Definition: version_set.cc:531
double compaction_score_
Definition: version_set.h:147
void SetupOtherInputs(Compaction *c)
int file_to_compact_level_
Definition: version_set.h:142
const InternalKeyComparator icmp_
Definition: version_set.h:301
FileMetaData * file_to_compact_
Definition: version_set.h:141
std::string compact_pointer_[config::kNumLevels]
Definition: version_set.h:316
const Options *const options_
Definition: version_set.h:299
Here is the call graph for this function:
Here is the caller graph for this function:

§ PrevLogNumber()

uint64_t leveldb::VersionSet::PrevLogNumber ( ) const
inline

Definition at line 225 of file version_set.h.

225 { return prev_log_number_; }
uint64_t prev_log_number_
Definition: version_set.h:306
Here is the caller graph for this function:

§ Recover()

Status leveldb::VersionSet::Recover ( bool *  save_manifest)

Definition at line 905 of file version_set.cc.

905  {
906  struct LogReporter : public log::Reader::Reporter {
907  Status* status;
908  virtual void Corruption(size_t bytes, const Status& s) {
909  if (this->status->ok()) *this->status = s;
910  }
911  };
912 
913  // Read "CURRENT" file, which contains a pointer to the current manifest file
914  std::string current;
915  Status s = ReadFileToString(env_, CurrentFileName(dbname_), &current);
916  if (!s.ok()) {
917  return s;
918  }
919  if (current.empty() || current[current.size()-1] != '\n') {
920  return Status::Corruption("CURRENT file does not end with newline");
921  }
922  current.resize(current.size() - 1);
923 
924  std::string dscname = dbname_ + "/" + current;
925  SequentialFile* file;
926  s = env_->NewSequentialFile(dscname, &file);
927  if (!s.ok()) {
928  return s;
929  }
930 
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;
939  Builder builder(this, current_);
940 
941  {
942  LogReporter reporter;
943  reporter.status = &s;
944  log::Reader reader(file, &reporter, true/*checksum*/, 0/*initial_offset*/);
945  Slice record;
946  std::string scratch;
947  while (reader.ReadRecord(&record, &scratch) && s.ok()) {
948  VersionEdit edit;
949  s = edit.DecodeFrom(record);
950  if (s.ok()) {
951  if (edit.has_comparator_ &&
952  edit.comparator_ != icmp_.user_comparator()->Name()) {
954  edit.comparator_ + " does not match existing comparator ",
955  icmp_.user_comparator()->Name());
956  }
957  }
958 
959  if (s.ok()) {
960  builder.Apply(&edit);
961  }
962 
963  if (edit.has_log_number_) {
964  log_number = edit.log_number_;
965  have_log_number = true;
966  }
967 
968  if (edit.has_prev_log_number_) {
969  prev_log_number = edit.prev_log_number_;
970  have_prev_log_number = true;
971  }
972 
973  if (edit.has_next_file_number_) {
974  next_file = edit.next_file_number_;
975  have_next_file = true;
976  }
977 
978  if (edit.has_last_sequence_) {
979  last_sequence = edit.last_sequence_;
980  have_last_sequence = true;
981  }
982  }
983  }
984  delete file;
985  file = NULL;
986 
987  if (s.ok()) {
988  if (!have_next_file) {
989  s = Status::Corruption("no meta-nextfile entry in descriptor");
990  } else if (!have_log_number) {
991  s = Status::Corruption("no meta-lognumber entry in descriptor");
992  } else if (!have_last_sequence) {
993  s = Status::Corruption("no last-sequence-number entry in descriptor");
994  }
995 
996  if (!have_prev_log_number) {
997  prev_log_number = 0;
998  }
999 
1000  MarkFileNumberUsed(prev_log_number);
1001  MarkFileNumberUsed(log_number);
1002  }
1003 
1004  if (s.ok()) {
1005  Version* v = new Version(this);
1006  builder.SaveTo(v);
1007  // Install recovered version
1008  Finalize(v);
1009  AppendVersion(v);
1010  manifest_file_number_ = next_file;
1011  next_file_number_ = next_file + 1;
1012  last_sequence_ = last_sequence;
1013  log_number_ = log_number;
1014  prev_log_number_ = prev_log_number;
1015 
1016  // See if we can reuse the existing MANIFEST file.
1017  if (ReuseManifest(dscname, current)) {
1018  // No need to save new manifest
1019  } else {
1020  *save_manifest = true;
1021  }
1022  }
1023 
1024  return s;
1025 }
Version * current() const
Definition: version_set.h:185
uint64_t last_sequence_
Definition: version_set.h:304
const std::string dbname_
Definition: version_set.h:298
const Comparator * user_comparator() const
Definition: dbformat.h:125
void Finalize(Version *v)
virtual const char * Name() const =0
uint64_t next_file_number_
Definition: version_set.h:302
static Status Corruption(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:38
const InternalKeyComparator icmp_
Definition: version_set.h:301
friend class Version
Definition: version_set.h:275
void MarkFileNumberUsed(uint64_t number)
std::string CurrentFileName(const std::string &dbname)
Definition: filename.cc:50
void AppendVersion(Version *v)
Definition: version_set.cc:803
bool ReuseManifest(const std::string &dscname, const std::string &dscbase)
static Status InvalidArgument(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:44
virtual Status NewSequentialFile(const std::string &fname, SequentialFile **result)=0
uint64_t manifest_file_number_
Definition: version_set.h:303
uint64_t prev_log_number_
Definition: version_set.h:306
Status ReadFileToString(Env *env, const std::string &fname, std::string *data)
Definition: env.cc:72
Here is the call graph for this function:
Here is the caller graph for this function:

§ ReuseFileNumber()

void leveldb::VersionSet::ReuseFileNumber ( uint64_t  file_number)
inline

Definition at line 196 of file version_set.h.

196  {
197  if (next_file_number_ == file_number + 1) {
198  next_file_number_ = file_number;
199  }
200  }
uint64_t next_file_number_
Definition: version_set.h:302
Here is the caller graph for this function:

§ ReuseManifest()

bool leveldb::VersionSet::ReuseManifest ( const std::string &  dscname,
const std::string &  dscbase 
)
private

Definition at line 1027 of file version_set.cc.

1028  {
1029  if (!options_->reuse_logs) {
1030  return false;
1031  }
1032  FileType manifest_type;
1033  uint64_t manifest_number;
1034  uint64_t manifest_size;
1035  if (!ParseFileName(dscbase, &manifest_number, &manifest_type) ||
1036  manifest_type != kDescriptorFile ||
1037  !env_->GetFileSize(dscname, &manifest_size).ok() ||
1038  // Make new compacted MANIFEST if old one is too big
1039  manifest_size >= TargetFileSize(options_)) {
1040  return false;
1041  }
1042 
1043  assert(descriptor_file_ == NULL);
1044  assert(descriptor_log_ == NULL);
1045  Status r = env_->NewAppendableFile(dscname, &descriptor_file_);
1046  if (!r.ok()) {
1047  Log(options_->info_log, "Reuse MANIFEST: %s\n", r.ToString().c_str());
1048  assert(descriptor_file_ == NULL);
1049  return false;
1050  }
1051 
1052  Log(options_->info_log, "Reusing MANIFEST %s\n", dscname.c_str());
1053  descriptor_log_ = new log::Writer(descriptor_file_, manifest_size);
1054  manifest_file_number_ = manifest_number;
1055  return true;
1056 }
static int TargetFileSize(const Options *options)
Definition: version_set.cc:23
WritableFile * descriptor_file_
Definition: version_set.h:309
bool ParseFileName(const std::string &fname, uint64_t *number, FileType *type)
Definition: filename.cc:80
void Log(Logger *info_log, const char *format,...)
Definition: env.cc:31
virtual Status GetFileSize(const std::string &fname, uint64_t *file_size)=0
log::Writer * descriptor_log_
Definition: version_set.h:310
Logger * info_log
Definition: options.h:68
virtual Status NewAppendableFile(const std::string &fname, WritableFile **result)
Definition: env.cc:12
bool ok() const
Definition: status.h:52
uint64_t manifest_file_number_
Definition: version_set.h:303
FileType
Definition: filename.h:20
const Options *const options_
Definition: version_set.h:299
Here is the call graph for this function:
Here is the caller graph for this function:

§ SetLastSequence()

void leveldb::VersionSet::SetLastSequence ( uint64_t  s)
inline

Definition at line 212 of file version_set.h.

212  {
213  assert(s >= last_sequence_);
214  last_sequence_ = s;
215  }
uint64_t last_sequence_
Definition: version_set.h:304
Here is the caller graph for this function:

§ SetupOtherInputs()

void leveldb::VersionSet::SetupOtherInputs ( Compaction c)
private

Definition at line 1345 of file version_set.cc.

1345  {
1346  const int level = c->level();
1347  InternalKey smallest, largest;
1348  GetRange(c->inputs_[0], &smallest, &largest);
1349 
1350  current_->GetOverlappingInputs(level+1, &smallest, &largest, &c->inputs_[1]);
1351 
1352  // Get entire range covered by compaction
1353  InternalKey all_start, all_limit;
1354  GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit);
1355 
1356  // See if we can grow the number of inputs in "level" without
1357  // changing the number of "level+1" files we pick up.
1358  if (!c->inputs_[1].empty()) {
1359  std::vector<FileMetaData*> expanded0;
1360  current_->GetOverlappingInputs(level, &all_start, &all_limit, &expanded0);
1361  const int64_t inputs0_size = TotalFileSize(c->inputs_[0]);
1362  const int64_t inputs1_size = TotalFileSize(c->inputs_[1]);
1363  const int64_t expanded0_size = TotalFileSize(expanded0);
1364  if (expanded0.size() > c->inputs_[0].size() &&
1365  inputs1_size + expanded0_size <
1367  InternalKey new_start, new_limit;
1368  GetRange(expanded0, &new_start, &new_limit);
1369  std::vector<FileMetaData*> expanded1;
1370  current_->GetOverlappingInputs(level+1, &new_start, &new_limit,
1371  &expanded1);
1372  if (expanded1.size() == c->inputs_[1].size()) {
1374  "Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n",
1375  level,
1376  int(c->inputs_[0].size()),
1377  int(c->inputs_[1].size()),
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;
1384  c->inputs_[0] = expanded0;
1385  c->inputs_[1] = expanded1;
1386  GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit);
1387  }
1388  }
1389  }
1390 
1391  // Compute the set of grandparent files that overlap this compaction
1392  // (parent == level+1; grandparent == level+2)
1393  if (level + 2 < config::kNumLevels) {
1394  current_->GetOverlappingInputs(level + 2, &all_start, &all_limit,
1395  &c->grandparents_);
1396  }
1397 
1398  if (false) {
1399  Log(options_->info_log, "Compacting %d '%s' .. '%s'",
1400  level,
1401  smallest.DebugString().c_str(),
1402  largest.DebugString().c_str());
1403  }
1404 
1405  // Update the place where we will do the next compaction for this level.
1406  // We update this immediately instead of waiting for the VersionEdit
1407  // to be applied so that if the compaction fails, we will try a different
1408  // key range next time.
1409  compact_pointer_[level] = largest.Encode().ToString();
1410  c->edit_.SetCompactPointer(level, largest);
1411 }
void GetRange(const std::vector< FileMetaData *> &inputs, InternalKey *smallest, InternalKey *largest)
static const int kNumLevels
Definition: dbformat.h:22
void Log(Logger *info_log, const char *format,...)
Definition: env.cc:31
void GetOverlappingInputs(int level, const InternalKey *begin, const InternalKey *end, std::vector< FileMetaData *> *inputs)
Definition: version_set.cc:531
std::string compact_pointer_[config::kNumLevels]
Definition: version_set.h:316
Logger * info_log
Definition: options.h:68
static int64_t TotalFileSize(const std::vector< FileMetaData *> &files)
Definition: version_set.cc:58
static int64_t ExpandedCompactionByteSizeLimit(const Options *options)
Definition: version_set.cc:36
const Options *const options_
Definition: version_set.h:299
void GetRange2(const std::vector< FileMetaData *> &inputs1, const std::vector< FileMetaData *> &inputs2, InternalKey *smallest, InternalKey *largest)
Here is the call graph for this function:
Here is the caller graph for this function:

§ WriteSnapshot()

Status leveldb::VersionSet::WriteSnapshot ( log::Writer log)
private

Definition at line 1102 of file version_set.cc.

1102  {
1103  // TODO: Break up into multiple records to reduce memory usage on recovery?
1104 
1105  // Save metadata
1106  VersionEdit edit;
1107  edit.SetComparatorName(icmp_.user_comparator()->Name());
1108 
1109  // Save compaction pointers
1110  for (int level = 0; level < config::kNumLevels; level++) {
1111  if (!compact_pointer_[level].empty()) {
1112  InternalKey key;
1113  key.DecodeFrom(compact_pointer_[level]);
1114  edit.SetCompactPointer(level, key);
1115  }
1116  }
1117 
1118  // Save files
1119  for (int level = 0; level < config::kNumLevels; level++) {
1120  const std::vector<FileMetaData*>& files = current_->files_[level];
1121  for (size_t i = 0; i < files.size(); i++) {
1122  const FileMetaData* f = files[i];
1123  edit.AddFile(level, f->number, f->file_size, f->smallest, f->largest);
1124  }
1125  }
1126 
1127  std::string record;
1128  edit.EncodeTo(&record);
1129  return log->AddRecord(record);
1130 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
static const int kNumLevels
Definition: dbformat.h:22
const Comparator * user_comparator() const
Definition: dbformat.h:125
virtual const char * Name() const =0
const InternalKeyComparator icmp_
Definition: version_set.h:301
std::string compact_pointer_[config::kNumLevels]
Definition: version_set.h:316
Here is the call graph for this function:
Here is the caller graph for this function:

Friends And Related Function Documentation

§ Compaction

friend class Compaction
friend

Definition at line 272 of file version_set.h.

§ Version

friend class Version
friend

Definition at line 275 of file version_set.h.

Member Data Documentation

§ compact_pointer_

std::string leveldb::VersionSet::compact_pointer_[config::kNumLevels]
private

Definition at line 316 of file version_set.h.

§ current_

Version* leveldb::VersionSet::current_
private

Definition at line 312 of file version_set.h.

§ dbname_

const std::string leveldb::VersionSet::dbname_
private

Definition at line 298 of file version_set.h.

§ descriptor_file_

WritableFile* leveldb::VersionSet::descriptor_file_
private

Definition at line 309 of file version_set.h.

§ descriptor_log_

log::Writer* leveldb::VersionSet::descriptor_log_
private

Definition at line 310 of file version_set.h.

§ dummy_versions_

Version leveldb::VersionSet::dummy_versions_
private

Definition at line 311 of file version_set.h.

§ env_

Env* const leveldb::VersionSet::env_
private

Definition at line 297 of file version_set.h.

§ icmp_

const InternalKeyComparator leveldb::VersionSet::icmp_
private

Definition at line 301 of file version_set.h.

§ last_sequence_

uint64_t leveldb::VersionSet::last_sequence_
private

Definition at line 304 of file version_set.h.

§ log_number_

uint64_t leveldb::VersionSet::log_number_
private

Definition at line 305 of file version_set.h.

§ manifest_file_number_

uint64_t leveldb::VersionSet::manifest_file_number_
private

Definition at line 303 of file version_set.h.

§ next_file_number_

uint64_t leveldb::VersionSet::next_file_number_
private

Definition at line 302 of file version_set.h.

§ options_

const Options* const leveldb::VersionSet::options_
private

Definition at line 299 of file version_set.h.

§ prev_log_number_

uint64_t leveldb::VersionSet::prev_log_number_
private

Definition at line 306 of file version_set.h.

§ table_cache_

TableCache* const leveldb::VersionSet::table_cache_
private

Definition at line 300 of file version_set.h.


The documentation for this class was generated from the following files: