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.
1751fprintf(stderr, "iter %d; errors %d\n", i, errors);1752if (!Put("foo", big).ok()) {1753errors++;1754DelayMilliseconds(100);1755}1756}1757ASSERT_GT(errors, 0);1758env_->non_writable_.store(false, std::memory_order_release);1759}1761TEST(DBTest, WriteSyncError) {1762// Check that log sync errors cause the DB to disallow future writes.1764// (a) Cause log sync calls to fail1765Options options = CurrentOptions();1766options.env = env_;1767Reopen(&options);1768env_->data_sync_error_.store(true, std::memory_order_release);1770// (b) Normal write should succeed1771WriteOptions w;1772ASSERT_OK(db_->Put(w, "k1", "v1"));1773ASSERT_EQ("v1", Get("k1"));1775// (c) Do a sync write; should fail1776w.sync = true;1777ASSERT_TRUE(!db_->Put(w, "k2", "v2").ok());1778ASSERT_EQ("v1", Get("k1"));1779ASSERT_EQ("NOT_FOUND", Get("k2"));1781// (d) make sync behave normally1782env_->data_sync_error_.store(false, std::memory_order_release);1784// (e) Do a non-sync write; should fail1785w.sync = false;1786ASSERT_TRUE(!db_->Put(w, "k3", "v3").ok());1787ASSERT_EQ("v1", Get("k1"));1788ASSERT_EQ("NOT_FOUND", Get("k2"));1789ASSERT_EQ("NOT_FOUND", Get("k3"));1790}1792TEST(DBTest, ManifestWriteError) {1793// Test for the following problem:1794// (a) Compaction produces file F1795// (b) Log record containing F is written to MANIFEST file, but Sync() fails1796// (c) GC deletes F1797// (d) After reopening DB, reads fail since deleted F is named in log record1799// We iterate twice. In the second iteration, everything is the1800// same except the log record never makes it to the MANIFEST file.1801for (int iter = 0; iter < 2; iter++) {1802std::atomic<bool>* error_type = (iter == 0) ? &env_->manifest_sync_error_1803: &env_->manifest_write_error_;1805// Insert foo=>bar mapping1806Options options = CurrentOptions();1807options.env = env_;1808options.create_if_missing = true;1809options.error_if_exists = false;1810DestroyAndReopen(&options);1811ASSERT_OK(Put("foo", "bar"));1812ASSERT_EQ("bar", Get("foo"));1814// Memtable compaction (will succeed)1815dbfull()->TEST_CompactMemTable();1816ASSERT_EQ("bar", Get("foo"));1817const int last = config::kMaxMemCompactLevel;1818ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo=>bar is now in last level1820// Merging compaction (will fail)1821error_type->store(true, std::memory_order_release);1822dbfull()->TEST_CompactRange(last, nullptr, nullptr); // Should fail1823ASSERT_EQ("bar", Get("foo"));1825// Recovery: should not lose data1826error_type->store(false, std::memory_order_release);1827Reopen(&options);1828ASSERT_EQ("bar", Get("foo"));1829}1830}1832TEST(DBTest, MissingSSTFile) {1833ASSERT_OK(Put("foo", "bar"));1834ASSERT_EQ("bar", Get("foo"));1836// Dump the memtable to disk.1837dbfull()->TEST_CompactMemTable();1838ASSERT_EQ("bar", Get("foo"));1840Close();1841ASSERT_TRUE(DeleteAnSSTFile());1842Options options = CurrentOptions();1843options.paranoid_checks = true;1844Status s = TryReopen(&options);1845ASSERT_TRUE(!s.ok());1846ASSERT_TRUE(s.ToString().find("issing") != std::string::npos) << s.ToString();1847}1849TEST(DBTest, StillReadSST) {1850ASSERT_OK(Put("foo", "bar"));1851ASSERT_EQ("bar", Get("foo"));1853// Dump the memtable to disk.1854dbfull()->TEST_CompactMemTable();1855ASSERT_EQ("bar", Get("foo"));1856Close();1857ASSERT_GT(RenameLDBToSST(), 0);1858Options options = CurrentOptions();1859options.paranoid_checks = true;1860Status s = TryReopen(&options);1861ASSERT_TRUE(s.ok());1862ASSERT_EQ("bar", Get("foo"));1863}1865TEST(DBTest, FilesDeletedAfterCompaction) {1866ASSERT_OK(Put("foo", "v2"));1867Compact("a", "z");1868const int num_files = CountFiles();1869for (int i = 0; i < 10; i++) {1870ASSERT_OK(Put("foo", "v2"));1871Compact("a", "z");1872}1873ASSERT_EQ(CountFiles(), num_files);1874}1876TEST(DBTest, BloomFilter) {1877env_->count_random_reads_ = true;1878Options options = CurrentOptions();1879options.env = env_;1880options.block_cache = NewLRUCache(0); // Prevent cache hits1881options.filter_policy = NewBloomFilterPolicy(10);1882Reopen(&options);1884// Populate multiple layers1885const int N = 10000;1886for (int i = 0; i < N; i++) {1887ASSERT_OK(Put(Key(i), Key(i)));1888}1889Compact("a", "z");1890for (int i = 0; i < N; i += 100) {1891ASSERT_OK(Put(Key(i), Key(i)));1892}1893dbfull()->TEST_CompactMemTable();1895// Prevent auto compactions triggered by seeks1896env_->delay_data_sync_.store(true, std::memory_order_release);1898// Lookup present keys. Should rarely read from small sstable.1899env_->random_read_counter_.Reset();1900for (int i = 0; i < N; i++) {1901ASSERT_EQ(Key(i), Get(Key(i)));1902}1903int reads = env_->random_read_counter_.Read();1904fprintf(stderr, "%d present => %d reads\n", N, reads);1905ASSERT_GE(reads, N);1906ASSERT_LE(reads, N + 2 * N / 100);1908// Lookup present keys. Should rarely read from either sstable.1909env_->random_read_counter_.Reset();1910for (int i = 0; i < N; i++) {1911ASSERT_EQ("NOT_FOUND", Get(Key(i) + ".missing"));1912}1913reads = env_->random_read_counter_.Read();1914fprintf(stderr, "%d missing => %d reads\n", N, reads);1915ASSERT_LE(reads, 3 * N / 100);1917env_->delay_data_sync_.store(false, std::memory_order_release);1918Close();1919delete options.block_cache;1920delete options.filter_policy;1921}1923// Multi-threaded test:1924namespace {1926static const int kNumThreads = 4;1927static const int kTestSeconds = 10;1928static const int kNumKeys = 1000;1930struct MTState {1931DBTest* test;1932std::atomic<bool> stop;1933std::atomic<int> counter[kNumThreads];1934std::atomic<bool> thread_done[kNumThreads];1935};1937struct MTThread {1938MTState* state;1939int id;1940};1942static void MTThreadBody(void* arg) {1943MTThread* t = reinterpret_cast<MTThread*>(arg);1944int id = t->id;1945DB* db = t->state->test->db_;1946int counter = 0;1947fprintf(stderr, "... starting thread %d\n", id);1948Random rnd(1000 + id);1949std::string value;1950char valbuf[1500];1951while (!t->state->stop.load(std::memory_order_acquire)) {1952t->state->counter[id].store(counter, std::memory_order_release);1954int key = rnd.Uniform(kNumKeys);1955char keybuf[20];1956snprintf(keybuf, sizeof(keybuf), "%016d", key);1958if (rnd.OneIn(2)) {1959// Write values of the form <key, my id, counter>.1960// We add some padding for force compactions.1961snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d", key, id,1962static_cast<int>(counter));1963ASSERT_OK(db->Put(WriteOptions(), Slice(keybuf), Slice(valbuf)));1964} else {1965// Read a value and verify that it matches the pattern written above.1966Status s = db->Get(ReadOptions(), Slice(keybuf), &value);1967if (s.IsNotFound()) {1968// Key has not yet been written1969} else {1970// Check that the writer thread counter is >= the counter in the value1971ASSERT_OK(s);1972int k, w, c;1973ASSERT_EQ(3, sscanf(value.c_str(), "%d.%d.%d", &k, &w, &c)) << value;1974ASSERT_EQ(k, key);1975ASSERT_GE(w, 0);1976ASSERT_LT(w, kNumThreads);1977ASSERT_LE(c, t->state->counter[w].load(std::memory_order_acquire));1978}1979}1980counter++;1981}1982t->state->thread_done[id].store(true, std::memory_order_release);1983fprintf(stderr, "... stopping thread %d after %d ops\n", id, counter);1984}1986} // namespace1988TEST(DBTest, MultiThreaded) {1989do {1990// Initialize state1991MTState mt;1992mt.test = this;1993mt.stop.store(false, std::memory_order_release);1994for (int id = 0; id < kNumThreads; id++) {1995mt.counter[id].store(false, std::memory_order_release);1996mt.thread_done[id].store(false, std::memory_order_release);1997}1999// Start threads2000MTThread thread[kNumThreads];
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.