Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251delete env_;252delete filter_policy_;253}255// Switch to a fresh database with the next option configuration to256// test. Return false if there are no more configurations to test.257bool ChangeOptions() {258option_config_++;259if (option_config_ >= kEnd) {260return false;261} else {262DestroyAndReopen();263return true;264}265}267// Return the current option configuration.268Options CurrentOptions() {269Options options;270options.reuse_logs = false;271switch (option_config_) {272case kReuse:273options.reuse_logs = true;274break;275case kFilter:276options.filter_policy = filter_policy_;277break;278case kUncompressed:279options.compression = kNoCompression;280break;281default:282break;283}284return options;285}287DBImpl* dbfull() { return reinterpret_cast<DBImpl*>(db_); }289void Reopen(Options* options = nullptr) { ASSERT_OK(TryReopen(options)); }291void Close() {292delete db_;293db_ = nullptr;294}296void DestroyAndReopen(Options* options = nullptr) {297delete db_;298db_ = nullptr;299DestroyDB(dbname_, Options());300ASSERT_OK(TryReopen(options));301}303Status TryReopen(Options* options) {304delete db_;305db_ = nullptr;306Options opts;307if (options != nullptr) {308opts = *options;309} else {310opts = CurrentOptions();311opts.create_if_missing = true;312}313last_options_ = opts;315return DB::Open(opts, dbname_, &db_);316}318Status Put(const std::string& k, const std::string& v) {319return db_->Put(WriteOptions(), k, v);320}322Status Delete(const std::string& k) { return db_->Delete(WriteOptions(), k); }324std::string Get(const std::string& k, const Snapshot* snapshot = nullptr) {325ReadOptions options;326options.snapshot = snapshot;327std::string result;328Status s = db_->Get(options, k, &result);329if (s.IsNotFound()) {330result = "NOT_FOUND";331} else if (!s.ok()) {332result = s.ToString();333}334return result;335}337// Return a string that contains all key,value pairs in order,338// formatted like "(k1->v1)(k2->v2)".339std::string Contents() {340std::vector<std::string> forward;341std::string result;342Iterator* iter = db_->NewIterator(ReadOptions());343for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {344std::string s = IterStatus(iter);345result.push_back('(');346result.append(s);347result.push_back(')');348forward.push_back(s);349}351// Check reverse iteration results are the reverse of forward results352size_t matched = 0;353for (iter->SeekToLast(); iter->Valid(); iter->Prev()) {354ASSERT_LT(matched, forward.size());355ASSERT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]);356matched++;357}358ASSERT_EQ(matched, forward.size());360delete iter;361return result;362}364std::string AllEntriesFor(const Slice& user_key) {365Iterator* iter = dbfull()->TEST_NewInternalIterator();366InternalKey target(user_key, kMaxSequenceNumber, kTypeValue);367iter->Seek(target.Encode());368std::string result;369if (!iter->status().ok()) {370result = iter->status().ToString();371} else {372result = "[ ";373bool first = true;374while (iter->Valid()) {375ParsedInternalKey ikey;376if (!ParseInternalKey(iter->key(), &ikey)) {377result += "CORRUPTED";378} else {379if (last_options_.comparator->Compare(ikey.user_key, user_key) != 0) {380break;381}382if (!first) {383result += ", ";384}385first = false;386switch (ikey.type) {387case kTypeValue:388result += iter->value().ToString();389break;390case kTypeDeletion:391result += "DEL";392break;393}394}395iter->Next();396}397if (!first) {398result += " ";399}400result += "]";401}402delete iter;403return result;404}406int NumTableFilesAtLevel(int level) {407std::string property;408ASSERT_TRUE(db_->GetProperty(409"leveldb.num-files-at-level" + NumberToString(level), &property));410return std::stoi(property);411}413int TotalTableFiles() {414int result = 0;415for (int level = 0; level < config::kNumLevels; level++) {416result += NumTableFilesAtLevel(level);417}418return result;419}421// Return spread of files per level422std::string FilesPerLevel() {423std::string result;424int last_non_zero_offset = 0;425for (int level = 0; level < config::kNumLevels; level++) {426int f = NumTableFilesAtLevel(level);427char buf[100];428snprintf(buf, sizeof(buf), "%s%d", (level ? "," : ""), f);429result += buf;430if (f > 0) {431last_non_zero_offset = result.size();432}433}434result.resize(last_non_zero_offset);435return result;436}438int CountFiles() {439std::vector<std::string> files;440env_->GetChildren(dbname_, &files);441return static_cast<int>(files.size());442}444uint64_t Size(const Slice& start, const Slice& limit) {445Range r(start, limit);446uint64_t size;447db_->GetApproximateSizes(&r, 1, &size);448return size;449}451void Compact(const Slice& start, const Slice& limit) {452db_->CompactRange(&start, &limit);453}455// Do n memtable compactions, each of which produces an sstable456// covering the range [small_key,large_key].457void MakeTables(int n, const std::string& small_key,458const std::string& large_key) {459for (int i = 0; i < n; i++) {460Put(small_key, "begin");461Put(large_key, "end");462dbfull()->TEST_CompactMemTable();463}464}466// Prevent pushing of new sstables into deeper levels by adding467// tables that cover a specified range to all levels.468void FillLevels(const std::string& smallest, const std::string& largest) {469MakeTables(config::kNumLevels, smallest, largest);470}472void DumpFileCounts(const char* label) {473fprintf(stderr, "---\n%s:\n", label);474fprintf(475stderr, "maxoverlap: %lld\n",476static_cast<long long>(dbfull()->TEST_MaxNextLevelOverlappingBytes()));477for (int level = 0; level < config::kNumLevels; level++) {478int num = NumTableFilesAtLevel(level);479if (num > 0) {480fprintf(stderr, " level %3d : %d files\n", level, num);481}482}483}485std::string DumpSSTableList() {486std::string property;487db_->GetProperty("leveldb.sstables", &property);488return property;489}491std::string IterStatus(Iterator* iter) {492std::string result;493if (iter->Valid()) {494result = iter->key().ToString() + "->" + iter->value().ToString();495} else {496result = "(invalid)";497}498return result;499}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.