diff -uNr a/bitcoin/manifest b/bitcoin/manifest --- a/bitcoin/manifest 8c2efd9aaefd27e6ced1feb4f81b6172cdab9f0bd2fd842671e338bb4e59fab63f11ce730a70a61538de3957eb66942caaca04fa633c8e78b826eb8ceeeed78b +++ b/bitcoin/manifest 56a9b8f0ce2813c45638e4ca9fedd14083bbb8f3ad43cc99fb283702fe0a6ffd84692f194f91192f7bec9781e8158f26ceeb57b1f0717c27d32a814c97d806a1 @@ -52,3 +52,4 @@ 735838 bitcoin_rebranding jfw Change version string to jwrd.net; apparently even something this simple can't be done without bumping into shoddy earlier work. 833338 bitcoin_reorg_tracing jfw Add more useful log messages for tracking reorganize progress (as well as initial block connection). 833339 bitcoin_db_shutdown_checkpoint_calming jfw Remove various frantic, overdone database-related activities, mostly in the shutdown path where they were doing more harm than good. The goal is to make shutdown fast and somewhat easier to analyze. Checkpointing comes up because it's no longer necessarily done at shutdown. The conditions for periodic checkpoints are simplified; in particular, it's no longer done ~every time a db handle object goes out of scope. Given the use of DB_TXN_WRITE_NOSYNC this means update durability with respect to system crash is somewhat relaxed, but this seems fine given the nature of the application. The size limit on db transaction log files is raised 10x, restoring its earlier value. +835694 bitcoin_drop_bdb_locking jfw Turn off BDB's page-level locking subsystem, with some tweaks to firm up the already largely single-threaded pattern of database use. This allows removing the magic-number limits on locks, lockers and lock objects; the numbers were reported by past authority to be sufficient for any 1MB block, but have proven insufficient for large reorganizations, because BDB accumulates locks for the duration of a transaction. It also saves nearly 2GB of preallocations in the database environment (__db.00[1-5] files) to support the large limits. diff -uNr a/bitcoin/src/bitcoinrpc.cpp b/bitcoin/src/bitcoinrpc.cpp --- a/bitcoin/src/bitcoinrpc.cpp 75044b931d61cddd9f751edc71844e87fe3a1f1343e45a6d44b417f32258740690a5297033cfa6789954607f639141101d117bbf7a91ce1f900d29f9d9212fc7 +++ b/bitcoin/src/bitcoinrpc.cpp 24c9b92b9c80d0b2e8a9d9767e609cf73d26a7b8dd7811b8bf0b9bc6ccb3e127f4eb2cebd2c60397359ac3db1e1e21d170cbc48a8f91f1f777b7026dfcd21483 @@ -269,7 +269,10 @@ fGenerate = false; } - GenerateBitcoins(fGenerate, pwalletMain); + // Moving these here out of GenerateBitcoins removes an unnecessary coupling between wallet and miner code. Really we ought to get rid of all these wallet-based "settings" in favor of bitcoin.conf / CLI options but so far not all have an equivalent. + WriteSetting("fGenerateBitcoins", fGenerate); + fGenerateBitcoins = fGenerate; + GenerateBitcoins(pwalletMain); return Value::null; } @@ -1391,12 +1394,6 @@ return Value::null; } - -void ThreadTopUpKeyPool(void* parg) -{ - pwalletMain->TopUpKeyPool(); -} - void ThreadCleanWalletPassphrase(void* parg) { int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000; @@ -1467,7 +1464,9 @@ "walletpassphrase \n" "Stores the wallet decryption key in memory for seconds."); - CreateThread(ThreadTopUpKeyPool, NULL); + // This was previously done by spinning up a temporary thread just for the purpose, perhaps to avoid adding latency to the RPC response; but since that thread would now need to grab cs_main (because of using CWalletDB), it would block things out anyway, so there doesn't seem to be much point. That is, walletpassphrase may now be delayed for new key generation just as getnewaddress and keypoolrefill already were. + pwalletMain->TopUpKeyPool(); + int64* pnSleepTime = new int64(params[1].get_int64()); CreateThread(ThreadCleanWalletPassphrase, pnSleepTime); @@ -1850,8 +1849,7 @@ key.SetSecret(secret); CBitcoinAddress vchAddress = CBitcoinAddress(key.GetPubKey()); - CRITICAL_BLOCK(cs_main) - CRITICAL_BLOCK(pwalletMain->cs_wallet) + // Removed redundant locks here on cs_main and pwalletMain->cs_wallet, from mod6_privkey_tools.vpatch ; all RPCs are already run with those locks, and it's not like there's any discipline to it or anything else is fine-grained. { pwalletMain->MarkDirty(); pwalletMain->SetAddressBookName(vchAddress, strLabel); diff -uNr a/bitcoin/src/db.cpp b/bitcoin/src/db.cpp --- a/bitcoin/src/db.cpp 8184aa47fc758c7c623aa3132fefecbe880b17a158dfeea205fee801aec3d32a0379310efebd75fe0faf6ba17c093ef7c9454376fe3c03e1e12081f3f6fc3c97 +++ b/bitcoin/src/db.cpp 140376fc982ad4ecee0b57873be88938a14b77352d558ff9e611e625f6eeb993c8d51a8df5c801a3df8b29ce2b87ec24f0cfab6b97493157cb1a6a7589b4b208 @@ -36,6 +36,8 @@ if (!fDbEnvInit) return; + // not obvious if we've otherwise fully excluded concurrent db operations (maybe this runs in the main thread as it exits but others are still running) + SCOPED_LOCK(cs_main); fDbEnvInit = false; try { @@ -89,16 +91,12 @@ dbenv.set_lg_dir(strLogDir.c_str()); // Reverting the reduction in log file size limit from 10MB to 1MB in bitcoin-v0_5_3-db_config.6.vpatch ; that seems to have been an early unsuccessful experiment in avoiding lock resource limits. dbenv.set_lg_max(10*1000*1000); - dbenv.set_lk_max_locks(2737000); - dbenv.set_lk_max_objects(1119200); - dbenv.set_lk_max_lockers(1119200); dbenv.set_errfile(fopen(strErrorFile.c_str(), "a")); /// debug dbenv.set_flags(DB_AUTO_COMMIT, 1); dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1); dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); ret = dbenv.open(strDataDir.c_str(), DB_CREATE | - DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | @@ -1001,6 +999,7 @@ nLastWalletUpdate = GetTime(); } + SCOPED_LOCK(cs_main); // Now excluding concurrent database operations altogether because BDB's locking is unworkable. if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2) { TRY_CRITICAL_BLOCK(cs_db) diff -uNr a/bitcoin/src/init.cpp b/bitcoin/src/init.cpp --- a/bitcoin/src/init.cpp 495622f455f896aac3529ff002d7eb85b60cf56dd49a732de67eaeb48f59fa61ff721609221a9cec6b4ccf9c4e5794b9580405245d2c622f6e9161d4133e3bce +++ b/bitcoin/src/init.cpp 3b26dcbfbf59ff4bacbb62b11d0f1acad77a94d66fcf37a30703257b0e00511b7c63942bbe09056fe811af6539ec9ea97d71c4e2577a82cdc40b0f5abb2693d1 @@ -40,7 +40,11 @@ fShutdown = true; nTransactionsUpdated++; StopNode(); - DBFlush(); + { + // not obvious if we've otherwise fully excluded concurrent db operations (StopNode doesn't necessarily stop all threads) + SCOPED_LOCK(cs_main); + DBFlush(); + } boost::filesystem::remove(GetPidFile()); UnregisterWallet(pwalletMain); delete pwalletMain; diff -uNr a/bitcoin/src/main.cpp b/bitcoin/src/main.cpp --- a/bitcoin/src/main.cpp 037744e5a27978ab9e5a828e03e12a9209a7907465f2374aacf64e591fa9c85727651968d6667cdadd202c29f377baaa68ea635b1b43182a570adab5d71318de +++ b/bitcoin/src/main.cpp e55bbe5755159c32d355c180a750d942058656a78f4eddbc3feb8ed3ba0fc8ccf35269ffd3d71f43e8fdae287ecfd300456e6a943caa674a67e237663ebf7b83 @@ -233,15 +233,6 @@ return ReadFromDisk(txdb, prevout, txindex); } -bool CTransaction::ReadFromDisk(COutPoint prevout) -{ - CTxDB txdb("r"); - CTxIndex txindex; - return ReadFromDisk(txdb, prevout, txindex); -} - - - int CMerkleTx::SetMerkleBranch(const CBlock* pblock) { if (fClient) @@ -565,12 +556,6 @@ return false; } -bool CWalletTx::AcceptWalletTransaction() -{ - CTxDB txdb("r"); - return AcceptWalletTransaction(txdb); -} - int CTxIndex::GetDepthInMainChain() const { // Read block header @@ -2562,6 +2547,7 @@ txNew.vin.resize(1); txNew.vin[0].prevout.SetNull(); txNew.vout.resize(1); + SCOPED_LOCK(cs_main); // no later than here because GetReservedKey uses CWalletDB. txNew.vout[0].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG; // Add our coinbase tx as first transaction @@ -2569,7 +2555,6 @@ // Collect memory pool transactions into the block int64 nFees = 0; - CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_mapTransactions) { CTxDB txdb("r"); @@ -2963,14 +2948,8 @@ } -void GenerateBitcoins(bool fGenerate, CWallet* pwallet) +void GenerateBitcoins(CWallet* pwallet) { - if (fGenerateBitcoins != fGenerate) - { - fGenerateBitcoins = fGenerate; - WriteSetting("fGenerateBitcoins", fGenerateBitcoins); - MainFrameRepaint(); - } if (fGenerateBitcoins) { int nProcessors = boost::thread::hardware_concurrency(); diff -uNr a/bitcoin/src/main.h b/bitcoin/src/main.h --- a/bitcoin/src/main.h aca54ef12a38a60aaa5aa4cf466cc6514d35429d041db06352175e4ed73b265bae7d1b87131225b860f7dda5e6815a02b525d555407d82c5d4c5cd2974e0f2d1 +++ b/bitcoin/src/main.h f2d586abd98cb8b61ddcd5c63e6f627b58f1e8d5fa1be70e249347ff96e017afaace0b7d586715cc8d855c732f776c1f7e3f60cea8bdf4c2314c6cfb838560af @@ -97,7 +97,7 @@ void PrintBlockTree(); bool ProcessMessages(CNode* pfrom); bool SendMessages(CNode* pto, bool fSendTrickle); -void GenerateBitcoins(bool fGenerate, CWallet* pwallet); +void GenerateBitcoins(CWallet* pwallet); CBlock* CreateNewBlock(CReserveKey& reservekey); void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1); @@ -592,7 +592,6 @@ bool ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet); bool ReadFromDisk(CTxDB& txdb, COutPoint prevout); - bool ReadFromDisk(COutPoint prevout); bool DisconnectInputs(CTxDB& txdb); bool ConnectInputs(CTxDB& txdb, std::map& mapTestPool, CDiskTxPos posThisTx, CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee, diff -uNr a/bitcoin/src/net.cpp b/bitcoin/src/net.cpp --- a/bitcoin/src/net.cpp 15bb33eac15ff9e8d26a6a02ac68936bf748be6edd6f55a860edf8dc2b470ac9bc5e3cccd076164e82b6c9c282956820b2b3466b6c77dc77651d835e07732853 +++ b/bitcoin/src/net.cpp 2e8488fc44ab3883e25516df67fcd1bf5c06e4c413950935850cd854a22e5cf5c1567e3b046aad6ab0afd421610371ee2e61585fa82f4877ca5a0b35796b155d @@ -1192,7 +1192,7 @@ printf("Error: CreateThread(ThreadMessageHandler) failed\n"); // Generate coins in the background - GenerateBitcoins(fGenerateBitcoins, pwalletMain); + GenerateBitcoins(pwalletMain); } bool StopNode() diff -uNr a/bitcoin/src/wallet.cpp b/bitcoin/src/wallet.cpp --- a/bitcoin/src/wallet.cpp a7688a9eadf8cea2d5d65c432ae068bedbaf9ab865310c6d846dc3635732dd5ba217d2bf9c02131f241ed80681f15615bd579404e39750358c22ba8e866bd51a +++ b/bitcoin/src/wallet.cpp e185015ffd525641ab93cfc884b30b480ac5bba41e6e5596590fdc17063d0d749ebade8f3178ea1187120c17f25aca81eb8ffe0e303720826ef6bc031ff838f6 @@ -1181,15 +1181,6 @@ return CWalletDB(strWalletFile).WriteName(address.ToString(), strName); } -bool CWallet::DelAddressBookName(const CBitcoinAddress& address) -{ - mapAddressBook.erase(address); - if (!fFileBacked) - return false; - return CWalletDB(strWalletFile).EraseName(address.ToString()); -} - - void CWallet::PrintWallet(const CBlock& block) { CRITICAL_BLOCK(cs_wallet) diff -uNr a/bitcoin/src/wallet.h b/bitcoin/src/wallet.h --- a/bitcoin/src/wallet.h 61326c2a68a1ceef4a6d0512f02c291bfe7025275e52f69744d3bfec0ab8a41fa62e819aaebc151762f42be182ace3e9ef4f506a36aedf24ad204e60284e14a4 +++ b/bitcoin/src/wallet.h 5b385f013f54c927ac9b33988a5d8429548b02c94385345780e79620776f546d3fe332b3f300f0eaa6a399936691f4fc8b16ad871f362de3386152ca3ef257c5 @@ -180,8 +180,6 @@ bool SetAddressBookName(const CBitcoinAddress& address, const std::string& strName); - bool DelAddressBookName(const CBitcoinAddress& address); - void UpdatedTransaction(const uint256 &hashTx) { CRITICAL_BLOCK(cs_wallet) @@ -531,7 +529,6 @@ void AddSupportingTransactions(CTxDB& txdb); bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true); - bool AcceptWalletTransaction(); void RelayWalletTransaction(CTxDB& txdb); void RelayWalletTransaction();