Merge pull request #1046 from laanwj/2012_04_rpcporterror
authorWladimir J. van der Laan <laanwj@gmail.com>
Tue, 10 Apr 2012 20:14:47 +0000 (13:14 -0700)
committerWladimir J. van der Laan <laanwj@gmail.com>
Tue, 10 Apr 2012 20:14:47 +0000 (13:14 -0700)
Show error message instead of exception crash when unable to bind RPC port

37 files changed:
bitcoin-qt.pro
contrib/debian/bitcoin-qt.desktop
doc/assets-attribution.txt
src/addrman.h
src/bitcoinrpc.cpp
src/db.cpp
src/init.cpp
src/keystore.cpp
src/keystore.h
src/main.cpp
src/net.cpp
src/net.h
src/qt/addresstablemodel.cpp
src/qt/bitcoin.cpp
src/qt/bitcoingui.cpp
src/qt/bitcoingui.h
src/qt/forms/messagepage.ui
src/qt/guiutil.cpp
src/qt/guiutil.h
src/qt/qtipcserver.cpp
src/qt/qtipcserver.h
src/qt/sendcoinsdialog.cpp
src/qt/sendcoinsdialog.h
src/qt/test/test_main.cpp
src/qt/test/uritests.cpp [moved from src/qt/test/urltests.cpp with 57% similarity]
src/qt/test/uritests.h [new file with mode: 0644]
src/qt/test/urltests.h [deleted file]
src/qt/transactiondesc.cpp
src/qt/transactiontablemodel.cpp
src/qt/walletmodel.cpp
src/rpcdump.cpp
src/test/util_tests.cpp
src/ui_interface.h
src/util.cpp
src/util.h
src/wallet.cpp
src/wallet.h

index edb0fad..8b34d6c 100644 (file)
@@ -225,8 +225,8 @@ FORMS += src/qt/forms/qrcodedialog.ui
 
 contains(BITCOIN_QT_TEST, 1) {
 SOURCES += src/qt/test/test_main.cpp \
-    src/qt/test/urltests.cpp
-HEADERS += src/qt/test/urltests.h
+    src/qt/test/uritests.cpp
+HEADERS += src/qt/test/uritests.h
 DEPENDPATH += src/qt/test
 QT += testlib
 TARGET = bitcoin-qt_test
index ea5a6e4..7cb00a2 100644 (file)
@@ -2,6 +2,8 @@
 Encoding=UTF-8
 Name=Bitcoin
 Comment=Bitcoin P2P Cryptocurrency
+Comment[fr]=Bitcoin, monnaie virtuelle cryptographique pair à pair
+Comment[tr]=Bitcoin, eşten eşe kriptografik sanal para birimi
 Exec=/usr/bin/bitcoin-qt
 Terminal=false
 Type=Application
index fabcdee..0b0e377 100644 (file)
@@ -1,3 +1,7 @@
+Code: src/strlcpy.h
+Author: Todd C. Miller <Todd.Miller@courtesan.com>
+License: ISC
+
 Icon: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png,
       src/qt/res/src/*.svg
 Designer: Wladimir van der Laan
index 91e1f87..7652df6 100644 (file)
@@ -266,8 +266,8 @@ public:
         //
         // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
         // changes to the ADDRMAN_ parameters without breaking the on-disk structure.
-        CRITICAL_BLOCK(cs)
         {
+            LOCK(cs);
             unsigned char nVersion = 0;
             READWRITE(nVersion);
             READWRITE(nKey);
@@ -398,8 +398,8 @@ public:
     void Check()
     {
 #ifdef DEBUG_ADDRMAN
-        CRITICAL_BLOCK(cs)
         {
+            LOCK(cs);
             int err;
             if ((err=Check_()))
                 printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
@@ -411,8 +411,8 @@ public:
     bool Add(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty = 0)
     {
         bool fRet = false;
-        CRITICAL_BLOCK(cs)
         {
+            LOCK(cs);
             Check();
             fRet |= Add_(addr, source, nTimePenalty);
             Check();
@@ -426,8 +426,8 @@ public:
     bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64 nTimePenalty = 0)
     {
         int nAdd = 0;
-        CRITICAL_BLOCK(cs)
         {
+            LOCK(cs);
             Check();
             for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
                 nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
@@ -441,8 +441,8 @@ public:
     // Mark an entry as accessible.
     void Good(const CService &addr, int64 nTime = GetAdjustedTime())
     {
-        CRITICAL_BLOCK(cs)
         {
+            LOCK(cs);
             Check();
             Good_(addr, nTime);
             Check();
@@ -452,8 +452,8 @@ public:
     // Mark an entry as connection attempted to.
     void Attempt(const CService &addr, int64 nTime = GetAdjustedTime())
     {
-        CRITICAL_BLOCK(cs)
         {
+            LOCK(cs);
             Check();
             Attempt_(addr, nTime);
             Check();
@@ -465,8 +465,8 @@ public:
     CAddress Select(int nUnkBias = 50)
     {
         CAddress addrRet;
-        CRITICAL_BLOCK(cs)
         {
+            LOCK(cs);
             Check();
             addrRet = Select_(nUnkBias);
             Check();
@@ -479,8 +479,10 @@ public:
     {
         Check();
         std::vector<CAddress> vAddr;
-        CRITICAL_BLOCK(cs)
+        {
+            LOCK(cs);
             GetAddr_(vAddr);
+        }
         Check();
         return vAddr;
     }
@@ -488,8 +490,8 @@ public:
     // Mark an entry as currently-connected-to.
     void Connected(const CService &addr, int64 nTime = GetAdjustedTime())
     {
-        CRITICAL_BLOCK(cs)
         {
+            LOCK(cs);
             Check();
             Connected_(addr, nTime);
             Check();
index f0b7a52..4075c90 100644 (file)
@@ -15,7 +15,6 @@
 #include <boost/algorithm/string.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/asio/ssl.hpp> 
-#include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
 
@@ -1648,8 +1647,8 @@ Value walletlock(const Array& params, bool fHelp)
     if (!pwalletMain->IsCrypted())
         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
 
-    CRITICAL_BLOCK(cs_nWalletUnlockTime)
     {
+        LOCK(cs_nWalletUnlockTime);
         pwalletMain->Lock();
         nWalletUnlockTime = 0;
     }
@@ -2397,18 +2396,21 @@ void ThreadRPCServer2(void* parg)
     if (fUseSSL)
     {
         context.set_options(ssl::context::no_sslv2);
-        filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
-        if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
-        if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
-        else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
-        filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
-        if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
-        if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
-        else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
 
-        string ciphers = GetArg("-rpcsslciphers",
-                                         "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
-        SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
+        filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
+        if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
+        pathCertFile.make_preferred();
+        if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string().c_str());
+        else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
+
+        filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
+        if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
+        pathPKFile.make_preferred();
+        if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string().c_str(), ssl::context::pem);
+        else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
+
+        string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
+        SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
     }
 
     loop
@@ -2510,9 +2512,10 @@ void ThreadRPCServer2(void* parg)
             {
                 // Execute
                 Value result;
-                CRITICAL_BLOCK(cs_main)
-                CRITICAL_BLOCK(pwalletMain->cs_wallet)
+                {
+                    LOCK2(cs_main, pwalletMain->cs_wallet);
                     result = (*(*mi).second)(params, false);
+                }
 
                 // Send reply
                 string strReply = JSONRPCReply(result, Value::null, id);
index 2a09e2e..d47c159 100644 (file)
@@ -28,7 +28,6 @@ static bool fDbEnvInit = false;
 DbEnv dbenv(0);
 static map<string, int> mapFileUseCount;
 static map<string, Db*> mapDb;
-static int64 nTxn = 0;
 
 static void EnvShutdown()
 {
@@ -73,26 +72,28 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
     if (fCreate)
         nFlags |= DB_CREATE;
 
-    CRITICAL_BLOCK(cs_db)
     {
+        LOCK(cs_db);
         if (!fDbEnvInit)
         {
             if (fShutdown)
                 return;
             string strDataDir = GetDataDir();
-            string strLogDir = strDataDir + "/database";
-            filesystem::create_directory(strLogDir.c_str());
-            string strErrorFile = strDataDir + "/db.log";
-            printf("dbenv.open strLogDir=%s strErrorFile=%s\n", strLogDir.c_str(), strErrorFile.c_str());
+            filesystem::path pathLogDir(strDataDir + "/database");
+            pathLogDir.make_preferred();
+            filesystem::create_directory(pathLogDir);
+            filesystem::path pathErrorFile(strDataDir + "/db.log");
+            pathErrorFile.make_preferred();
+            printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str());
 
             int nDbCache = GetArg("-dbcache", 25);
-            dbenv.set_lg_dir(strLogDir.c_str());
+            dbenv.set_lg_dir(pathLogDir.string().c_str());
             dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1);
             dbenv.set_lg_bsize(1048576);
             dbenv.set_lg_max(10485760);
             dbenv.set_lk_max_locks(10000);
             dbenv.set_lk_max_objects(10000);
-            dbenv.set_errfile(fopen(strErrorFile.c_str(), "a")); /// debug
+            dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
             dbenv.set_flags(DB_AUTO_COMMIT, 1);
             dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
             ret = dbenv.open(strDataDir.c_str(),
@@ -127,8 +128,10 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
             {
                 delete pdb;
                 pdb = NULL;
-                CRITICAL_BLOCK(cs_db)
+                {
+                     LOCK(cs_db);
                     --mapFileUseCount[strFile];
+                }
                 strFile = "";
                 throw runtime_error(strprintf("CDB() : can't open database file %s, error %d", pszFile, ret));
             }
@@ -164,22 +167,18 @@ void CDB::Close()
     if (strFile == "blkindex.dat" && IsInitialBlockDownload())
         nMinutes = 5;
 
-    if (nMinutes == 0 || nTxn > 200000)
-    {
-        nTxn = 0;
-        nMinutes = 0;
-    }
+    dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
 
-    dbenv.txn_checkpoint(0, nMinutes, 0);
-
-    CRITICAL_BLOCK(cs_db)
+    {
+        LOCK(cs_db);
         --mapFileUseCount[strFile];
+    }
 }
 
 void static CloseDb(const string& strFile)
 {
-    CRITICAL_BLOCK(cs_db)
     {
+        LOCK(cs_db);
         if (mapDb[strFile] != NULL)
         {
             // Close the database handle
@@ -195,8 +194,8 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
 {
     while (!fShutdown)
     {
-        CRITICAL_BLOCK(cs_db)
         {
+            LOCK(cs_db);
             if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
             {
                 // Flush log data to the dat file
@@ -293,8 +292,8 @@ void DBFlush(bool fShutdown)
     printf("DBFlush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
     if (!fDbEnvInit)
         return;
-    CRITICAL_BLOCK(cs_db)
     {
+        LOCK(cs_db);
         map<string, int>::iterator mi = mapFileUseCount.begin();
         while (mi != mapFileUseCount.end())
         {
@@ -344,7 +343,6 @@ bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex)
 bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
 {
     assert(!fClient);
-    nTxn++;
     return Write(make_pair(string("tx"), hash), txindex);
 }
 
@@ -355,7 +353,6 @@ bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeigh
     // Add to tx index
     uint256 hash = tx.GetHash();
     CTxIndex txindex(pos, tx.vout.size());
-    nTxn++;
     return Write(make_pair(string("tx"), hash), txindex);
 }
 
@@ -886,8 +883,8 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
     bool fIsEncrypted = false;
 
     //// todo: shouldn't we catch exceptions and try to recover and continue?
-    CRITICAL_BLOCK(pwallet->cs_wallet)
     {
+        LOCK(pwallet->cs_wallet);
         int nMinVersion = 0;
         if (Read((string)"minversion", nMinVersion))
         {
@@ -1128,7 +1125,8 @@ void ThreadFlushWalletDB(void* parg)
 
         if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
         {
-            TRY_CRITICAL_BLOCK(cs_db)
+            TRY_LOCK(cs_db,lockDb);
+            if (lockDb)
             {
                 // Don't do this if any databases are in use
                 int nRefCount = 0;
@@ -1169,8 +1167,8 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
         return false;
     while (!fShutdown)
     {
-        CRITICAL_BLOCK(cs_db)
         {
+            LOCK(cs_db);
             if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0)
             {
                 // Flush log data to the dat file
@@ -1181,7 +1179,9 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
 
                 // Copy wallet.dat
                 filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile);
+                pathSrc.make_preferred();
                 filesystem::path pathDest(strDest);
+                pathDest.make_preferred();
                 if (filesystem::is_directory(pathDest))
                     pathDest = pathDest / wallet.strWalletFile;
 
index 05b4e87..a1e45b1 100644 (file)
@@ -40,10 +40,13 @@ void Shutdown(void* parg)
     static CCriticalSection cs_Shutdown;
     static bool fTaken;
     bool fFirstThread = false;
-    TRY_CRITICAL_BLOCK(cs_Shutdown)
     {
-        fFirstThread = !fTaken;
-        fTaken = true;
+        TRY_LOCK(cs_Shutdown, lockShutdown);
+        if (lockShutdown)
+        {
+            fFirstThread = !fTaken;
+            fTaken = true;
+        }
     }
     static bool fExit;
     if (fFirstThread)
@@ -171,6 +174,7 @@ bool AppInit2(int argc, char* argv[])
             "  -splash          \t\t  " + _("Show splash screen on startup (default: 1)") + "\n" +
             "  -datadir=<dir>   \t\t  " + _("Specify data directory") + "\n" +
             "  -dbcache=<n>     \t\t  " + _("Set database cache size in megabytes (default: 25)") + "\n" +
+            "  -dblogsize=<n>   \t\t  " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
             "  -timeout=<n>     \t  "   + _("Specify connection timeout (in milliseconds)") + "\n" +
             "  -proxy=<ip:port> \t  "   + _("Connect through socks4 proxy") + "\n" +
             "  -dns             \t  "   + _("Allow DNS lookups for addnode and connect") + "\n" +
index 23f9e32..7b46f6b 100644 (file)
@@ -21,31 +21,37 @@ bool CBasicKeyStore::AddKey(const CKey& key)
 {
     bool fCompressed = false;
     CSecret secret = key.GetSecret(fCompressed);
-    CRITICAL_BLOCK(cs_KeyStore)
+    {
+        LOCK(cs_KeyStore);
         mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed);
+    }
     return true;
 }
 
 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
 {
-    CRITICAL_BLOCK(cs_KeyStore)
+    {
+        LOCK(cs_KeyStore);
         mapScripts[Hash160(redeemScript)] = redeemScript;
+    }
     return true;
 }
 
 bool CBasicKeyStore::HaveCScript(const uint160& hash) const
 {
     bool result;
-    CRITICAL_BLOCK(cs_KeyStore)
+    {
+        LOCK(cs_KeyStore);
         result = (mapScripts.count(hash) > 0);
+    }
     return result;
 }
 
 
 bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const
 {
-    CRITICAL_BLOCK(cs_KeyStore)
     {
+        LOCK(cs_KeyStore);
         ScriptMap::const_iterator mi = mapScripts.find(hash);
         if (mi != mapScripts.end())
         {
@@ -58,8 +64,8 @@ bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) c
 
 bool CCryptoKeyStore::SetCrypted()
 {
-    CRITICAL_BLOCK(cs_KeyStore)
     {
+        LOCK(cs_KeyStore);
         if (fUseCrypto)
             return true;
         if (!mapKeys.empty())
@@ -71,8 +77,8 @@ bool CCryptoKeyStore::SetCrypted()
 
 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
 {
-    CRITICAL_BLOCK(cs_KeyStore)
     {
+        LOCK(cs_KeyStore);
         if (!SetCrypted())
             return false;
 
@@ -100,8 +106,8 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
 
 bool CCryptoKeyStore::AddKey(const CKey& key)
 {
-    CRITICAL_BLOCK(cs_KeyStore)
     {
+        LOCK(cs_KeyStore);
         if (!IsCrypted())
             return CBasicKeyStore::AddKey(key);
 
@@ -123,8 +129,8 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
 
 bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
 {
-    CRITICAL_BLOCK(cs_KeyStore)
     {
+        LOCK(cs_KeyStore);
         if (!SetCrypted())
             return false;
 
@@ -135,8 +141,8 @@ bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey,
 
 bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
 {
-    CRITICAL_BLOCK(cs_KeyStore)
     {
+        LOCK(cs_KeyStore);
         if (!IsCrypted())
             return CBasicKeyStore::GetKey(address, keyOut);
 
@@ -160,8 +166,8 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
 
 bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
 {
-    CRITICAL_BLOCK(cs_KeyStore)
     {
+        LOCK(cs_KeyStore);
         if (!IsCrypted())
             return CKeyStore::GetPubKey(address, vchPubKeyOut);
 
@@ -177,8 +183,8 @@ bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsi
 
 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
 {
-    CRITICAL_BLOCK(cs_KeyStore)
     {
+        LOCK(cs_KeyStore);
         if (!mapCryptedKeys.empty() || IsCrypted())
             return false;
 
index c32db26..282eaaa 100644 (file)
@@ -54,15 +54,17 @@ public:
     bool HaveKey(const CBitcoinAddress &address) const
     {
         bool result;
-        CRITICAL_BLOCK(cs_KeyStore)
+        {
+            LOCK(cs_KeyStore);
             result = (mapKeys.count(address) > 0);
+        }
         return result;
     }
     void GetKeys(std::set<CBitcoinAddress> &setAddress) const
     {
         setAddress.clear();
-        CRITICAL_BLOCK(cs_KeyStore)
         {
+            LOCK(cs_KeyStore);
             KeyMap::const_iterator mi = mapKeys.begin();
             while (mi != mapKeys.end())
             {
@@ -73,8 +75,8 @@ public:
     }
     bool GetKey(const CBitcoinAddress &address, CKey &keyOut) const
     {
-        CRITICAL_BLOCK(cs_KeyStore)
         {
+            LOCK(cs_KeyStore);
             KeyMap::const_iterator mi = mapKeys.find(address);
             if (mi != mapKeys.end())
             {
@@ -129,8 +131,10 @@ public:
         if (!IsCrypted())
             return false;
         bool result;
-        CRITICAL_BLOCK(cs_KeyStore)
+        {
+            LOCK(cs_KeyStore);
             result = vMasterKey.empty();
+        }
         return result;
     }
 
@@ -139,8 +143,10 @@ public:
         if (!SetCrypted())
             return false;
 
-        CRITICAL_BLOCK(cs_KeyStore)
+        {
+            LOCK(cs_KeyStore);
             vMasterKey.clear();
+        }
 
         return true;
     }
@@ -149,8 +155,8 @@ public:
     bool AddKey(const CKey& key);
     bool HaveKey(const CBitcoinAddress &address) const
     {
-        CRITICAL_BLOCK(cs_KeyStore)
         {
+            LOCK(cs_KeyStore);
             if (!IsCrypted())
                 return CBasicKeyStore::HaveKey(address);
             return mapCryptedKeys.count(address) > 0;
index 7c49316..dea60f0 100644 (file)
@@ -75,16 +75,16 @@ int64 nTransactionFee = 0;
 
 void RegisterWallet(CWallet* pwalletIn)
 {
-    CRITICAL_BLOCK(cs_setpwalletRegistered)
     {
+        LOCK(cs_setpwalletRegistered);
         setpwalletRegistered.insert(pwalletIn);
     }
 }
 
 void UnregisterWallet(CWallet* pwalletIn)
 {
-    CRITICAL_BLOCK(cs_setpwalletRegistered)
     {
+        LOCK(cs_setpwalletRegistered);
         setpwalletRegistered.erase(pwalletIn);
     }
 }
@@ -478,9 +478,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
 
     // Do we already have it?
     uint256 hash = GetHash();
-    CRITICAL_BLOCK(cs_mapTransactions)
+    {
+        LOCK(cs_mapTransactions);
         if (mapTransactions.count(hash))
             return false;
+    }
     if (fCheckInputs)
         if (txdb.ContainsTx(hash))
             return false;
@@ -552,8 +554,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
             static int64 nLastTime;
             int64 nNow = GetTime();
 
-            CRITICAL_BLOCK(cs)
             {
+                LOCK(cs);
                 // Use an exponentially decaying ~10-minute window:
                 dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
                 nLastTime = nNow;
@@ -576,8 +578,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
     }
 
     // Store transaction in memory
-    CRITICAL_BLOCK(cs_mapTransactions)
     {
+        LOCK(cs_mapTransactions);
         if (ptxOld)
         {
             printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
@@ -608,8 +610,8 @@ bool CTransaction::AddToMemoryPoolUnchecked()
     printf("AcceptToMemoryPoolUnchecked(): size %lu\n",  mapTransactions.size());
     // Add to memory pool without checking anything.  Don't call this directly,
     // call AcceptToMemoryPool to properly check the transaction first.
-    CRITICAL_BLOCK(cs_mapTransactions)
     {
+        LOCK(cs_mapTransactions);
         uint256 hash = GetHash();
         mapTransactions[hash] = *this;
         for (int i = 0; i < vin.size(); i++)
@@ -624,8 +626,8 @@ bool CTransaction::AddToMemoryPoolUnchecked()
 bool CTransaction::RemoveFromMemoryPool()
 {
     // Remove transaction from memory pool
-    CRITICAL_BLOCK(cs_mapTransactions)
     {
+        LOCK(cs_mapTransactions);
         uint256 hash = GetHash();
         if (mapTransactions.count(hash))
         {
@@ -702,8 +704,9 @@ bool CMerkleTx::AcceptToMemoryPool()
 
 bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
 {
-    CRITICAL_BLOCK(cs_mapTransactions)
+
     {
+        LOCK(cs_mapTransactions);
         // Add previous supporting transactions first
         BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
         {
@@ -1024,8 +1027,8 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map<uint256, CTxIndex>& mapTes
         if (!fFound || txindex.pos == CDiskTxPos(1,1,1))
         {
             // Get prev tx from single transactions in memory
-            CRITICAL_BLOCK(cs_mapTransactions)
             {
+                LOCK(cs_mapTransactions);
                 if (!mapTransactions.count(prevout.hash))
                     return error("FetchInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,10).c_str(),  prevout.hash.ToString().substr(0,10).c_str());
                 txPrev = mapTransactions[prevout.hash];
@@ -1190,8 +1193,8 @@ bool CTransaction::ClientConnectInputs()
         return false;
 
     // Take over previous transactions' spent pointers
-    CRITICAL_BLOCK(cs_mapTransactions)
     {
+        LOCK(cs_mapTransactions);
         int64 nValueIn = 0;
         for (int i = 0; i < vin.size(); i++)
         {
@@ -1707,10 +1710,12 @@ bool CBlock::AcceptBlock()
     // Relay inventory, but don't relay old inventory during initial block download
     int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
     if (hashBestChain == hash)
-        CRITICAL_BLOCK(cs_vNodes)
-            BOOST_FOREACH(CNode* pnode, vNodes)
-                if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
-                    pnode->PushInventory(CInv(MSG_BLOCK, hash));
+    {
+        LOCK(cs_vNodes);
+        BOOST_FOREACH(CNode* pnode, vNodes)
+            if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
+                pnode->PushInventory(CInv(MSG_BLOCK, hash));
+    }
 
     return true;
 }
@@ -2052,8 +2057,8 @@ string GetWarnings(string strFor)
     }
 
     // Alerts
-    CRITICAL_BLOCK(cs_mapAlerts)
     {
+        LOCK(cs_mapAlerts);
         BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
         {
             const CAlert& alert = item.second;
@@ -2080,8 +2085,8 @@ bool CAlert::ProcessAlert()
     if (!IsInEffect())
         return false;
 
-    CRITICAL_BLOCK(cs_mapAlerts)
     {
+        LOCK(cs_mapAlerts);
         // Cancel previous alerts
         for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
         {
@@ -2260,9 +2265,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         }
 
         // Relay alerts
-        CRITICAL_BLOCK(cs_mapAlerts)
+        {
+            LOCK(cs_mapAlerts);
             BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
                 item.second.RelayTo(pfrom);
+        }
 
         pfrom->fSuccessfullyConnected = true;
 
@@ -2316,8 +2323,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
             if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
             {
                 // Relay to a limited number of other nodes
-                CRITICAL_BLOCK(cs_vNodes)
                 {
+                    LOCK(cs_vNodes);
                     // Use deterministic randomness to send to the same nodes for 24 hours
                     // at a time so the setAddrKnowns of the chosen nodes prevent repeats
                     static uint256 hashSalt;
@@ -2428,8 +2435,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
             else if (inv.IsKnownType())
             {
                 // Send stream from relay memory
-                CRITICAL_BLOCK(cs_mapRelay)
                 {
+                    LOCK(cs_mapRelay);
                     map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
                     if (mi != mapRelay.end())
                         pfrom->PushMessage(inv.GetCommand(), (*mi).second);
@@ -2634,8 +2641,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         vRecv >> hashReply;
 
         CRequestTracker tracker;
-        CRITICAL_BLOCK(pfrom->cs_mapRequests)
         {
+            LOCK(pfrom->cs_mapRequests);
             map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply);
             if (mi != pfrom->mapRequests.end())
             {
@@ -2662,9 +2669,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         {
             // Relay
             pfrom->setKnown.insert(alert.GetHash());
-            CRITICAL_BLOCK(cs_vNodes)
+            {
+                LOCK(cs_vNodes);
                 BOOST_FOREACH(CNode* pnode, vNodes)
                     alert.RelayTo(pnode);
+            }
         }
     }
 
@@ -2763,8 +2772,10 @@ bool ProcessMessages(CNode* pfrom)
         bool fRet = false;
         try
         {
-            CRITICAL_BLOCK(cs_main)
+            {
+                LOCK(cs_main);
                 fRet = ProcessMessage(pfrom, strCommand, vMsg);
+            }
             if (fShutdown)
                 return true;
         }
@@ -2802,8 +2813,8 @@ bool ProcessMessages(CNode* pfrom)
 
 bool SendMessages(CNode* pto, bool fSendTrickle)
 {
-    CRITICAL_BLOCK(cs_main)
     {
+        LOCK(cs_main);
         // Don't send anything until we get their version message
         if (pto->nVersion == 0)
             return true;
@@ -2819,8 +2830,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
         static int64 nLastRebroadcast;
         if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
         {
-            CRITICAL_BLOCK(cs_vNodes)
             {
+                LOCK(cs_vNodes);
                 BOOST_FOREACH(CNode* pnode, vNodes)
                 {
                     // Periodically clear setAddrKnown to allow refresh broadcasts
@@ -2871,8 +2882,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
         //
         vector<CInv> vInv;
         vector<CInv> vInvWait;
-        CRITICAL_BLOCK(pto->cs_inventory)
         {
+            LOCK(pto->cs_inventory);
             vInv.reserve(pto->vInventoryToSend.size());
             vInvWait.reserve(pto->vInventoryToSend.size());
             BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend)
@@ -3087,9 +3098,8 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
 
     // Collect memory pool transactions into the block
     int64 nFees = 0;
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapTransactions)
     {
+        LOCK2(cs_main, cs_mapTransactions);
         CTxDB txdb("r");
 
         // Priority order to process transactions
@@ -3317,8 +3327,8 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
     printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
 
     // Found a solution
-    CRITICAL_BLOCK(cs_main)
     {
+        LOCK(cs_main);
         if (pblock->hashPrevBlock != hashBestChain)
             return error("BitcoinMiner : generated block is stale");
 
@@ -3326,8 +3336,10 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
         reservekey.KeepKey();
 
         // Track how many getdata requests this block gets
-        CRITICAL_BLOCK(wallet.cs_wallet)
+        {
+            LOCK(wallet.cs_wallet);
             wallet.mapRequestCount[pblock->GetHash()] = 0;
+        }
 
         // Process this block the same as if we had received it from another node
         if (!ProcessBlock(NULL, pblock))
@@ -3443,8 +3455,8 @@ void static BitcoinMiner(CWallet *pwallet)
             if (GetTimeMillis() - nHPSTimerStart > 4000)
             {
                 static CCriticalSection cs;
-                CRITICAL_BLOCK(cs)
                 {
+                    LOCK(cs);
                     if (GetTimeMillis() - nHPSTimerStart > 4000)
                     {
                         dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
index 7dc2d4c..8272b25 100644 (file)
@@ -64,6 +64,9 @@ map<CInv, int64> mapAlreadyAskedFor;
 set<CNetAddr> setservAddNodeAddresses;
 CCriticalSection cs_setservAddNodeAddresses;
 
+static CWaitableCriticalSection csOutbound;
+static int nOutbound = 0;
+static CConditionVariable condOutbound;
 
 
 unsigned short GetListenPort()
@@ -269,9 +272,11 @@ void ThreadGetMyExternalIP(void* parg)
             // setAddrKnown automatically filters any duplicate sends.
             CAddress addr(addrLocalHost);
             addr.nTime = GetAdjustedTime();
-            CRITICAL_BLOCK(cs_vNodes)
+            {
+                LOCK(cs_vNodes);
                 BOOST_FOREACH(CNode* pnode, vNodes)
                     pnode->PushAddress(addr);
+            }
         }
     }
 }
@@ -293,8 +298,8 @@ void AddressCurrentlyConnected(const CService& addr)
 
 CNode* FindNode(const CNetAddr& ip)
 {
-    CRITICAL_BLOCK(cs_vNodes)
     {
+        LOCK(cs_vNodes);
         BOOST_FOREACH(CNode* pnode, vNodes)
             if ((CNetAddr)pnode->addr == ip)
                 return (pnode);
@@ -304,8 +309,8 @@ CNode* FindNode(const CNetAddr& ip)
 
 CNode* FindNode(const CService& addr)
 {
-    CRITICAL_BLOCK(cs_vNodes)
     {
+        LOCK(cs_vNodes);
         BOOST_FOREACH(CNode* pnode, vNodes)
             if ((CService)pnode->addr == addr)
                 return (pnode);
@@ -359,8 +364,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
             pnode->AddRef(nTimeout);
         else
             pnode->AddRef();
-        CRITICAL_BLOCK(cs_vNodes)
+        {
+            LOCK(cs_vNodes);
             vNodes.push_back(pnode);
+        }
+        {
+            WAITABLE_LOCK(csOutbound);
+            nOutbound++;
+        }
 
         pnode->nTimeConnected = GetTime();
         return pnode;
@@ -416,8 +427,8 @@ void CNode::ClearBanned()
 bool CNode::IsBanned(CNetAddr ip)
 {
     bool fResult = false;
-    CRITICAL_BLOCK(cs_setBanned)
     {
+        LOCK(cs_setBanned);
         std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
         if (i != setBanned.end())
         {
@@ -441,9 +452,11 @@ bool CNode::Misbehaving(int howmuch)
     if (nMisbehavior >= GetArg("-banscore", 100))
     {
         int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);  // Default 24-hour ban
-        CRITICAL_BLOCK(cs_setBanned)
+        {
+            LOCK(cs_setBanned);
             if (setBanned[addr] < banTime)
                 setBanned[addr] = banTime;
+        }
         CloseSocketDisconnect();
         printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
         return true;
@@ -492,8 +505,8 @@ void ThreadSocketHandler2(void* parg)
         //
         // Disconnect nodes
         //
-        CRITICAL_BLOCK(cs_vNodes)
         {
+            LOCK(cs_vNodes);
             // Disconnect unused nodes
             vector<CNode*> vNodesCopy = vNodes;
             BOOST_FOREACH(CNode* pnode, vNodesCopy)
@@ -504,6 +517,15 @@ void ThreadSocketHandler2(void* parg)
                     // remove from vNodes
                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
 
+                    if (!pnode->fInbound)
+                        {
+                            WAITABLE_LOCK(csOutbound);
+                            nOutbound--;
+
+                            // Connection slot(s) were removed, notify connection creator(s)
+                            NOTIFY(condOutbound);
+                        }
+
                     // close socket and cleanup
                     pnode->CloseSocketDisconnect();
                     pnode->Cleanup();
@@ -524,11 +546,23 @@ void ThreadSocketHandler2(void* parg)
                 if (pnode->GetRefCount() <= 0)
                 {
                     bool fDelete = false;
-                    TRY_CRITICAL_BLOCK(pnode->cs_vSend)
-                     TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
-                      TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
-                       TRY_CRITICAL_BLOCK(pnode->cs_inventory)
-                        fDelete = true;
+                    {
+                        TRY_LOCK(pnode->cs_vSend, lockSend);
+                        if (lockSend)
+                        {
+                            TRY_LOCK(pnode->cs_vRecv, lockRecv);
+                            if (lockRecv)
+                            {
+                                TRY_LOCK(pnode->cs_mapRequests, lockReq);
+                                if (lockReq)
+                                {
+                                    TRY_LOCK(pnode->cs_inventory, lockInv);
+                                    if (lockInv)
+                                        fDelete = true;
+                                }
+                            }
+                        }
+                    }
                     if (fDelete)
                     {
                         vNodesDisconnected.remove(pnode);
@@ -562,8 +596,8 @@ void ThreadSocketHandler2(void* parg)
         if(hListenSocket != INVALID_SOCKET)
             FD_SET(hListenSocket, &fdsetRecv);
         hSocketMax = max(hSocketMax, hListenSocket);
-        CRITICAL_BLOCK(cs_vNodes)
         {
+            LOCK(cs_vNodes);
             BOOST_FOREACH(CNode* pnode, vNodes)
             {
                 if (pnode->hSocket == INVALID_SOCKET)
@@ -571,9 +605,11 @@ void ThreadSocketHandler2(void* parg)
                 FD_SET(pnode->hSocket, &fdsetRecv);
                 FD_SET(pnode->hSocket, &fdsetError);
                 hSocketMax = max(hSocketMax, pnode->hSocket);
-                TRY_CRITICAL_BLOCK(pnode->cs_vSend)
-                    if (!pnode->vSend.empty())
+                {
+                    TRY_LOCK(pnode->cs_vSend, lockSend);
+                    if (lockSend && !pnode->vSend.empty())
                         FD_SET(pnode->hSocket, &fdsetSend);
+                }
             }
         }
 
@@ -611,10 +647,12 @@ void ThreadSocketHandler2(void* parg)
             if (hSocket != INVALID_SOCKET)
                 addr = CAddress(sockaddr);
 
-            CRITICAL_BLOCK(cs_vNodes)
+            {
+                LOCK(cs_vNodes);
                 BOOST_FOREACH(CNode* pnode, vNodes)
-                if (pnode->fInbound)
-                    nInbound++;
+                    if (pnode->fInbound)
+                        nInbound++;
+            }
 
             if (hSocket == INVALID_SOCKET)
             {
@@ -623,9 +661,11 @@ void ThreadSocketHandler2(void* parg)
             }
             else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
             {
-                CRITICAL_BLOCK(cs_setservAddNodeAddresses)
+                {
+                    LOCK(cs_setservAddNodeAddresses);
                     if (!setservAddNodeAddresses.count(addr))
                         closesocket(hSocket);
+                }
             }
             else if (CNode::IsBanned(addr))
             {
@@ -637,8 +677,10 @@ void ThreadSocketHandler2(void* parg)
                 printf("accepted connection %s\n", addr.ToString().c_str());
                 CNode* pnode = new CNode(hSocket, addr, true);
                 pnode->AddRef();
-                CRITICAL_BLOCK(cs_vNodes)
+                {
+                    LOCK(cs_vNodes);
                     vNodes.push_back(pnode);
+                }
             }
         }
 
@@ -647,8 +689,8 @@ void ThreadSocketHandler2(void* parg)
         // Service each socket
         //
         vector<CNode*> vNodesCopy;
-        CRITICAL_BLOCK(cs_vNodes)
         {
+            LOCK(cs_vNodes);
             vNodesCopy = vNodes;
             BOOST_FOREACH(CNode* pnode, vNodesCopy)
                 pnode->AddRef();
@@ -665,7 +707,8 @@ void ThreadSocketHandler2(void* parg)
                 continue;
             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
             {
-                TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
+                TRY_LOCK(pnode->cs_vRecv, lockRecv);
+                if (lockRecv)
                 {
                     CDataStream& vRecv = pnode->vRecv;
                     unsigned int nPos = vRecv.size();
@@ -714,7 +757,8 @@ void ThreadSocketHandler2(void* parg)
                 continue;
             if (FD_ISSET(pnode->hSocket, &fdsetSend))
             {
-                TRY_CRITICAL_BLOCK(pnode->cs_vSend)
+                TRY_LOCK(pnode->cs_vSend, lockSend);
+                if (lockSend)
                 {
                     CDataStream& vSend = pnode->vSend;
                     if (!vSend.empty())
@@ -768,8 +812,8 @@ void ThreadSocketHandler2(void* parg)
                 }
             }
         }
-        CRITICAL_BLOCK(cs_vNodes)
         {
+            LOCK(cs_vNodes);
             BOOST_FOREACH(CNode* pnode, vNodesCopy)
                 pnode->Release();
         }
@@ -1172,8 +1216,6 @@ void ThreadOpenConnections2(void* parg)
     int64 nStart = GetTime();
     loop
     {
-        int nOutbound = 0;
-
         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
         Sleep(500);
         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
@@ -1181,23 +1223,15 @@ void ThreadOpenConnections2(void* parg)
             return;
 
         // Limit outbound connections
-        loop
+        int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
+        vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
         {
-            nOutbound = 0;
-            CRITICAL_BLOCK(cs_vNodes)
-                BOOST_FOREACH(CNode* pnode, vNodes)
-                    if (!pnode->fInbound)
-                        nOutbound++;
-            int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
-            nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
-            if (nOutbound < nMaxOutboundConnections)
-                break;
-            vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
-            Sleep(2000);
-            vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
-            if (fShutdown)
-                return;
+            WAITABLE_LOCK(csOutbound);
+            WAIT(condOutbound, fShutdown || nOutbound < nMaxOutbound);
         }
+        vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
+        if (fShutdown)
+            return;
 
         bool fAddSeeds = false;
 
@@ -1231,9 +1265,11 @@ void ThreadOpenConnections2(void* parg)
         // Only connect to one address per a.b.?.? range.
         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
         set<vector<unsigned char> > setConnected;
-        CRITICAL_BLOCK(cs_vNodes)
+        {
+            LOCK(cs_vNodes);
             BOOST_FOREACH(CNode* pnode, vNodes)
                 setConnected.insert(pnode->addr.GetGroup());
+        }
 
         int64 nANow = GetAdjustedTime();
 
@@ -1299,9 +1335,11 @@ void ThreadOpenAddedConnections2(void* parg)
         if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0))
         {
             vservAddressesToAdd.push_back(vservNode);
-            CRITICAL_BLOCK(cs_setservAddNodeAddresses)
+            {
+                LOCK(cs_setservAddNodeAddresses);
                 BOOST_FOREACH(CService& serv, vservNode)
                     setservAddNodeAddresses.insert(serv);
+            }
         }
     }
     loop
@@ -1309,7 +1347,8 @@ void ThreadOpenAddedConnections2(void* parg)
         vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
         // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
         // (keeping in mind that addnode entries can have many IPs if fAllowDNS)
-        CRITICAL_BLOCK(cs_vNodes)
+        {
+            LOCK(cs_vNodes);
             BOOST_FOREACH(CNode* pnode, vNodes)
                 for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)
                     BOOST_FOREACH(CService& addrNode, *(it))
@@ -1319,6 +1358,7 @@ void ThreadOpenAddedConnections2(void* parg)
                             it--;
                             break;
                         }
+        }
         BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
         {
             OpenNetworkConnection(CAddress(*(vserv.begin())));
@@ -1392,8 +1432,8 @@ void ThreadMessageHandler2(void* parg)
     while (!fShutdown)
     {
         vector<CNode*> vNodesCopy;
-        CRITICAL_BLOCK(cs_vNodes)
         {
+            LOCK(cs_vNodes);
             vNodesCopy = vNodes;
             BOOST_FOREACH(CNode* pnode, vNodesCopy)
                 pnode->AddRef();
@@ -1406,20 +1446,26 @@ void ThreadMessageHandler2(void* parg)
         BOOST_FOREACH(CNode* pnode, vNodesCopy)
         {
             // Receive messages
-            TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
-                ProcessMessages(pnode);
+            {
+                TRY_LOCK(pnode->cs_vRecv, lockRecv);
+                if (lockRecv)
+                    ProcessMessages(pnode);
+            }
             if (fShutdown)
                 return;
 
             // Send messages
-            TRY_CRITICAL_BLOCK(pnode->cs_vSend)
-                SendMessages(pnode, pnode == pnodeTrickle);
+            {
+                TRY_LOCK(pnode->cs_vSend, lockSend);
+                if (lockSend)
+                    SendMessages(pnode, pnode == pnodeTrickle);
+            }
             if (fShutdown)
                 return;
         }
 
-        CRITICAL_BLOCK(cs_vNodes)
         {
+            LOCK(cs_vNodes);
             BOOST_FOREACH(CNode* pnode, vNodesCopy)
                 pnode->Release();
         }
@@ -1646,6 +1692,7 @@ bool StopNode()
     fShutdown = true;
     nTransactionsUpdated++;
     int64 nStart = GetTime();
+    NOTIFY_ALL(condOutbound);
     do
     {
         int nThreadsRunning = 0;
index cd707e7..3c84650 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -247,15 +247,19 @@ public:
 
     void AddInventoryKnown(const CInv& inv)
     {
-        CRITICAL_BLOCK(cs_inventory)
+        {
+            LOCK(cs_inventory);
             setInventoryKnown.insert(inv);
+        }
     }
 
     void PushInventory(const CInv& inv)
     {
-        CRITICAL_BLOCK(cs_inventory)
+        {
+            LOCK(cs_inventory);
             if (!setInventoryKnown.count(inv))
                 vInventoryToSend.push_back(inv);
+        }
     }
 
     void AskFor(const CInv& inv)
@@ -519,8 +523,10 @@ public:
         uint256 hashReply;
         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
 
-        CRITICAL_BLOCK(cs_mapRequests)
+        {
+            LOCK(cs_mapRequests);
             mapRequests[hashReply] = CRequestTracker(fn, param1);
+        }
 
         PushMessage(pszCommand, hashReply);
     }
@@ -532,8 +538,10 @@ public:
         uint256 hashReply;
         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
 
-        CRITICAL_BLOCK(cs_mapRequests)
+        {
+            LOCK(cs_mapRequests);
             mapRequests[hashReply] = CRequestTracker(fn, param1);
+        }
 
         PushMessage(pszCommand, hashReply, a1);
     }
@@ -545,8 +553,10 @@ public:
         uint256 hashReply;
         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
 
-        CRITICAL_BLOCK(cs_mapRequests)
+        {
+            LOCK(cs_mapRequests);
             mapRequests[hashReply] = CRequestTracker(fn, param1);
+        }
 
         PushMessage(pszCommand, hashReply, a1, a2);
     }
@@ -592,9 +602,11 @@ public:
 inline void RelayInventory(const CInv& inv)
 {
     // Put on lists to offer to the other nodes
-    CRITICAL_BLOCK(cs_vNodes)
+    {
+        LOCK(cs_vNodes);
         BOOST_FOREACH(CNode* pnode, vNodes)
             pnode->PushInventory(inv);
+    }
 }
 
 template<typename T>
@@ -609,8 +621,8 @@ void RelayMessage(const CInv& inv, const T& a)
 template<>
 inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
 {
-    CRITICAL_BLOCK(cs_mapRelay)
     {
+        LOCK(cs_mapRelay);
         // Expire old relay messages
         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
         {
index 198a857..05f3a81 100644 (file)
@@ -39,8 +39,8 @@ struct AddressTablePriv
     {
         cachedAddressTable.clear();
 
-        CRITICAL_BLOCK(wallet->cs_wallet)
         {
+            LOCK(wallet->cs_wallet);
             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, wallet->mapAddressBook)
             {
                 const CBitcoinAddress& address = item.first;
@@ -169,8 +169,8 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
             // Double-check that we're not overwriting a receiving address
             if(rec->type == AddressTableEntry::Sending)
             {
-                CRITICAL_BLOCK(wallet->cs_wallet)
                 {
+                    LOCK(wallet->cs_wallet);
                     // Remove old entry
                     wallet->DelAddressBookName(rec->address.toStdString());
                     // Add new entry with new address
@@ -254,8 +254,8 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
             return QString();
         }
         // Check for duplicate addresses
-        CRITICAL_BLOCK(wallet->cs_wallet)
         {
+            LOCK(wallet->cs_wallet);
             if(wallet->mapAddressBook.count(strAddress))
             {
                 editStatus = DUPLICATE_ADDRESS;
@@ -286,8 +286,10 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
         return QString();
     }
     // Add entry
-    CRITICAL_BLOCK(wallet->cs_wallet)
+    {
+        LOCK(wallet->cs_wallet);
         wallet->SetAddressBookName(strAddress, strLabel);
+    }
     return QString::fromStdString(strAddress);
 }
 
@@ -301,8 +303,8 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
         // Also refuse to remove receiving addresses.
         return false;
     }
-    CRITICAL_BLOCK(wallet->cs_wallet)
     {
+        LOCK(wallet->cs_wallet);
         wallet->DelAddressBookName(rec->address.toStdString());
     }
     return true;
@@ -312,8 +314,8 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
  */
 QString AddressTableModel::labelForAddress(const QString &address) const
 {
-    CRITICAL_BLOCK(wallet->cs_wallet)
     {
+        LOCK(wallet->cs_wallet);
         CBitcoinAddress address_parsed(address.toStdString());
         std::map<CBitcoinAddress, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed);
         if (mi != wallet->mapAddressBook.end())
index 394e4a7..bfb49cb 100644 (file)
@@ -74,13 +74,13 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
     return payFee;
 }
 
-void ThreadSafeHandleURL(const std::string& strURL)
+void ThreadSafeHandleURI(const std::string& strURI)
 {
     if(!guiref)
         return;
 
-    QMetaObject::invokeMethod(guiref, "handleURL", GUIUtil::blockingGUIThreadConnection(),
-                               Q_ARG(QString, QString::fromStdString(strURL)));
+    QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(),
+                               Q_ARG(QString, QString::fromStdString(strURI)));
 }
 
 void MainFrameRepaint()
@@ -133,10 +133,10 @@ int main(int argc, char *argv[])
     {
         if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
         {
-            const char *strURL = argv[i];
+            const char *strURI = argv[i];
             try {
-                boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
-                if(mq.try_send(strURL, strlen(strURL), 0))
+                boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
+                if(mq.try_send(strURI, strlen(strURI), 0))
                     exit(0);
                 else
                     break;
@@ -248,21 +248,21 @@ int main(int argc, char *argv[])
                     window.show();
                 }
 
-                // Place this here as guiref has to be defined if we dont want to lose URLs
+                // Place this here as guiref has to be defined if we dont want to lose URIs
                 ipcInit();
 
 #if !defined(MAC_OSX) && !defined(WIN32)
 // TODO: implement qtipcserver.cpp for Mac and Windows
 
-                // Check for URL in argv
+                // Check for URI in argv
                 for (int i = 1; i < argc; i++)
                 {
                     if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
                     {
-                        const char *strURL = argv[i];
+                        const char *strURI = argv[i];
                         try {
-                            boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
-                            mq.try_send(strURL, strlen(strURL), 0);
+                            boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
+                            mq.try_send(strURI, strlen(strURI), 0);
                         }
                         catch (boost::interprocess::interprocess_exception &ex) {
                         }
index a60b585..70a3313 100644 (file)
@@ -715,7 +715,7 @@ void BitcoinGUI::gotoMessagePage(QString addr)
 
 void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
 {
-    // Accept only URLs
+    // Accept only URIs
     if(event->mimeData()->hasUrls())
         event->acceptProposedAction();
 }
@@ -725,20 +725,20 @@ void BitcoinGUI::dropEvent(QDropEvent *event)
     if(event->mimeData()->hasUrls())
     {
         gotoSendCoinsPage();
-        QList<QUrl> urls = event->mimeData()->urls();
-        foreach(const QUrl &url, urls)
+        QList<QUrl> uris = event->mimeData()->urls();
+        foreach(const QUrl &uri, uris)
         {
-            sendCoinsPage->handleURL(url.toString());
+            sendCoinsPage->handleURI(uri.toString());
         }
     }
 
     event->acceptProposedAction();
 }
 
-void BitcoinGUI::handleURL(QString strURL)
+void BitcoinGUI::handleURI(QString strURI)
 {
     gotoSendCoinsPage();
-    sendCoinsPage->handleURL(strURL);
+    sendCoinsPage->handleURI(strURI);
 
     if(!isActiveWindow())
         activateWindow();
index c684d7c..46e0fb1 100644 (file)
@@ -125,7 +125,7 @@ public slots:
       @param[out] payFee            true to pay the fee, false to not pay the fee
     */
     void askFee(qint64 nFeeRequired, bool *payFee);
-    void handleURL(QString strURL);
+    void handleURI(QString strURI);
 
     void gotoMessagePage();
     void gotoMessagePage(QString);
index 131e15b..8bd6d8b 100644 (file)
@@ -35,7 +35,7 @@
      <item>
       <widget class="QValidatedLineEdit" name="signFrom">
        <property name="toolTip">
-        <string>The address to send the payment to  (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
+        <string>The address to sign the message with  (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
        </property>
        <property name="maxLength">
         <number>34</number>
index ad530a7..2a3063b 100644 (file)
@@ -52,15 +52,15 @@ void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent)
     widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
 }
 
-bool GUIUtil::parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out)
+bool GUIUtil::parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
 {
-    if(url.scheme() != QString("bitcoin"))
+    if(uri.scheme() != QString("bitcoin"))
         return false;
 
     SendCoinsRecipient rv;
-    rv.address = url.path();
+    rv.address = uri.path();
     rv.amount = 0;
-    QList<QPair<QString, QString> > items = url.queryItems();
+    QList<QPair<QString, QString> > items = uri.queryItems();
     for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
     {
         bool fShouldReturnFalse = false;
@@ -97,18 +97,18 @@ bool GUIUtil::parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out)
     return true;
 }
 
-bool GUIUtil::parseBitcoinURL(QString url, SendCoinsRecipient *out)
+bool GUIUtil::parseBitcoinURI(QString uri, SendCoinsRecipient *out)
 {
     // Convert bitcoin:// to bitcoin:
     //
     //    Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host,
     //    which will lowercase it (and thus invalidate the address).
-    if(url.startsWith("bitcoin://"))
+    if(uri.startsWith("bitcoin://"))
     {
-        url.replace(0, 10, "bitcoin:");
+        uri.replace(0, 10, "bitcoin:");
     }
-    QUrl urlInstance(url);
-    return parseBitcoinURL(urlInstance, out);
+    QUrl uriInstance(uri);
+    return parseBitcoinURI(uriInstance, out);
 }
 
 QString GUIUtil::HtmlEscape(const QString& str, bool fMultiLine)
index 06426d7..3b5bc38 100644 (file)
@@ -29,10 +29,10 @@ public:
     static void setupAddressWidget(QLineEdit *widget, QWidget *parent);
     static void setupAmountWidget(QLineEdit *widget, QWidget *parent);
 
-    // Parse "bitcoin:" URL into recipient object, return true on succesful parsing
-    // See Bitcoin URL definition discussion here: https://bitcointalk.org/index.php?topic=33490.0
-    static bool parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out);
-    static bool parseBitcoinURL(QString url, SendCoinsRecipient *out);
+    // Parse "bitcoin:" URI into recipient object, return true on succesful parsing
+    // See Bitcoin URI definition discussion here: https://bitcointalk.org/index.php?topic=33490.0
+    static bool parseBitcoinURI(const QUrl &, SendCoinsRecipient *out);
+    static bool parseBitcoinURI(QString uri, SendCoinsRecipient *out);
 
     // HTML escaping for rich text controls
     static QString HtmlEscape(const QString& str, bool fMultiLine=false);
index 8b9270e..3c7889c 100644 (file)
@@ -8,6 +8,7 @@
 #include <boost/date_time/posix_time/posix_time.hpp>
 
 #include "headers.h"
+#include "qtipcserver.h"
 
 using namespace boost::interprocess;
 using namespace boost::posix_time;
@@ -16,7 +17,7 @@ using namespace std;
 
 void ipcShutdown()
 {
-    message_queue::remove("BitcoinURL");
+    message_queue::remove(BITCOINURI_QUEUE_NAME);
 }
 
 void ipcThread(void* parg)
@@ -30,7 +31,7 @@ void ipcThread(void* parg)
         ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
         if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
         {
-            ThreadSafeHandleURL(std::string(strBuf, nSize));
+            ThreadSafeHandleURI(std::string(strBuf, nSize));
             Sleep(1000);
         }
         if (fShutdown)
@@ -60,7 +61,7 @@ void ipcInit()
     size_t nSize;
     unsigned int nPriority;
     try {
-        mq = new message_queue(open_or_create, "BitcoinURL", 2, 256);
+        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
 
         // Make sure we don't lose any bitcoin: URIs
         for (int i = 0; i < 2; i++)
@@ -68,15 +69,15 @@ void ipcInit()
             ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
             if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
             {
-                ThreadSafeHandleURL(std::string(strBuf, nSize));
+                ThreadSafeHandleURI(std::string(strBuf, nSize));
             }
             else
                 break;
         }
 
         // Make sure only one bitcoin instance is listening
-        message_queue::remove("BitcoinURL");
-        mq = new message_queue(open_or_create, "BitcoinURL", 2, 256);
+        message_queue::remove(BITCOINURI_QUEUE_NAME);
+        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
     }
     catch (interprocess_exception &ex) {
         return;
index 1de0334..fcff10d 100644 (file)
@@ -1,2 +1,4 @@
+#define BITCOINURI_QUEUE_NAME "BitcoinURI"
+
 void ipcInit();
 void ipcShutdown();
index 964313e..592ae6f 100644 (file)
@@ -265,10 +265,10 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
 }
 
 
-void SendCoinsDialog::handleURL(const QString &url)
+void SendCoinsDialog::handleURI(const QString &uri)
 {
     SendCoinsRecipient rv;
-    if(!GUIUtil::parseBitcoinURL(url, &rv))
+    if(!GUIUtil::parseBitcoinURI(uri, &rv))
     {
         return;
     }
index 4dc3f08..5dcbfbe 100644 (file)
@@ -30,7 +30,7 @@ public:
     QWidget *setupTabChain(QWidget *prev);
 
     void pasteEntry(const SendCoinsRecipient &rv);
-    void handleURL(const QString &url);
+    void handleURI(const QString &uri);
 
 public slots:
     void clear();
index 0a08eaf..5b11e39 100644 (file)
@@ -1,11 +1,11 @@
 #include <QTest>\r
 #include <QObject>\r
 \r
-#include "urltests.h"\r
+#include "uritests.h"\r
 \r
 // This is all you need to run all the tests\r
 int main(int argc, char *argv[])\r
 {\r
-    URLTests test1;\r
+    URITests test1;\r
     QTest::qExec(&test1);\r
 }\r
similarity index 57%
rename from src/qt/test/urltests.cpp
rename to src/qt/test/uritests.cpp
index 1f11795..70c20be 100644 (file)
@@ -1,4 +1,4 @@
-#include "urltests.h"
+#include "uritests.h"
 #include "../guiutil.h"
 #include "../walletmodel.h"
 
@@ -13,59 +13,59 @@ struct SendCoinsRecipient
 };
 */
 
-void URLTests::urlTests()
+void URITests::uriTests()
 {
     SendCoinsRecipient rv;
-    QUrl url;
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
-    QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
+    QUrl uri;
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
+    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
 
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
-    QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
+    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
     QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
     QVERIFY(rv.label == QString());
     QVERIFY(rv.amount == 0);
 
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
-    QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
+    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
     QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
     QVERIFY(rv.label == QString("Wikipedia Example Address"));
     QVERIFY(rv.amount == 0);
 
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
-    QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
+    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
     QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
     QVERIFY(rv.label == QString());
     QVERIFY(rv.amount == 100000);
 
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
-    QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
+    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
     QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
     QVERIFY(rv.label == QString());
     QVERIFY(rv.amount == 100100000);
 
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
-    QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
+    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
     QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
     QVERIFY(rv.amount == 10000000000);
     QVERIFY(rv.label == QString("Wikipedia Example"));
 
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
-    QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
+    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
     QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
     QVERIFY(rv.label == QString());
 
-    QVERIFY(GUIUtil::parseBitcoinURL("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv));
+    QVERIFY(GUIUtil::parseBitcoinURI("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv));
     QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
     QVERIFY(rv.label == QString());
 
     // We currently dont implement the message paramenter (ok, yea, we break spec...)
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
-    QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
+    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
 
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
-    QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
+    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
 
-    url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
-    QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
+    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
+    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
 }
diff --git a/src/qt/test/uritests.h b/src/qt/test/uritests.h
new file mode 100644 (file)
index 0000000..1237516
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef URITESTS_H
+#define URITESTS_H
+
+#include <QTest>
+#include <QObject>
+
+class URITests : public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void uriTests();
+};
+
+#endif // URITESTS_H
diff --git a/src/qt/test/urltests.h b/src/qt/test/urltests.h
deleted file mode 100644 (file)
index 393c511..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef URLTESTS_H
-#define URLTESTS_H
-
-#include <QTest>
-#include <QObject>
-
-class URLTests : public QObject
-{
-    Q_OBJECT
-
-private slots:
-    void urlTests();
-};
-
-#endif // URLTESTS_H
index c32a006..dd7dd61 100644 (file)
@@ -34,8 +34,9 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
 {
     QString strHTML;
-    CRITICAL_BLOCK(wallet->cs_wallet)
+
     {
+        LOCK(wallet->cs_wallet);
         strHTML.reserve(4000);
         strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
 
@@ -243,8 +244,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
 
             strHTML += "<br><b>Inputs:</b>";
             strHTML += "<ul>";
-            CRITICAL_BLOCK(wallet->cs_wallet)
+
             {
+                LOCK(wallet->cs_wallet);
                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
                 {
                     COutPoint prevout = txin.prevout;
index 480d4ac..aa11df9 100644 (file)
@@ -69,8 +69,8 @@ struct TransactionTablePriv
         qDebug() << "refreshWallet";
 #endif
         cachedWallet.clear();
-        CRITICAL_BLOCK(wallet->cs_wallet)
         {
+            LOCK(wallet->cs_wallet);
             for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it)
             {
                 cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second));
@@ -95,8 +95,8 @@ struct TransactionTablePriv
         QList<uint256> updated_sorted = updated;
         qSort(updated_sorted);
 
-        CRITICAL_BLOCK(wallet->cs_wallet)
         {
+            LOCK(wallet->cs_wallet);
             for(int update_idx = updated_sorted.size()-1; update_idx >= 0; --update_idx)
             {
                 const uint256 &hash = updated_sorted.at(update_idx);
@@ -171,8 +171,8 @@ struct TransactionTablePriv
             // simply re-use the cached status.
             if(rec->statusUpdateNeeded())
             {
-                CRITICAL_BLOCK(wallet->cs_wallet)
                 {
+                    LOCK(wallet->cs_wallet);
                     std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
 
                     if(mi != wallet->mapWallet.end())
@@ -191,8 +191,8 @@ struct TransactionTablePriv
 
     QString describe(TransactionRecord *rec)
     {
-        CRITICAL_BLOCK(wallet->cs_wallet)
         {
+            LOCK(wallet->cs_wallet);
             std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
             if(mi != wallet->mapWallet.end())
             {
@@ -229,9 +229,9 @@ void TransactionTableModel::update()
     QList<uint256> updated;
 
     // Check if there are changes to wallet map
-    TRY_CRITICAL_BLOCK(wallet->cs_wallet)
     {
-        if(!wallet->vWalletUpdated.empty())
+        TRY_LOCK(wallet->cs_wallet, lockWallet);
+        if (lockWallet && !wallet->vWalletUpdated.empty())
         {
             BOOST_FOREACH(uint256 hash, wallet->vWalletUpdated)
             {
index 6cc0237..9c28a8a 100644 (file)
@@ -32,8 +32,8 @@ qint64 WalletModel::getUnconfirmedBalance() const
 int WalletModel::getNumTransactions() const
 {
     int numTransactions = 0;
-    CRITICAL_BLOCK(wallet->cs_wallet)
     {
+        LOCK(wallet->cs_wallet);
         numTransactions = wallet->mapWallet.size();
     }
     return numTransactions;
@@ -115,9 +115,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
         return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee);
     }
 
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(wallet->cs_wallet)
     {
+        LOCK2(cs_main, wallet->cs_wallet);
+
         // Sendmany
         std::vector<std::pair<CScript, int64> > vecSend;
         foreach(const SendCoinsRecipient &rcp, recipients)
@@ -155,8 +155,8 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
     foreach(const SendCoinsRecipient &rcp, recipients)
     {
         std::string strAddress = rcp.address.toStdString();
-        CRITICAL_BLOCK(wallet->cs_wallet)
         {
+            LOCK(wallet->cs_wallet);
             if (!wallet->mapAddressBook.count(strAddress))
                 wallet->SetAddressBookName(strAddress, rcp.label.toStdString());
         }
@@ -227,8 +227,8 @@ bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
 bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
 {
     bool retval;
-    CRITICAL_BLOCK(wallet->cs_wallet)
     {
+        LOCK(wallet->cs_wallet);
         wallet->Lock(); // Make sure wallet is locked before attempting pass change
         retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
     }
index 8180aad..5bb4789 100644 (file)
@@ -60,9 +60,9 @@ Value importprivkey(const Array& params, bool fHelp)
     key.SetSecret(secret, fCompressed);
     CBitcoinAddress vchAddress = CBitcoinAddress(key.GetPubKey());
 
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(pwalletMain->cs_wallet)
     {
+        LOCK2(cs_main, pwalletMain->cs_wallet);
+
         pwalletMain->MarkDirty();
         pwalletMain->SetAddressBookName(vchAddress, strLabel);
 
index 94c0c77..db31f49 100644 (file)
@@ -15,14 +15,15 @@ BOOST_AUTO_TEST_CASE(util_criticalsection)
     CCriticalSection cs;
 
     do {
-        CRITICAL_BLOCK(cs)
-            break;
+        LOCK(cs);
+        break;
 
         BOOST_ERROR("break was swallowed!");
     } while(0);
 
     do {
-        TRY_CRITICAL_BLOCK(cs)
+        TRY_LOCK(cs, lockTest);
+        if (lockTest)
             break;
 
         BOOST_ERROR("break was swallowed!");
index 2e29f2a..5147680 100644 (file)
@@ -40,7 +40,7 @@
 
 extern int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style=wxOK);
 extern bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption);
-extern void ThreadSafeHandleURL(const std::string& strURL);
+extern void ThreadSafeHandleURI(const std::string& strURI);
 extern void MainFrameRepaint();
 extern void AddressBookRepaint();
 extern void QueueShutdown();
index 5c47551..19538a4 100644 (file)
@@ -2,6 +2,7 @@
 // Copyright (c) 2009-2012 The Bitcoin developers
 // Distributed under the MIT/X11 software license, see the accompanying
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
 #include "headers.h"
 #include "strlcpy.h"
 #include <boost/algorithm/string/join.hpp>
@@ -195,8 +196,8 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
         static CCriticalSection cs_OutputDebugStringF;
 
         // accumulate a line at a time
-        CRITICAL_BLOCK(cs_OutputDebugStringF)
         {
+            LOCK(cs_OutputDebugStringF);
             static char pszBuffer[50000];
             static char* pend;
             if (pend == NULL)
@@ -858,10 +859,11 @@ string GetDataDir()
 string GetConfigFile()
 {
     namespace fs = boost::filesystem;
-    fs::path pathConfig(GetArg("-conf", "bitcoin.conf"));
-    if (!pathConfig.is_complete())
-        pathConfig = fs::path(GetDataDir()) / pathConfig;
-    return pathConfig.string();
+
+    fs::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
+    if (!pathConfigFile.is_complete()) pathConfigFile = fs::path(GetDataDir()) / pathConfigFile;
+    pathConfigFile.make_preferred();
+    return pathConfigFile.string();
 }
 
 bool ReadConfigFile(map<string, string>& mapSettingsRet,
@@ -874,7 +876,9 @@ bool ReadConfigFile(map<string, string>& mapSettingsRet,
     {
         if (fs::is_directory(fs::system_complete(mapSettingsRet["-datadir"])))
         {
-            fs::path pathDataDir = fs::system_complete(mapSettingsRet["-datadir"]);
+            fs::path pathDataDir(fs::system_complete(mapSettingsRet["-datadir"]));
+            pathDataDir.make_preferred();
+
             strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
         }
         else
@@ -908,10 +912,11 @@ bool ReadConfigFile(map<string, string>& mapSettingsRet,
 string GetPidFile()
 {
     namespace fs = boost::filesystem;
-    fs::path pathConfig(GetArg("-pid", "bitcoind.pid"));
-    if (!pathConfig.is_complete())
-        pathConfig = fs::path(GetDataDir()) / pathConfig;
-    return pathConfig.string();
+
+    fs::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
+    if (!pathPidFile.is_complete()) pathPidFile = fs::path(GetDataDir()) / pathPidFile;
+    pathPidFile.make_preferred();
+    return pathPidFile.string();
 }
 
 void CreatePidFile(string pidFile, pid_t pid)
@@ -1115,25 +1120,25 @@ private:
     int sourceLine;
 };
 
-typedef std::vector< std::pair<CCriticalSection*, CLockLocation> > LockStack;
+typedef std::vector< std::pair<void*, CLockLocation> > LockStack;
 
 static boost::interprocess::interprocess_mutex dd_mutex;
-static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lockorders;
+static std::map<std::pair<void*, void*>, LockStack> lockorders;
 static boost::thread_specific_ptr<LockStack> lockstack;
 
 
-static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCriticalSection*>& mismatch, const LockStack& s1, const LockStack& s2)
+static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
 {
     printf("POTENTIAL DEADLOCK DETECTED\n");
     printf("Previous lock order was:\n");
-    BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2)
+    BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2)
     {
         if (i.first == mismatch.first) printf(" (1)");
         if (i.first == mismatch.second) printf(" (2)");
         printf(" %s\n", i.second.ToString().c_str());
     }
     printf("Current lock order is:\n");
-    BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1)
+    BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1)
     {
         if (i.first == mismatch.first) printf(" (1)");
         if (i.first == mismatch.second) printf(" (2)");
@@ -1141,7 +1146,7 @@ static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCrit
     }
 }
 
-static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
+static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
 {
     bool fOrderOK = true;
     if (lockstack.get() == NULL)
@@ -1152,16 +1157,16 @@ static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
 
     (*lockstack).push_back(std::make_pair(c, locklocation));
 
-    BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, (*lockstack))
+    if (!fTry) BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack))
     {
         if (i.first == c) break;
 
-        std::pair<CCriticalSection*, CCriticalSection*> p1 = std::make_pair(i.first, c);
+        std::pair<void*, void*> p1 = std::make_pair(i.first, c);
         if (lockorders.count(p1))
             continue;
         lockorders[p1] = (*lockstack);
 
-        std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first);
+        std::pair<void*, void*> p2 = std::make_pair(c, i.first);
         if (lockorders.count(p2))
         {
             potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
@@ -1183,62 +1188,14 @@ static void pop_lock()
     dd_mutex.unlock();
 }
 
-void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine)
-{
-    push_lock(this, CLockLocation(pszName, pszFile, nLine));
-#ifdef DEBUG_LOCKCONTENTION
-    bool result = mutex.try_lock();
-    if (!result)
-    {
-        printf("LOCKCONTENTION: %s\n", pszName);
-        printf("Locker: %s:%d\n", pszFile, nLine);
-        mutex.lock();
-        printf("Locked\n");
-    }
-#else
-    mutex.lock();
-#endif
-}
-void CCriticalSection::Leave()
+void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
 {
-    mutex.unlock();
-    pop_lock();
-}
-bool CCriticalSection::TryEnter(const char* pszName, const char* pszFile, int nLine)
-{
-    push_lock(this, CLockLocation(pszName, pszFile, nLine));
-    bool result = mutex.try_lock();
-    if (!result) pop_lock();
-    return result;
+    push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
 }
 
-#else
-
-void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine)
+void LeaveCritical()
 {
-#ifdef DEBUG_LOCKCONTENTION
-    bool result = mutex.try_lock();
-    if (!result)
-    {
-        printf("LOCKCONTENTION: %s\n", pszName);
-        printf("Locker: %s:%d\n", pszFile, nLine);
-        mutex.lock();
-    }
-#else
-    mutex.lock();
-#endif
-}
-
-void CCriticalSection::Leave()
-{
-    mutex.unlock();
-}
-
-bool CCriticalSection::TryEnter(const char*, const char*, int)
-{
-    bool result = mutex.try_lock();
-    return result;
+    pop_lock();
 }
 
 #endif /* DEBUG_LOCKORDER */
-
index e4cf83f..a04ab2c 100644 (file)
@@ -20,6 +20,9 @@ typedef int pid_t; /* define for windows compatiblity */
 
 #include <boost/thread.hpp>
 #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/sync/interprocess_condition.hpp>
+#include <boost/interprocess/sync/lock_options.hpp>
 #include <boost/date_time/gregorian/gregorian_types.hpp>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 
@@ -180,82 +183,127 @@ void AddTimeData(const CNetAddr& ip, int64 nTime);
 
 
 
+/** Wrapped boost mutex: supports recursive locking, but no waiting  */
+typedef boost::interprocess::interprocess_recursive_mutex CCriticalSection;
 
-/** Wrapper to automatically initialize mutex. */
-class CCriticalSection
-{
-protected:
-    boost::interprocess::interprocess_recursive_mutex mutex;
-public:
-    explicit CCriticalSection() { }
-    ~CCriticalSection() { }
-    void Enter(const char* pszName, const char* pszFile, int nLine);
-    void Leave();
-    bool TryEnter(const char* pszName, const char* pszFile, int nLine);
-};
+/** Wrapped boost mutex: supports waiting but not recursive locking */
+typedef boost::interprocess::interprocess_mutex CWaitableCriticalSection;
 
-/** RAII object that acquires mutex. Needed for exception safety. */
-class CCriticalBlock
-{
-protected:
-    CCriticalSection* pcs;
+#ifdef DEBUG_LOCKORDER
+void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
+void LeaveCritical();
+#else
+void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
+void static inline LeaveCritical() {}
+#endif
 
+/** Wrapper around boost::interprocess::scoped_lock */
+template<typename Mutex>
+class CMutexLock
+{
+private:
+    boost::interprocess::scoped_lock<Mutex> lock;
 public:
-    CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine)
+
+    void Enter(const char* pszName, const char* pszFile, int nLine)
     {
-        pcs = &csIn;
-        pcs->Enter(pszName, pszFile, nLine);
+        if (!lock.owns())
+        {
+            EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
+#ifdef DEBUG_LOCKCONTENTION
+            if (!lock.try_lock())
+            {
+                printf("LOCKCONTENTION: %s\n", pszName);
+                printf("Locker: %s:%d\n", pszFile, nLine);
+            }
+#endif
+            lock.lock();
+        }
     }
 
-    operator bool() const
+    void Leave()
     {
-        return true;
+        if (lock.owns())
+        {
+            lock.unlock();
+            LeaveCritical();
+        }
     }
 
-    ~CCriticalBlock()
+    bool TryEnter(const char* pszName, const char* pszFile, int nLine)
     {
-        pcs->Leave();
+        if (!lock.owns())
+        {
+            EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
+            lock.try_lock();
+            if (!lock.owns())
+                LeaveCritical();
+        }
+        return lock.owns();
     }
-};
-
-#define CRITICAL_BLOCK(cs)     \
-    if (CCriticalBlock criticalblock = CCriticalBlock(cs, #cs, __FILE__, __LINE__))
-
-#define ENTER_CRITICAL_SECTION(cs) \
-    (cs).Enter(#cs, __FILE__, __LINE__)
 
-#define LEAVE_CRITICAL_SECTION(cs) \
-    (cs).Leave()
-
-/** RAII object that tries to acquire mutex. Needed for exception safety. */
-class CTryCriticalBlock
-{
-protected:
-    CCriticalSection* pcs;
+    CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::interprocess::defer_lock)
+    {
+        if (fTry)
+            TryEnter(pszName, pszFile, nLine);
+        else
+            Enter(pszName, pszFile, nLine);
+    }
 
-public:
-    CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine)
+    ~CMutexLock()
     {
-        pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL);
+        if (lock.owns())
+            LeaveCritical();
     }
 
-    operator bool() const
+    operator bool()
     {
-        return Entered();
+        return lock.owns();
     }
 
-    ~CTryCriticalBlock()
+    boost::interprocess::scoped_lock<Mutex> &GetLock()
     {
-        if (pcs)
-        {
-            pcs->Leave();
-        }
+        return lock;
     }
-    bool Entered() const { return pcs != NULL; }
 };
 
-#define TRY_CRITICAL_BLOCK(cs)     \
-    if (CTryCriticalBlock criticalblock = CTryCriticalBlock(cs, #cs, __FILE__, __LINE__))
+typedef CMutexLock<CCriticalSection> CCriticalBlock;
+typedef CMutexLock<CWaitableCriticalSection> CWaitableCriticalBlock;
+typedef boost::interprocess::interprocess_condition CConditionVariable;
+
+/** Wait for a given condition inside a WAITABLE_CRITICAL_BLOCK */
+#define WAIT(name,condition) \
+   do { while(!(condition)) { (name).wait(waitablecriticalblock.GetLock()); } } while(0)
+
+/** Notify waiting threads that a condition may hold now */
+#define NOTIFY(name) \
+   do { (name).notify_one(); } while(0)
+
+#define NOTIFY_ALL(name) \
+   do { (name).notify_all(); } while(0)
+
+#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
+#define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__)
+#define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
+#define WAITABLE_LOCK(cs) CWaitableCriticalBlock waitablecriticalblock(cs, #cs, __FILE__, __LINE__)
+
+#define ENTER_CRITICAL_SECTION(cs) \
+    { \
+        EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
+        (cs).lock(); \
+    }
+
+#define LEAVE_CRITICAL_SECTION(cs) \
+    { \
+        (cs).unlock(); \
+        LeaveCritical(); \
+    }
+
+
+// This is exactly like std::string, but with a custom allocator.
+// (secure_allocator<> is defined in serialize.h)
+typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
+
 
 
 
index e444e5f..97ed6aa 100644 (file)
@@ -49,8 +49,8 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector
         return false;
     if (!fFileBacked)
         return true;
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         if (pwalletdbEncryption)
             return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
         else
@@ -76,7 +76,8 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
     CCrypter crypter;
     CKeyingMaterial vMasterKey;
 
-    CRITICAL_BLOCK(cs_wallet)
+    {
+        LOCK(cs_wallet);
         BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
         {
             if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
@@ -86,6 +87,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
             if (CCryptoKeyStore::Unlock(vMasterKey))
                 return true;
         }
+    }
     return false;
 }
 
@@ -93,8 +95,8 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
 {
     bool fWasLocked = IsLocked();
 
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         Lock();
 
         CCrypter crypter;
@@ -228,8 +230,8 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
     if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
         return false;
 
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
         if (fFileBacked)
         {
@@ -275,8 +277,8 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
     // Anytime a signature is successfully verified, it's proof the outpoint is spent.
     // Update the wallet spent flag if it doesn't know due to wallet.dat being
     // restored from backup or the user making copies of wallet.dat.
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         BOOST_FOREACH(const CTxIn& txin, tx.vin)
         {
             map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
@@ -297,8 +299,8 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
 
 void CWallet::MarkDirty()
 {
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
             item.second.MarkDirty();
     }
@@ -307,8 +309,8 @@ void CWallet::MarkDirty()
 bool CWallet::AddToWallet(const CWalletTx& wtxIn)
 {
     uint256 hash = wtxIn.GetHash();
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         // Inserts only if not already there, returns tx inserted or tx found
         pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
         CWalletTx& wtx = (*ret.first).second;
@@ -382,8 +384,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
 {
     uint256 hash = tx.GetHash();
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         bool fExisted = mapWallet.count(hash);
         if (fExisted && !fUpdate) return false;
         if (fExisted || IsMine(tx) || IsFromMe(tx))
@@ -404,8 +406,8 @@ bool CWallet::EraseFromWallet(uint256 hash)
 {
     if (!fFileBacked)
         return false;
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         if (mapWallet.erase(hash))
             CWalletDB(strWalletFile).EraseTx(hash);
     }
@@ -415,8 +417,8 @@ bool CWallet::EraseFromWallet(uint256 hash)
 
 bool CWallet::IsMine(const CTxIn &txin) const
 {
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
         if (mi != mapWallet.end())
         {
@@ -431,8 +433,8 @@ bool CWallet::IsMine(const CTxIn &txin) const
 
 int64 CWallet::GetDebit(const CTxIn &txin) const
 {
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
         if (mi != mapWallet.end())
         {
@@ -457,9 +459,11 @@ bool CWallet::IsChange(const CTxOut& txout) const
     // 'the change' will need to be implemented (maybe extend CWalletTx to remember
     // which output, if any, was change).
     if (ExtractAddress(txout.scriptPubKey, address) && HaveKey(address))
-        CRITICAL_BLOCK(cs_wallet)
-            if (!mapAddressBook.count(address))
-                return true;
+    {
+        LOCK(cs_wallet);
+        if (!mapAddressBook.count(address))
+            return true;
+    }
     return false;
 }
 
@@ -472,8 +476,8 @@ int CWalletTx::GetRequestCount() const
 {
     // Returns -1 if it wasn't being tracked
     int nRequests = -1;
-    CRITICAL_BLOCK(pwallet->cs_wallet)
     {
+        LOCK(pwallet->cs_wallet);
         if (IsCoinBase())
         {
             // Generated block
@@ -577,8 +581,8 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, i
             nSent += s.second;
         nFee = allFee;
     }
-    CRITICAL_BLOCK(pwallet->cs_wallet)
     {
+        LOCK(pwallet->cs_wallet);
         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
         {
             if (pwallet->mapAddressBook.count(r.first))
@@ -607,8 +611,8 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
             vWorkQueue.push_back(txin.prevout.hash);
 
         // This critsect is OK because txdb is already open
-        CRITICAL_BLOCK(pwallet->cs_wallet)
         {
+            LOCK(pwallet->cs_wallet);
             map<uint256, const CMerkleTx*> mapWalletPrev;
             set<uint256> setAlreadyDone;
             for (int i = 0; i < vWorkQueue.size(); i++)
@@ -666,8 +670,8 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
     int ret = 0;
 
     CBlockIndex* pindex = pindexStart;
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         while (pindex)
         {
             CBlock block;
@@ -696,8 +700,9 @@ void CWallet::ReacceptWalletTransactions()
 {
     CTxDB txdb("r");
     bool fRepeat = true;
-    while (fRepeat) CRITICAL_BLOCK(cs_wallet)
+    while (fRepeat)
     {
+        LOCK(cs_wallet);
         fRepeat = false;
         vector<CDiskTxPos> vMissingTx;
         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
@@ -799,8 +804,8 @@ void CWallet::ResendWalletTransactions()
     // Rebroadcast any of our txes that aren't in a block yet
     printf("ResendWalletTransactions()\n");
     CTxDB txdb("r");
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         // Sort them in chronological order
         multimap<unsigned int, CWalletTx*> mapSorted;
         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
@@ -833,8 +838,8 @@ void CWallet::ResendWalletTransactions()
 int64 CWallet::GetBalance() const
 {
     int64 nTotal = 0;
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
         {
             const CWalletTx* pcoin = &(*it).second;
@@ -850,8 +855,8 @@ int64 CWallet::GetBalance() const
 int64 CWallet::GetUnconfirmedBalance() const
 {
     int64 nTotal = 0;
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
         {
             const CWalletTx* pcoin = &(*it).second;
@@ -875,8 +880,8 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfThe
     vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
     int64 nTotalLower = 0;
 
-    CRITICAL_BLOCK(cs_wallet)
     {
+       LOCK(cs_wallet);
        vector<const CWalletTx*> vCoins;
        vCoins.reserve(mapWallet.size());
        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
@@ -1032,9 +1037,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
 
     wtxNew.BindWallet(this);
 
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK2(cs_main, cs_wallet);
         // txdb must be opened before the mapWallet lock
         CTxDB txdb("r");
         {
@@ -1146,9 +1150,8 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w
 // Call after CreateTransaction unless you want to abort
 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
 {
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK2(cs_main, cs_wallet);
         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
         {
             // This is only to keep the database open to defeat the auto-flush for the
@@ -1297,8 +1300,8 @@ bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
 
 void CWallet::PrintWallet(const CBlock& block)
 {
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         if (mapWallet.count(block.vtx[0].GetHash()))
         {
             CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
@@ -1310,8 +1313,8 @@ void CWallet::PrintWallet(const CBlock& block)
 
 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
 {
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
         if (mi != mapWallet.end())
         {
@@ -1347,8 +1350,8 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
 //
 bool CWallet::NewKeyPool()
 {
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         CWalletDB walletdb(strWalletFile);
         BOOST_FOREACH(int64 nIndex, setKeyPool)
             walletdb.ErasePool(nIndex);
@@ -1371,8 +1374,9 @@ bool CWallet::NewKeyPool()
 
 bool CWallet::TopUpKeyPool()
 {
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
+
         if (IsLocked())
             return false;
 
@@ -1398,8 +1402,9 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
 {
     nIndex = -1;
     keypool.vchPubKey.clear();
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
+
         if (!IsLocked())
             TopUpKeyPool();
 
@@ -1422,9 +1427,8 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
 
 int64 CWallet::AddReserveKey(const CKeyPool& keypool)
 {
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK2(cs_main, cs_wallet);
         CWalletDB walletdb(strWalletFile);
 
         int64 nIndex = 1 + *(--setKeyPool.end());
@@ -1450,8 +1454,10 @@ void CWallet::KeepKey(int64 nIndex)
 void CWallet::ReturnKey(int64 nIndex)
 {
     // Return to key pool
-    CRITICAL_BLOCK(cs_wallet)
+    {
+        LOCK(cs_wallet);
         setKeyPool.insert(nIndex);
+    }
     printf("keypool return %"PRI64d"\n", nIndex);
 }
 
@@ -1459,8 +1465,8 @@ bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
 {
     int64 nIndex = 0;
     CKeyPool keypool;
-    CRITICAL_BLOCK(cs_wallet)
     {
+        LOCK(cs_wallet);
         ReserveKeyFromKeyPool(nIndex, keypool);
         if (nIndex == -1)
         {
@@ -1530,8 +1536,7 @@ void CWallet::GetAllReserveAddresses(set<CBitcoinAddress>& setAddress)
 
     CWalletDB walletdb(strWalletFile);
 
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_wallet)
+    LOCK2(cs_main, cs_wallet);
     BOOST_FOREACH(const int64& id, setKeyPool)
     {
         CKeyPool keypool;
index e1065cf..f864370 100644 (file)
@@ -211,16 +211,18 @@ public:
 
     void UpdatedTransaction(const uint256 &hashTx)
     {
-        CRITICAL_BLOCK(cs_wallet)
+        {
+            LOCK(cs_wallet);
             vWalletUpdated.push_back(hashTx);
+        }
     }
 
     void PrintWallet(const CBlock& block);
 
     void Inventory(const uint256 &hash)
     {
-        CRITICAL_BLOCK(cs_wallet)
         {
+            LOCK(cs_wallet);
             std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
             if (mi != mapRequestCount.end())
                 (*mi).second++;