以下是levldbd的Get()函数 ,给出该函数的调用关系图以文本的方式并解释下具体是怎么调用每个函数的Status DBImpl::Get(const ReadOptions& options, const Slice& key, std::string* value) { Status s; MutexLock l(&mutex_); SequenceNumber snapshot; if (options.snapshot != nullptr) { snapshot = static_cast<const SnapshotImpl*>(options.snapshot)->sequence_number(); } else { snapshot = versions_->LastSequence(); } MemTable* mem = mem_; MemTable* imm = imm_; Version* current = versions_->current(); mem->Ref(); if (imm != nullptr) imm->Ref(); current->Ref(); bool have_stat_update = false; Version::GetStats stats; // Unlock while reading from files and memtables { mutex_.Unlock(); // First look in the memtable, then in the immutable memtable (if any). LookupKey lkey(key, snapshot); if (mem->Get(lkey, value, &s)) { // Done } else if (imm != nullptr && imm->Get(lkey, value, &s)) { // Done } else { s = current->Get(options, lkey, value, &stats); have_stat_update = true; } mutex_.Lock(); } if (have_stat_update && current->UpdateStats(stats)) { MaybeScheduleCompaction(); } mem->Unref(); if (imm != nullptr) imm->Unref(); current->Unref(); return s; }
时间: 2024-02-23 11:58:25 浏览: 65
getJSON调用后台json数据时函数被调用两次的原因猜想
以下是 `DBImpl::Get` 函数的调用关系图,每个函数的调用方式和作用在注释中有说明:
```
DBImpl::Get(const ReadOptions& options, const Slice& key, std::string* value) {
Status s;
MutexLock l(&mutex_);
SequenceNumber snapshot;
if (options.snapshot != nullptr) {
snapshot = static_cast<const SnapshotImpl*>(options.snapshot)->sequence_number();
} else {
snapshot = versions_->LastSequence();
}
MemTable* mem = mem_;
MemTable* imm = imm_;
Version* current = versions_->current();
mem->Ref();
if (imm != nullptr) {
imm->Ref();
}
current->Ref();
bool have_stat_update = false;
Version::GetStats stats;
// Unlock while reading from files and memtables
{
mutex_.Unlock();
LookupKey lkey(key, snapshot);
if (mem->Get(lkey, value, &s)) { // 在 memtable 中查找 key
// Done
} else if (imm != nullptr && imm->Get(lkey, value, &s)) { // 在 immutable memtable 中查找 key
// Done
} else {
// 在 version 中查找 key
s = current->Get(options, lkey, value, &stats);
have_stat_update = true;
}
mutex_.Lock();
}
if (have_stat_update && current->UpdateStats(stats)) {
MaybeScheduleCompaction(); // 更新 version 的统计信息,如果需要,则进行压缩操作
}
mem->Unref();
if (imm != nullptr) {
imm->Unref();
}
current->Unref();
return s; // 返回查找结果
}
```
在 `DBImpl::Get` 函数中,首先通过 `options` 参数中传入的快照获取当前 `snapshot`,然后分别获取当前的 `memtable`、`imm` 和 `version` 对象,并对其进行引用计数。接着使用 `LookupKey` 类构造一个 `lkey`,然后依次在 `memtable` 和 `imm` 中查找 `lkey`,如果找到则直接返回结果,否则需要在 `version` 中查找。在查找过程中,为了避免锁的粒度过大,需要先解锁再进行查找操作,最后再加锁。
如果在 `version` 中查找成功,则需要更新 `version` 的统计信息,并根据需要进行压缩操作。最后对 `memtable`、`imm` 和 `version` 进行引用计数的减少,并返回查找结果。
阅读全文