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

#include <version_set.h>

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

Classes

struct  GetStats
 
class  LevelFileNumIterator
 

Public Member Functions

void AddIterators (const ReadOptions &, std::vector< Iterator *> *iters)
 
Status Get (const ReadOptions &, const LookupKey &key, std::string *val, GetStats *stats)
 
bool UpdateStats (const GetStats &stats)
 
bool RecordReadSample (Slice key)
 
void Ref ()
 
void Unref ()
 
void GetOverlappingInputs (int level, const InternalKey *begin, const InternalKey *end, std::vector< FileMetaData *> *inputs)
 
bool OverlapInLevel (int level, const Slice *smallest_user_key, const Slice *largest_user_key)
 
int PickLevelForMemTableOutput (const Slice &smallest_user_key, const Slice &largest_user_key)
 
int NumFiles (int level) const
 
std::string DebugString () const
 

Private Member Functions

IteratorNewConcatenatingIterator (const ReadOptions &, int level) const
 
void ForEachOverlapping (Slice user_key, Slice internal_key, void *arg, bool(*func)(void *, int, FileMetaData *))
 
 Version (VersionSet *vset)
 
 ~Version ()
 
 Version (const Version &)
 
void operator= (const Version &)
 

Private Attributes

VersionSetvset_
 
Versionnext_
 
Versionprev_
 
int refs_
 
std::vector< FileMetaData * > files_ [config::kNumLevels]
 
FileMetaDatafile_to_compact_
 
int file_to_compact_level_
 
double compaction_score_
 
int compaction_level_
 

Friends

class Compaction
 
class VersionSet
 

Detailed Description

Definition at line 59 of file version_set.h.


Class Documentation

§ leveldb::Version::GetStats

struct leveldb::Version::GetStats

Definition at line 69 of file version_set.h.

Collaboration diagram for leveldb::Version::GetStats:
Class Members
FileMetaData * seek_file
int seek_file_level

Constructor & Destructor Documentation

§ Version() [1/2]

leveldb::Version::Version ( VersionSet vset)
inlineexplicitprivate

Definition at line 150 of file version_set.h.

151  : vset_(vset), next_(this), prev_(this), refs_(0),
152  file_to_compact_(NULL),
154  compaction_score_(-1),
155  compaction_level_(-1) {
156  }
Version * next_
Definition: version_set.h:133
Version * prev_
Definition: version_set.h:134
double compaction_score_
Definition: version_set.h:147
VersionSet * vset_
Definition: version_set.h:132
int file_to_compact_level_
Definition: version_set.h:142
FileMetaData * file_to_compact_
Definition: version_set.h:141

§ ~Version()

leveldb::Version::~Version ( )
private

Definition at line 66 of file version_set.cc.

66  {
67  assert(refs_ == 0);
68 
69  // Remove from linked list
70  prev_->next_ = next_;
71  next_->prev_ = prev_;
72 
73  // Drop references to files
74  for (int level = 0; level < config::kNumLevels; level++) {
75  for (size_t i = 0; i < files_[level].size(); i++) {
76  FileMetaData* f = files_[level][i];
77  assert(f->refs > 0);
78  f->refs--;
79  if (f->refs <= 0) {
80  delete f;
81  }
82  }
83  }
84 }
Version * next_
Definition: version_set.h:133
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
static const int kNumLevels
Definition: dbformat.h:22
Version * prev_
Definition: version_set.h:134

§ Version() [2/2]

leveldb::Version::Version ( const Version )
private

Member Function Documentation

§ AddIterators()

void leveldb::Version::AddIterators ( const ReadOptions options,
std::vector< Iterator *> *  iters 
)

Definition at line 234 of file version_set.cc.

235  {
236  // Merge all level zero files together since they may overlap
237  for (size_t i = 0; i < files_[0].size(); i++) {
238  iters->push_back(
240  options, files_[0][i]->number, files_[0][i]->file_size));
241  }
242 
243  // For levels > 0, we can use a concatenating iterator that sequentially
244  // walks through the non-overlapping files in the level, opening them
245  // lazily.
246  for (int level = 1; level < config::kNumLevels; level++) {
247  if (!files_[level].empty()) {
248  iters->push_back(NewConcatenatingIterator(options, level));
249  }
250  }
251 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
TableCache *const table_cache_
Definition: version_set.h:300
Iterator * NewConcatenatingIterator(const ReadOptions &, int level) const
Definition: version_set.cc:227
static const int kNumLevels
Definition: dbformat.h:22
VersionSet * vset_
Definition: version_set.h:132
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:

§ DebugString()

std::string leveldb::Version::DebugString ( ) const

Definition at line 574 of file version_set.cc.

574  {
575  std::string r;
576  for (int level = 0; level < config::kNumLevels; level++) {
577  // E.g.,
578  // --- level 1 ---
579  // 17:123['a' .. 'd']
580  // 20:43['e' .. 'g']
581  r.append("--- level ");
582  AppendNumberTo(&r, level);
583  r.append(" ---\n");
584  const std::vector<FileMetaData*>& files = files_[level];
585  for (size_t i = 0; i < files.size(); i++) {
586  r.push_back(' ');
587  AppendNumberTo(&r, files[i]->number);
588  r.push_back(':');
589  AppendNumberTo(&r, files[i]->file_size);
590  r.append("[");
591  r.append(files[i]->smallest.DebugString());
592  r.append(" .. ");
593  r.append(files[i]->largest.DebugString());
594  r.append("]\n");
595  }
596  }
597  return r;
598 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
static const int kNumLevels
Definition: dbformat.h:22
void AppendNumberTo(std::string *str, uint64_t num)
Definition: logging.cc:16
Here is the call graph for this function:
Here is the caller graph for this function:

§ ForEachOverlapping()

void leveldb::Version::ForEachOverlapping ( Slice  user_key,
Slice  internal_key,
void *  arg,
bool(*)(void *, int, FileMetaData *)  func 
)
private

Definition at line 287 of file version_set.cc.

289  {
290  // TODO(sanjay): Change Version::Get() to use this function.
291  const Comparator* ucmp = vset_->icmp_.user_comparator();
292 
293  // Search level-0 in order from newest to oldest.
294  std::vector<FileMetaData*> tmp;
295  tmp.reserve(files_[0].size());
296  for (uint32_t i = 0; i < files_[0].size(); i++) {
297  FileMetaData* f = files_[0][i];
298  if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 &&
299  ucmp->Compare(user_key, f->largest.user_key()) <= 0) {
300  tmp.push_back(f);
301  }
302  }
303  if (!tmp.empty()) {
304  std::sort(tmp.begin(), tmp.end(), NewestFirst);
305  for (uint32_t i = 0; i < tmp.size(); i++) {
306  if (!(*func)(arg, 0, tmp[i])) {
307  return;
308  }
309  }
310  }
311 
312  // Search other levels.
313  for (int level = 1; level < config::kNumLevels; level++) {
314  size_t num_files = files_[level].size();
315  if (num_files == 0) continue;
316 
317  // Binary search to find earliest index whose largest key >= internal_key.
318  uint32_t index = FindFile(vset_->icmp_, files_[level], internal_key);
319  if (index < num_files) {
320  FileMetaData* f = files_[level][index];
321  if (ucmp->Compare(user_key, f->smallest.user_key()) < 0) {
322  // All of "f" is past any data for user_key
323  } else {
324  if (!(*func)(arg, level, f)) {
325  return;
326  }
327  }
328  }
329  }
330 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
static const int kNumLevels
Definition: dbformat.h:22
int FindFile(const InternalKeyComparator &icmp, const std::vector< FileMetaData *> &files, const Slice &key)
Definition: version_set.cc:86
const Comparator * user_comparator() const
Definition: dbformat.h:125
VersionSet * vset_
Definition: version_set.h:132
const InternalKeyComparator icmp_
Definition: version_set.h:301
static bool NewestFirst(FileMetaData *a, FileMetaData *b)
Definition: version_set.cc:283
Here is the call graph for this function:
Here is the caller graph for this function:

§ Get()

Status leveldb::Version::Get ( const ReadOptions options,
const LookupKey key,
std::string *  val,
GetStats stats 
)

Definition at line 332 of file version_set.cc.

335  {
336  Slice ikey = k.internal_key();
337  Slice user_key = k.user_key();
338  const Comparator* ucmp = vset_->icmp_.user_comparator();
339  Status s;
340 
341  stats->seek_file = NULL;
342  stats->seek_file_level = -1;
343  FileMetaData* last_file_read = NULL;
344  int last_file_read_level = -1;
345 
346  // We can search level-by-level since entries never hop across
347  // levels. Therefore we are guaranteed that if we find data
348  // in an smaller level, later levels are irrelevant.
349  std::vector<FileMetaData*> tmp;
350  FileMetaData* tmp2;
351  for (int level = 0; level < config::kNumLevels; level++) {
352  size_t num_files = files_[level].size();
353  if (num_files == 0) continue;
354 
355  // Get the list of files to search in this level
356  FileMetaData* const* files = &files_[level][0];
357  if (level == 0) {
358  // Level-0 files may overlap each other. Find all files that
359  // overlap user_key and process them in order from newest to oldest.
360  tmp.reserve(num_files);
361  for (uint32_t i = 0; i < num_files; i++) {
362  FileMetaData* f = files[i];
363  if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 &&
364  ucmp->Compare(user_key, f->largest.user_key()) <= 0) {
365  tmp.push_back(f);
366  }
367  }
368  if (tmp.empty()) continue;
369 
370  std::sort(tmp.begin(), tmp.end(), NewestFirst);
371  files = &tmp[0];
372  num_files = tmp.size();
373  } else {
374  // Binary search to find earliest index whose largest key >= ikey.
375  uint32_t index = FindFile(vset_->icmp_, files_[level], ikey);
376  if (index >= num_files) {
377  files = NULL;
378  num_files = 0;
379  } else {
380  tmp2 = files[index];
381  if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) {
382  // All of "tmp2" is past any data for user_key
383  files = NULL;
384  num_files = 0;
385  } else {
386  files = &tmp2;
387  num_files = 1;
388  }
389  }
390  }
391 
392  for (uint32_t i = 0; i < num_files; ++i) {
393  if (last_file_read != NULL && stats->seek_file == NULL) {
394  // We have had more than one seek for this read. Charge the 1st file.
395  stats->seek_file = last_file_read;
396  stats->seek_file_level = last_file_read_level;
397  }
398 
399  FileMetaData* f = files[i];
400  last_file_read = f;
401  last_file_read_level = level;
402 
403  Saver saver;
404  saver.state = kNotFound;
405  saver.ucmp = ucmp;
406  saver.user_key = user_key;
407  saver.value = value;
408  s = vset_->table_cache_->Get(options, f->number, f->file_size,
409  ikey, &saver, SaveValue);
410  if (!s.ok()) {
411  return s;
412  }
413  switch (saver.state) {
414  case kNotFound:
415  break; // Keep searching in other files
416  case kFound:
417  return s;
418  case kDeleted:
419  s = Status::NotFound(Slice()); // Use empty error message for speed
420  return s;
421  case kCorrupt:
422  s = Status::Corruption("corrupted key for ", user_key);
423  return s;
424  }
425  }
426  }
427 
428  return Status::NotFound(Slice()); // Use an empty error message for speed
429 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
TableCache *const table_cache_
Definition: version_set.h:300
static Status NotFound(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:35
static const int kNumLevels
Definition: dbformat.h:22
int FindFile(const InternalKeyComparator &icmp, const std::vector< FileMetaData *> &files, const Slice &key)
Definition: version_set.cc:86
const Comparator * user_comparator() const
Definition: dbformat.h:125
VersionSet * vset_
Definition: version_set.h:132
static Status Corruption(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:38
const InternalKeyComparator icmp_
Definition: version_set.h:301
static bool NewestFirst(FileMetaData *a, FileMetaData *b)
Definition: version_set.cc:283
static void SaveValue(void *arg, const Slice &ikey, const Slice &v)
Definition: version_set.cc:268
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 &))
Definition: table_cache.cc:105
Here is the call graph for this function:
Here is the caller graph for this function:

§ GetOverlappingInputs()

void leveldb::Version::GetOverlappingInputs ( int  level,
const InternalKey begin,
const InternalKey end,
std::vector< FileMetaData *> *  inputs 
)

Definition at line 531 of file version_set.cc.

535  {
536  assert(level >= 0);
537  assert(level < config::kNumLevels);
538  inputs->clear();
539  Slice user_begin, user_end;
540  if (begin != NULL) {
541  user_begin = begin->user_key();
542  }
543  if (end != NULL) {
544  user_end = end->user_key();
545  }
546  const Comparator* user_cmp = vset_->icmp_.user_comparator();
547  for (size_t i = 0; i < files_[level].size(); ) {
548  FileMetaData* f = files_[level][i++];
549  const Slice file_start = f->smallest.user_key();
550  const Slice file_limit = f->largest.user_key();
551  if (begin != NULL && user_cmp->Compare(file_limit, user_begin) < 0) {
552  // "f" is completely before specified range; skip it
553  } else if (end != NULL && user_cmp->Compare(file_start, user_end) > 0) {
554  // "f" is completely after specified range; skip it
555  } else {
556  inputs->push_back(f);
557  if (level == 0) {
558  // Level-0 files may overlap each other. So check if the newly
559  // added file has expanded the range. If so, restart search.
560  if (begin != NULL && user_cmp->Compare(file_start, user_begin) < 0) {
561  user_begin = file_start;
562  inputs->clear();
563  i = 0;
564  } else if (end != NULL && user_cmp->Compare(file_limit, user_end) > 0) {
565  user_end = file_limit;
566  inputs->clear();
567  i = 0;
568  }
569  }
570  }
571  }
572 }
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
VersionSet * vset_
Definition: version_set.h:132
const InternalKeyComparator icmp_
Definition: version_set.h:301
Here is the call graph for this function:
Here is the caller graph for this function:

§ NewConcatenatingIterator()

Iterator * leveldb::Version::NewConcatenatingIterator ( const ReadOptions options,
int  level 
) const
private

Definition at line 227 of file version_set.cc.

228  {
229  return NewTwoLevelIterator(
230  new LevelFileNumIterator(vset_->icmp_, &files_[level]),
231  &GetFileIterator, vset_->table_cache_, options);
232 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
TableCache *const table_cache_
Definition: version_set.h:300
VersionSet * vset_
Definition: version_set.h:132
const InternalKeyComparator icmp_
Definition: version_set.h:301
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
Here is the call graph for this function:
Here is the caller graph for this function:

§ NumFiles()

int leveldb::Version::NumFiles ( int  level) const
inline

Definition at line 111 of file version_set.h.

111 { return files_[level].size(); }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138

§ operator=()

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

§ OverlapInLevel()

bool leveldb::Version::OverlapInLevel ( int  level,
const Slice smallest_user_key,
const Slice largest_user_key 
)

Definition at line 495 of file version_set.cc.

497  {
498  return SomeFileOverlapsRange(vset_->icmp_, (level > 0), files_[level],
499  smallest_user_key, largest_user_key);
500 }
std::vector< FileMetaData * > files_[config::kNumLevels]
Definition: version_set.h:138
VersionSet * vset_
Definition: version_set.h:132
bool SomeFileOverlapsRange(const InternalKeyComparator &icmp, bool disjoint_sorted_files, const std::vector< FileMetaData *> &files, const Slice *smallest_user_key, const Slice *largest_user_key)
Definition: version_set.cc:121
const InternalKeyComparator icmp_
Definition: version_set.h:301
Here is the call graph for this function:
Here is the caller graph for this function:

§ PickLevelForMemTableOutput()

int leveldb::Version::PickLevelForMemTableOutput ( const Slice smallest_user_key,
const Slice largest_user_key 
)

Definition at line 502 of file version_set.cc.

504  {
505  int level = 0;
506  if (!OverlapInLevel(0, &smallest_user_key, &largest_user_key)) {
507  // Push to next level if there is no overlap in next level,
508  // and the #bytes overlapping in the level after that are limited.
509  InternalKey start(smallest_user_key, kMaxSequenceNumber, kValueTypeForSeek);
510  InternalKey limit(largest_user_key, 0, static_cast<ValueType>(0));
511  std::vector<FileMetaData*> overlaps;
512  while (level < config::kMaxMemCompactLevel) {
513  if (OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) {
514  break;
515  }
516  if (level + 2 < config::kNumLevels) {
517  // Check that file does not overlap too many grandparent bytes.
518  GetOverlappingInputs(level + 2, &start, &limit, &overlaps);
519  const int64_t sum = TotalFileSize(overlaps);
521  break;
522  }
523  }
524  level++;
525  }
526  }
527  return level;
528 }
static const SequenceNumber kMaxSequenceNumber
Definition: dbformat.h:67
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
VersionSet * vset_
Definition: version_set.h:132
bool OverlapInLevel(int level, const Slice *smallest_user_key, const Slice *largest_user_key)
Definition: version_set.cc:495
static const ValueType kValueTypeForSeek
Definition: dbformat.h:61
static const int kMaxMemCompactLevel
Definition: dbformat.h:39
static int64_t MaxGrandParentOverlapBytes(const Options *options)
Definition: version_set.cc:29
static int64_t TotalFileSize(const std::vector< FileMetaData *> &files)
Definition: version_set.cc:58
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:

§ RecordReadSample()

bool leveldb::Version::RecordReadSample ( Slice  key)

Definition at line 444 of file version_set.cc.

444  {
445  ParsedInternalKey ikey;
446  if (!ParseInternalKey(internal_key, &ikey)) {
447  return false;
448  }
449 
450  struct State {
451  GetStats stats; // Holds first matching file
452  int matches;
453 
454  static bool Match(void* arg, int level, FileMetaData* f) {
455  State* state = reinterpret_cast<State*>(arg);
456  state->matches++;
457  if (state->matches == 1) {
458  // Remember first match.
459  state->stats.seek_file = f;
460  state->stats.seek_file_level = level;
461  }
462  // We can stop iterating once we have a second match.
463  return state->matches < 2;
464  }
465  };
466 
467  State state;
468  state.matches = 0;
469  ForEachOverlapping(ikey.user_key, internal_key, &state, &State::Match);
470 
471  // Must have at least two matches since we want to merge across
472  // files. But what if we have a single file that contains many
473  // overwrites and deletions? Should we have another mechanism for
474  // finding such files?
475  if (state.matches >= 2) {
476  // 1MB cost is about 1 seek (see comment in Builder::Apply).
477  return UpdateStats(state.stats);
478  }
479  return false;
480 }
bool UpdateStats(const GetStats &stats)
Definition: version_set.cc:431
bool ParseInternalKey(const Slice &internal_key, ParsedInternalKey *result)
Definition: dbformat.h:176
void ForEachOverlapping(Slice user_key, Slice internal_key, void *arg, bool(*func)(void *, int, FileMetaData *))
Definition: version_set.cc:287
Here is the call graph for this function:
Here is the caller graph for this function:

§ Ref()

void leveldb::Version::Ref ( )

Definition at line 482 of file version_set.cc.

482  {
483  ++refs_;
484 }
Here is the caller graph for this function:

§ Unref()

void leveldb::Version::Unref ( )

Definition at line 486 of file version_set.cc.

486  {
487  assert(this != &vset_->dummy_versions_);
488  assert(refs_ >= 1);
489  --refs_;
490  if (refs_ == 0) {
491  delete this;
492  }
493 }
VersionSet * vset_
Definition: version_set.h:132
Here is the caller graph for this function:

§ UpdateStats()

bool leveldb::Version::UpdateStats ( const GetStats stats)

Definition at line 431 of file version_set.cc.

431  {
432  FileMetaData* f = stats.seek_file;
433  if (f != NULL) {
434  f->allowed_seeks--;
435  if (f->allowed_seeks <= 0 && file_to_compact_ == NULL) {
436  file_to_compact_ = f;
437  file_to_compact_level_ = stats.seek_file_level;
438  return true;
439  }
440  }
441  return false;
442 }
int file_to_compact_level_
Definition: version_set.h:142
FileMetaData * file_to_compact_
Definition: version_set.h:141
Here is the caller graph for this function:

Friends And Related Function Documentation

§ Compaction

friend class Compaction
friend

Definition at line 117 of file version_set.h.

§ VersionSet

friend class VersionSet
friend

Definition at line 118 of file version_set.h.

Member Data Documentation

§ compaction_level_

int leveldb::Version::compaction_level_
private

Definition at line 148 of file version_set.h.

§ compaction_score_

double leveldb::Version::compaction_score_
private

Definition at line 147 of file version_set.h.

§ file_to_compact_

FileMetaData* leveldb::Version::file_to_compact_
private

Definition at line 141 of file version_set.h.

§ file_to_compact_level_

int leveldb::Version::file_to_compact_level_
private

Definition at line 142 of file version_set.h.

§ files_

std::vector<FileMetaData*> leveldb::Version::files_[config::kNumLevels]
private

Definition at line 138 of file version_set.h.

§ next_

Version* leveldb::Version::next_
private

Definition at line 133 of file version_set.h.

§ prev_

Version* leveldb::Version::prev_
private

Definition at line 134 of file version_set.h.

§ refs_

int leveldb::Version::refs_
private

Definition at line 135 of file version_set.h.

§ vset_

VersionSet* leveldb::Version::vset_
private

Definition at line 132 of file version_set.h.


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