| 1109 | } |
| 1110 | |
| 1111 | Status DBImpl::Get(const ReadOptions& options, const Slice& key, |
| 1112 | std::string* value) { |
| 1113 | Status s; |
| 1114 | MutexLock l(&mutex_); |
| 1115 | SequenceNumber snapshot; |
| 1116 | if (options.snapshot != nullptr) { |
| 1117 | snapshot = |
| 1118 | static_cast<const SnapshotImpl*>(options.snapshot)->sequence_number(); |
| 1119 | } else { |
| 1120 | snapshot = versions_->LastSequence(); |
| 1121 | } |
| 1122 | |
| 1123 | MemTable* mem = mem_; |
| 1124 | MemTable* imm = imm_; |
| 1125 | Version* current = versions_->current(); |
| 1126 | mem->Ref(); |
| 1127 | if (imm != nullptr) imm->Ref(); |
| 1128 | current->Ref(); |
| 1129 | |
| 1130 | bool have_stat_update = false; |
| 1131 | Version::GetStats stats; |
| 1132 | |
| 1133 | // Unlock while reading from files and memtables |
| 1134 | { |
| 1135 | mutex_.Unlock(); |
| 1136 | // First look in the memtable, then in the immutable memtable (if any). |
| 1137 | LookupKey lkey(key, snapshot); |
| 1138 | if (mem->Get(lkey, value, &s)) { |
| 1139 | // Done |
| 1140 | } else if (imm != nullptr && imm->Get(lkey, value, &s)) { |
| 1141 | // Done |
| 1142 | } else { |
| 1143 | s = current->Get(options, lkey, value, &stats); |
| 1144 | have_stat_update = true; |
| 1145 | } |
| 1146 | mutex_.Lock(); |
| 1147 | } |
| 1148 | |
| 1149 | if (have_stat_update && current->UpdateStats(stats)) { |
| 1150 | MaybeScheduleCompaction(); |
| 1151 | } |
| 1152 | mem->Unref(); |
| 1153 | if (imm != nullptr) imm->Unref(); |
| 1154 | current->Unref(); |
| 1155 | return s; |
| 1156 | } |
| 1157 | |
| 1158 | Iterator* DBImpl::NewIterator(const ReadOptions& options) { |
| 1159 | SequenceNumber latest_snapshot; |