<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "wallet/init.h"

#include "net.h"
#include "util.h"
#include "utilmoneystr.h"
#include "validation.h"
#include "wallet/wallet.h"
#include "wallet/rpcwallet.h"

std::string GetWalletHelpString(bool showDebug)
{
    std::string strUsage = HelpMessageGroup(_("Wallet options:"));
    strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
    strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
    strUsage += HelpMessageOpt("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),
                                                               CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)));
    strUsage += HelpMessageOpt("-discardfee=<amt>", strprintf(_("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
                                                                "Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target"),
                                                              CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE)));
    strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
                                                            CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
    strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
                                                            CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
    strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions on startup"));
    strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet on startup"));
    strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
    strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
    strUsage += HelpMessageOpt("-walletrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (default: %u)"), DEFAULT_WALLET_RBF));
    strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup"));
    strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
    strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST));
    strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
    strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
                               " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));

    if (showDebug)
    {
        strUsage += HelpMessageGroup(_("Wallet debugging/testing options:"));

        strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
        strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET));
        strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB));
        strUsage += HelpMessageOpt("-walletrejectlongchains", strprintf(_("Wallet will not create transactions that violate mempool chain limits (default: %u)"), DEFAULT_WALLET_REJECT_LONG_CHAINS));
    }

    return strUsage;
}

bool WalletParameterInteraction()
{
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        for (const std::string& wallet : gArgs.GetArgs("-wallet")) {
            LogPrintf("%s: parameter interaction: -disablewallet -> ignoring -wallet=%s\n", __func__, wallet);
        }

        return true;
    }

    gArgs.SoftSetArg("-wallet", DEFAULT_WALLET_DAT);
    const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;

    if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
        LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
    }

    if (gArgs.GetBoolArg("-salvagewallet", false)) {
        if (is_multiwallet) {
            return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet"));
        }
        // Rewrite just private keys: rescan to find transactions
        if (gArgs.SoftSetBoolArg("-rescan", true)) {
            LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
        }
    }

    int zapwallettxes = gArgs.GetArg("-zapwallettxes", 0);
    // -zapwallettxes implies dropping the mempool on startup
    if (zapwallettxes != 0 && gArgs.SoftSetBoolArg("-persistmempool", false)) {
        LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -persistmempool=0\n", __func__, zapwallettxes);
    }

    // -zapwallettxes implies a rescan
    if (zapwallettxes != 0) {
        if (is_multiwallet) {
            return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
        }
        if (gArgs.SoftSetBoolArg("-rescan", true)) {
            LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -rescan=1\n", __func__, zapwallettxes);
        }
    }

    if (is_multiwallet) {
        if (gArgs.GetBoolArg("-upgradewallet", false)) {
            return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet"));
        }
    }

    if (gArgs.GetBoolArg("-sysperms", false))
        return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
    if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false))
        return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again."));

    if (::minRelayTxFee.GetFeePerK() > HIGH_TX_FEE_PER_KB)
        InitWarning(AmountHighWarn("-minrelaytxfee") + " " +
                    _("The wallet will avoid paying less than the minimum relay fee."));

    if (gArgs.IsArgSet("-mintxfee"))
    {
        CAmount n = 0;
        if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n)
            return InitError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
        if (n > HIGH_TX_FEE_PER_KB)
            InitWarning(AmountHighWarn("-mintxfee") + " " +
                        _("This is the minimum transaction fee you pay on every transaction."));
        CWallet::minTxFee = CFeeRate(n);
    }
    if (gArgs.IsArgSet("-fallbackfee"))
    {
        CAmount nFeePerK = 0;
        if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK))
            return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", "")));
        if (nFeePerK > HIGH_TX_FEE_PER_KB)
            InitWarning(AmountHighWarn("-fallbackfee") + " " +
                        _("This is the transaction fee you may pay when fee estimates are not available."));
        CWallet::fallbackFee = CFeeRate(nFeePerK);
    }
    if (gArgs.IsArgSet("-discardfee"))
    {
        CAmount nFeePerK = 0;
        if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK))
            return InitError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", "")));
        if (nFeePerK > HIGH_TX_FEE_PER_KB)
            InitWarning(AmountHighWarn("-discardfee") + " " +
                        _("This is the transaction fee you may discard if change is smaller than dust at this level"));
        CWallet::m_discard_rate = CFeeRate(nFeePerK);
    }
    if (gArgs.IsArgSet("-paytxfee"))
    {
        CAmount nFeePerK = 0;
        if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK))
            return InitError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
        if (nFeePerK > HIGH_TX_FEE_PER_KB)
            InitWarning(AmountHighWarn("-paytxfee") + " " +
                        _("This is the transaction fee you will pay if you send a transaction."));

        payTxFee = CFeeRate(nFeePerK, 1000);
        if (payTxFee < ::minRelayTxFee)
        {
            return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
                                       gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString()));
        }
    }
    if (gArgs.IsArgSet("-maxtxfee"))
    {
        CAmount nMaxFee = 0;
        if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee))
            return InitError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")));
        if (nMaxFee > HIGH_MAX_TX_FEE)
            InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
        maxTxFee = nMaxFee;
        if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
        {
            return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
                                       gArgs.GetArg("-maxtxfee", ""), ::minRelayTxFee.ToString()));
        }
    }
    nTxConfirmTarget = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
    bSpendZeroConfChange = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
    fWalletRbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);

    return true;
}

void RegisterWalletRPC(CRPCTable &t)
{
    if (gArgs.GetBoolArg("-disablewallet", false)) return;

    RegisterWalletRPCCommands(t);
}

bool VerifyWallets()
{
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET))
        return true;

    uiInterface.InitMessage(_("Verifying wallet(s)..."));

    // Keep track of each wallet absolute path to detect duplicates.
    std::set<fs::path> wallet_paths;

    for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
        if (boost::filesystem::path(walletFile).filename() != walletFile) {
            return InitError(strprintf(_("Error loading wallet %s. -wallet parameter must only specify a filename (not a path)."), walletFile));
        }

        if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) {
            return InitError(strprintf(_("Error loading wallet %s. Invalid characters in -wallet filename."), walletFile));
        }

        fs::path wallet_path = fs::absolute(walletFile, GetDataDir());

        if (fs::exists(wallet_path) && (!fs::is_regular_file(wallet_path) || fs::is_symlink(wallet_path))) {
            return InitError(strprintf(_("Error loading wallet %s. -wallet filename must be a regular file."), walletFile));
        }

        if (!wallet_paths.insert(wallet_path).second) {
            return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), walletFile));
        }

        std::string strError;
        if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) {
            return InitError(strError);
        }

        if (gArgs.GetBoolArg("-salvagewallet", false)) {
            // Recover readable keypairs:
            CWallet dummyWallet;
            std::string backup_filename;
            if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) {
                return false;
            }
        }

        std::string strWarning;
        bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError);
        if (!strWarning.empty()) {
            InitWarning(strWarning);
        }
        if (!dbV) {
            InitError(strError);
            return false;
        }
    }

    return true;
}

bool OpenWallets()
{
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        LogPrintf("Wallet disabled!\n");
        return true;
    }

    for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
        CWallet * const pwallet = CWallet::CreateWalletFromFile(walletFile);
        if (!pwallet) {
            return false;
        }
        vpwallets.push_back(pwallet);
    }

    return true;
}

void StartWallets(CScheduler& scheduler) {
    for (CWalletRef pwallet : vpwallets) {
        pwallet->postInitProcess(scheduler);
    }
}

void FlushWallets() {
    for (CWalletRef pwallet : vpwallets) {
        pwallet->Flush(false);
    }
}

void StopWallets() {
    for (CWalletRef pwallet : vpwallets) {
        pwallet->Flush(true);
    }
}

void CloseWallets() {
    for (CWalletRef pwallet : vpwallets) {
        delete pwallet;
    }
    vpwallets.clear();
}
<commit_msg>Fix -disablewallet default value<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "wallet/init.h"

#include "net.h"
#include "util.h"
#include "utilmoneystr.h"
#include "validation.h"
#include "wallet/wallet.h"
#include "wallet/rpcwallet.h"

std::string GetWalletHelpString(bool showDebug)
{
    std::string strUsage = HelpMessageGroup(_("Wallet options:"));
    strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
    strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
    strUsage += HelpMessageOpt("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),
                                                               CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)));
    strUsage += HelpMessageOpt("-discardfee=<amt>", strprintf(_("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
                                                                "Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target"),
                                                              CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE)));
    strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
                                                            CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
    strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
                                                            CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
    strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions on startup"));
    strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet on startup"));
    strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
    strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
    strUsage += HelpMessageOpt("-walletrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (default: %u)"), DEFAULT_WALLET_RBF));
    strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup"));
    strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
    strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST));
    strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
    strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
                               " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));

    if (showDebug)
    {
        strUsage += HelpMessageGroup(_("Wallet debugging/testing options:"));

        strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
        strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET));
        strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB));
        strUsage += HelpMessageOpt("-walletrejectlongchains", strprintf(_("Wallet will not create transactions that violate mempool chain limits (default: %u)"), DEFAULT_WALLET_REJECT_LONG_CHAINS));
    }

    return strUsage;
}

bool WalletParameterInteraction()
{
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        for (const std::string& wallet : gArgs.GetArgs("-wallet")) {
            LogPrintf("%s: parameter interaction: -disablewallet -> ignoring -wallet=%s\n", __func__, wallet);
        }

        return true;
    }

    gArgs.SoftSetArg("-wallet", DEFAULT_WALLET_DAT);
    const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;

    if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
        LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
    }

    if (gArgs.GetBoolArg("-salvagewallet", false)) {
        if (is_multiwallet) {
            return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet"));
        }
        // Rewrite just private keys: rescan to find transactions
        if (gArgs.SoftSetBoolArg("-rescan", true)) {
            LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
        }
    }

    int zapwallettxes = gArgs.GetArg("-zapwallettxes", 0);
    // -zapwallettxes implies dropping the mempool on startup
    if (zapwallettxes != 0 && gArgs.SoftSetBoolArg("-persistmempool", false)) {
        LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -persistmempool=0\n", __func__, zapwallettxes);
    }

    // -zapwallettxes implies a rescan
    if (zapwallettxes != 0) {
        if (is_multiwallet) {
            return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
        }
        if (gArgs.SoftSetBoolArg("-rescan", true)) {
            LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -rescan=1\n", __func__, zapwallettxes);
        }
    }

    if (is_multiwallet) {
        if (gArgs.GetBoolArg("-upgradewallet", false)) {
            return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet"));
        }
    }

    if (gArgs.GetBoolArg("-sysperms", false))
        return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
    if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false))
        return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again."));

    if (::minRelayTxFee.GetFeePerK() > HIGH_TX_FEE_PER_KB)
        InitWarning(AmountHighWarn("-minrelaytxfee") + " " +
                    _("The wallet will avoid paying less than the minimum relay fee."));

    if (gArgs.IsArgSet("-mintxfee"))
    {
        CAmount n = 0;
        if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n)
            return InitError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
        if (n > HIGH_TX_FEE_PER_KB)
            InitWarning(AmountHighWarn("-mintxfee") + " " +
                        _("This is the minimum transaction fee you pay on every transaction."));
        CWallet::minTxFee = CFeeRate(n);
    }
    if (gArgs.IsArgSet("-fallbackfee"))
    {
        CAmount nFeePerK = 0;
        if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK))
            return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", "")));
        if (nFeePerK > HIGH_TX_FEE_PER_KB)
            InitWarning(AmountHighWarn("-fallbackfee") + " " +
                        _("This is the transaction fee you may pay when fee estimates are not available."));
        CWallet::fallbackFee = CFeeRate(nFeePerK);
    }
    if (gArgs.IsArgSet("-discardfee"))
    {
        CAmount nFeePerK = 0;
        if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK))
            return InitError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", "")));
        if (nFeePerK > HIGH_TX_FEE_PER_KB)
            InitWarning(AmountHighWarn("-discardfee") + " " +
                        _("This is the transaction fee you may discard if change is smaller than dust at this level"));
        CWallet::m_discard_rate = CFeeRate(nFeePerK);
    }
    if (gArgs.IsArgSet("-paytxfee"))
    {
        CAmount nFeePerK = 0;
        if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK))
            return InitError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
        if (nFeePerK > HIGH_TX_FEE_PER_KB)
            InitWarning(AmountHighWarn("-paytxfee") + " " +
                        _("This is the transaction fee you will pay if you send a transaction."));

        payTxFee = CFeeRate(nFeePerK, 1000);
        if (payTxFee < ::minRelayTxFee)
        {
            return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
                                       gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString()));
        }
    }
    if (gArgs.IsArgSet("-maxtxfee"))
    {
        CAmount nMaxFee = 0;
        if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee))
            return InitError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")));
        if (nMaxFee > HIGH_MAX_TX_FEE)
            InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
        maxTxFee = nMaxFee;
        if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
        {
            return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
                                       gArgs.GetArg("-maxtxfee", ""), ::minRelayTxFee.ToString()));
        }
    }
    nTxConfirmTarget = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
    bSpendZeroConfChange = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
    fWalletRbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);

    return true;
}

void RegisterWalletRPC(CRPCTable &t)
{
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        return;
    }

    RegisterWalletRPCCommands(t);
}

bool VerifyWallets()
{
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        return true;
    }

    uiInterface.InitMessage(_("Verifying wallet(s)..."));

    // Keep track of each wallet absolute path to detect duplicates.
    std::set<fs::path> wallet_paths;

    for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
        if (boost::filesystem::path(walletFile).filename() != walletFile) {
            return InitError(strprintf(_("Error loading wallet %s. -wallet parameter must only specify a filename (not a path)."), walletFile));
        }

        if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) {
            return InitError(strprintf(_("Error loading wallet %s. Invalid characters in -wallet filename."), walletFile));
        }

        fs::path wallet_path = fs::absolute(walletFile, GetDataDir());

        if (fs::exists(wallet_path) && (!fs::is_regular_file(wallet_path) || fs::is_symlink(wallet_path))) {
            return InitError(strprintf(_("Error loading wallet %s. -wallet filename must be a regular file."), walletFile));
        }

        if (!wallet_paths.insert(wallet_path).second) {
            return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), walletFile));
        }

        std::string strError;
        if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) {
            return InitError(strError);
        }

        if (gArgs.GetBoolArg("-salvagewallet", false)) {
            // Recover readable keypairs:
            CWallet dummyWallet;
            std::string backup_filename;
            if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) {
                return false;
            }
        }

        std::string strWarning;
        bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError);
        if (!strWarning.empty()) {
            InitWarning(strWarning);
        }
        if (!dbV) {
            InitError(strError);
            return false;
        }
    }

    return true;
}

bool OpenWallets()
{
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        LogPrintf("Wallet disabled!\n");
        return true;
    }

    for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
        CWallet * const pwallet = CWallet::CreateWalletFromFile(walletFile);
        if (!pwallet) {
            return false;
        }
        vpwallets.push_back(pwallet);
    }

    return true;
}

void StartWallets(CScheduler& scheduler) {
    for (CWalletRef pwallet : vpwallets) {
        pwallet->postInitProcess(scheduler);
    }
}

void FlushWallets() {
    for (CWalletRef pwallet : vpwallets) {
        pwallet->Flush(false);
    }
}

void StopWallets() {
    for (CWalletRef pwallet : vpwallets) {
        pwallet->Flush(true);
    }
}

void CloseWallets() {
    for (CWalletRef pwallet : vpwallets) {
        delete pwallet;
    }
    vpwallets.clear();
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bench.h"

#include "chainparams.h"
#include "main.h"
#include "consensus/validation.h"

namespace block_bench {
#include "bench/data/block413567.raw.h"
}

// These are the two major time-sinks which happen after we have fully received
// a block off the wire, but before we can relay the block on to peers using
// compact block relay.

static void DeserializeBlockTest(benchmark::State& state)
{
    CDataStream stream((const char*)block_bench::block413567,
            (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
            SER_NETWORK, PROTOCOL_VERSION);
    char a = '\0';
    stream.write(&a, 1); // Prevent compaction

    while (state.KeepRunning()) {
        CBlock block;
        stream >> block;
        assert(stream.Rewind(sizeof(block_bench::block413567)));
    }
}

static void DeserializeAndCheckBlockTest(benchmark::State& state)
{
    CDataStream stream((const char*)block_bench::block413567,
            (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
            SER_NETWORK, PROTOCOL_VERSION);
    char a = '\0';
    stream.write(&a, 1); // Prevent compaction

    Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus();

    while (state.KeepRunning()) {
        CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
        stream >> block;
        assert(stream.Rewind(sizeof(block_bench::block413567)));

        CValidationState validationState;
        assert(CheckBlock(block, validationState, params));
    }
}

BENCHMARK(DeserializeBlockTest);
BENCHMARK(DeserializeAndCheckBlockTest);
<commit_msg>catch up<commit_after>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bench.h"

#include "chainparams.h"
#include "streams.h"
#include "validation.h"
#include "consensus/validation.h"

namespace block_bench {
#include "bench/data/block413567.raw.h"
}

// These are the two major time-sinks which happen after we have fully received
// a block off the wire, but before we can relay the block on to peers using
// compact block relay.

static void DeserializeBlockTest(benchmark::State& state)
{
    CDataStream stream((const char*)block_bench::block413567,
            (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
            SER_NETWORK, PROTOCOL_VERSION);
    char a = '\0';
    stream.write(&a, 1); // Prevent compaction

    while (state.KeepRunning()) {
        CBlock block;
        stream >> block;
        assert(stream.Rewind(sizeof(block_bench::block413567)));
    }
}

static void DeserializeAndCheckBlockTest(benchmark::State& state)
{
    CDataStream stream((const char*)block_bench::block413567,
            (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
            SER_NETWORK, PROTOCOL_VERSION);
    char a = '\0';
    stream.write(&a, 1); // Prevent compaction

    Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus();

    while (state.KeepRunning()) {
        CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
        stream >> block;
        assert(stream.Rewind(sizeof(block_bench::block413567)));

        CValidationState validationState;
        assert(CheckBlock(block, validationState, params));
    }
}

BENCHMARK(DeserializeBlockTest);
BENCHMARK(DeserializeAndCheckBlockTest);
<|endoftext|>


<commit_before>#include <string.h> // memset

#include "Math.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include "Reference.h"
#include "ModelWorld.h"
#include "PhysicsManager.h"
#include "Shader.h"
#include "Camera.h"

using glm::mat4;

struct Camera
{
    ReferenceCounter refCounter;
    ModelWorld* world;
    Solid* attachmentTarget;
    int attachmentFlags;
    glm::mat4 modelTransformation;
    glm::mat4 viewTransformation;

    float aspect;
    float zNear, zFar;
    bool projectionTransformationNeedsUpdate;
    glm::mat4 projectionTransformation;

    CameraProjectionType projectionType;
    float fieldOfView; // perspective projection
    float scale; // orthographic projection
};

Camera* CreateCamera( ModelWorld* world )
{
    Camera* camera = new Camera;
    memset(camera, 0, sizeof(Camera));

    InitReferenceCounter(&camera->refCounter);
    camera->world = world;
    ReferenceModelWorld(world);

    camera->modelTransformation = mat4(1);
    camera->viewTransformation = mat4(1);

    camera->aspect = 1;
    camera->zNear  = 0.1f;
    camera->zFar   = 100;

    camera->projectionType = CAMERA_PERSPECTIVE_PROJECTION;
    camera->fieldOfView = TAU/4.0; // 90 degrees
    camera->scale = 1;
    camera->projectionTransformationNeedsUpdate = true;

    return camera;
}

static void FreeCamera( Camera* camera )
{
    ReleaseModelWorld(camera->world);
    if(camera->attachmentTarget)
        ReleaseSolid(camera->attachmentTarget);
    delete camera;
}

void ReferenceCamera( Camera* camera )
{
    Reference(&camera->refCounter);
}

void ReleaseCamera( Camera* camera )
{
    Release(&camera->refCounter);
    if(!HasReferences(&camera->refCounter))
        FreeCamera(camera);
}

void SetCameraAttachmentTarget( Camera* camera, Solid* target, int flags )
{
    if(camera->attachmentTarget)
        ReleaseSolid(camera->attachmentTarget);
    camera->attachmentTarget = target;
    camera->attachmentFlags = flags;
    if(camera->attachmentTarget)
        ReferenceSolid(camera->attachmentTarget);
}

void SetCameraModelTransformation( Camera* camera, glm::mat4 transformation )
{
    camera->modelTransformation = transformation;
}

void SetCameraViewTransformation( Camera* camera, mat4 transformation )
{
    camera->viewTransformation = transformation;
}

void SetCameraAspect( Camera* camera, float aspect )
{
    assert(aspect > 0);
    camera->aspect = aspect;
    camera->projectionTransformationNeedsUpdate = true;
}

void SetCameraNearAndFarPlanes( Camera* camera, float zNear, float zFar )
{
    assert(zNear > 0);
    assert(zNear <= zFar);
    camera->zNear = zNear;
    camera->zFar = zFar;
    camera->projectionTransformationNeedsUpdate = true;
}

void SetCameraProjectionType( Camera* camera, CameraProjectionType type )
{
    camera->projectionType = type;
    camera->projectionTransformationNeedsUpdate = true;
}

void SetCameraFieldOfView( Camera* camera, float fov )
{
    assert(fov > 0);
    camera->fieldOfView = fov;
    camera->projectionTransformationNeedsUpdate = true;
}

void SetCameraScale( Camera* camera, float scale )
{
    assert(scale > 0);
    camera->scale = scale;
    camera->projectionTransformationNeedsUpdate = true;
}

static void UpdateCameraProjection( Camera* camera )
{
    if(camera->projectionTransformationNeedsUpdate)
    {
        switch(camera->projectionType)
        {
            case CAMERA_PERSPECTIVE_PROJECTION:
                camera->projectionTransformation =
                    glm::perspective(camera->fieldOfView,
                                     camera->aspect,
                                     camera->zNear,
                                     camera->zFar);
                break;

            case CAMERA_ORTHOGRAPHIC_PROJECTION:
                const float aspect = camera->aspect;
                const float scale  = camera->scale;
                const float halfWidth  = aspect * scale * 0.5f;
                const float halfHeight =          scale * 0.5f;
                camera->projectionTransformation =
                    glm::ortho(halfWidth, // left
                               halfWidth, // right
                               halfHeight, // bottom
                               halfHeight, // top
                               camera->zNear,
                               camera->zFar);
                break;
        }
        camera->projectionTransformationNeedsUpdate = false;
    }
}

static const mat4 GetCameraModelTransformation( const Camera* camera )
{
    mat4 solidTransformation;
    if(camera->attachmentTarget)
        GetSolidTransformation(camera->attachmentTarget,
                               camera->attachmentFlags,
                               &solidTransformation);
    return glm::inverse(solidTransformation) * camera->modelTransformation;
}

template<class CalcFn>
static void CalcUniform( ShaderProgram* program,
                         const char* name,
                         CalcFn calcFn )
{
    if(HasUniform(program, name))
    {
        const mat4 value = calcFn();
        SetUniform(program,
                   name,
                   MAT4_UNIFORM,
                   (const UniformValue*)&value);
    }
}

void SetCameraUniforms( Camera* camera, ShaderProgram* program )
{
    UpdateCameraProjection(camera);
    const mat4* projection = &camera->projectionTransformation;

    SetUniform(program,
               "Projection",
               MAT4_UNIFORM,
               (const UniformValue*)projection);

    CalcUniform(program, "InverseProjection", [&]{
        return glm::inverse(*projection);
    });

    CalcUniform(program, "InverseTransposeProjection", [&]{
        return glm::inverseTranspose(*projection);
    });
}

void SetCameraModelUniforms( Camera* camera,
                             ShaderProgram* program,
                             const mat4* modelTransformation )
{
    UpdateCameraProjection(camera);
    const mat4* projection = &camera->projectionTransformation;
    const mat4* view = &camera->viewTransformation;
    const mat4  model = GetCameraModelTransformation(camera) *
                        *modelTransformation;

    const mat4 modelView = *view * model;
    const mat4 modelViewProjection = *projection * modelView;

    // These are almost always used:
    SetUniform(program,
               "ModelView",
               MAT4_UNIFORM,
               (const UniformValue*)&modelView);
    SetUniform(program,
               "ModelViewProjection",
               MAT4_UNIFORM,
               (const UniformValue*)&modelViewProjection);

    // Same set, but inversed:
    CalcUniform(program, "InverseModelView", [&]{
        return glm::inverse(modelView);
    });
    CalcUniform(program, "InverseModelViewProjection", [&]{
        return glm::inverse(modelViewProjection);
    });

    // Same set, but inversed and transposed:
    CalcUniform(program, "InverseTransposeModelView", [&]{
        return glm::inverseTranspose(modelView);
    });
    CalcUniform(program, "InverseTransposeModelViewProjection", [&]{
        return glm::inverseTranspose(modelViewProjection);
    });
}

void DrawCameraView( Camera* camera, ShaderProgramSet* set )
{
    DrawModelWorld(camera->world, set, camera);
}
<commit_msg>Made view matrix available in for shaders.<commit_after>#include <string.h> // memset

#include "Math.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include "Reference.h"
#include "ModelWorld.h"
#include "PhysicsManager.h"
#include "Shader.h"
#include "Camera.h"

using glm::mat4;

struct Camera
{
    ReferenceCounter refCounter;
    ModelWorld* world;
    Solid* attachmentTarget;
    int attachmentFlags;
    glm::mat4 modelTransformation;
    glm::mat4 viewTransformation;

    float aspect;
    float zNear, zFar;
    bool projectionTransformationNeedsUpdate;
    glm::mat4 projectionTransformation;

    CameraProjectionType projectionType;
    float fieldOfView; // perspective projection
    float scale; // orthographic projection
};

Camera* CreateCamera( ModelWorld* world )
{
    Camera* camera = new Camera;
    memset(camera, 0, sizeof(Camera));

    InitReferenceCounter(&camera->refCounter);
    camera->world = world;
    ReferenceModelWorld(world);

    camera->modelTransformation = mat4(1);
    camera->viewTransformation = mat4(1);

    camera->aspect = 1;
    camera->zNear  = 0.1f;
    camera->zFar   = 100;

    camera->projectionType = CAMERA_PERSPECTIVE_PROJECTION;
    camera->fieldOfView = TAU/4.0; // 90 degrees
    camera->scale = 1;
    camera->projectionTransformationNeedsUpdate = true;

    return camera;
}

static void FreeCamera( Camera* camera )
{
    ReleaseModelWorld(camera->world);
    if(camera->attachmentTarget)
        ReleaseSolid(camera->attachmentTarget);
    delete camera;
}

void ReferenceCamera( Camera* camera )
{
    Reference(&camera->refCounter);
}

void ReleaseCamera( Camera* camera )
{
    Release(&camera->refCounter);
    if(!HasReferences(&camera->refCounter))
        FreeCamera(camera);
}

void SetCameraAttachmentTarget( Camera* camera, Solid* target, int flags )
{
    if(camera->attachmentTarget)
        ReleaseSolid(camera->attachmentTarget);
    camera->attachmentTarget = target;
    camera->attachmentFlags = flags;
    if(camera->attachmentTarget)
        ReferenceSolid(camera->attachmentTarget);
}

void SetCameraModelTransformation( Camera* camera, glm::mat4 transformation )
{
    camera->modelTransformation = transformation;
}

void SetCameraViewTransformation( Camera* camera, mat4 transformation )
{
    camera->viewTransformation = transformation;
}

void SetCameraAspect( Camera* camera, float aspect )
{
    assert(aspect > 0);
    camera->aspect = aspect;
    camera->projectionTransformationNeedsUpdate = true;
}

void SetCameraNearAndFarPlanes( Camera* camera, float zNear, float zFar )
{
    assert(zNear > 0);
    assert(zNear <= zFar);
    camera->zNear = zNear;
    camera->zFar = zFar;
    camera->projectionTransformationNeedsUpdate = true;
}

void SetCameraProjectionType( Camera* camera, CameraProjectionType type )
{
    camera->projectionType = type;
    camera->projectionTransformationNeedsUpdate = true;
}

void SetCameraFieldOfView( Camera* camera, float fov )
{
    assert(fov > 0);
    camera->fieldOfView = fov;
    camera->projectionTransformationNeedsUpdate = true;
}

void SetCameraScale( Camera* camera, float scale )
{
    assert(scale > 0);
    camera->scale = scale;
    camera->projectionTransformationNeedsUpdate = true;
}

static void UpdateCameraProjection( Camera* camera )
{
    if(camera->projectionTransformationNeedsUpdate)
    {
        switch(camera->projectionType)
        {
            case CAMERA_PERSPECTIVE_PROJECTION:
                camera->projectionTransformation =
                    glm::perspective(camera->fieldOfView,
                                     camera->aspect,
                                     camera->zNear,
                                     camera->zFar);
                break;

            case CAMERA_ORTHOGRAPHIC_PROJECTION:
                const float aspect = camera->aspect;
                const float scale  = camera->scale;
                const float halfWidth  = aspect * scale * 0.5f;
                const float halfHeight =          scale * 0.5f;
                camera->projectionTransformation =
                    glm::ortho(halfWidth, // left
                               halfWidth, // right
                               halfHeight, // bottom
                               halfHeight, // top
                               camera->zNear,
                               camera->zFar);
                break;
        }
        camera->projectionTransformationNeedsUpdate = false;
    }
}

static const mat4 GetCameraModelTransformation( const Camera* camera )
{
    mat4 solidTransformation;
    if(camera->attachmentTarget)
        GetSolidTransformation(camera->attachmentTarget,
                               camera->attachmentFlags,
                               &solidTransformation);
    return glm::inverse(solidTransformation) * camera->modelTransformation;
}

template<class CalcFn>
static void CalcUniform( ShaderProgram* program,
                         const char* name,
                         CalcFn calcFn )
{
    if(HasUniform(program, name))
    {
        const mat4 value = calcFn();
        SetUniform(program,
                   name,
                   MAT4_UNIFORM,
                   (const UniformValue*)&value);
    }
}

void SetCameraUniforms( Camera* camera, ShaderProgram* program )
{
    UpdateCameraProjection(camera);
    const mat4* projection = &camera->projectionTransformation;

    SetUniform(program,
               "Projection",
               MAT4_UNIFORM,
               (const UniformValue*)projection);

    CalcUniform(program, "InverseProjection", [&]{
        return glm::inverse(*projection);
    });

    CalcUniform(program, "InverseTransposeProjection", [&]{
        return glm::inverseTranspose(*projection);
    });
}

void SetCameraModelUniforms( Camera* camera,
                             ShaderProgram* program,
                             const mat4* modelTransformation )
{
    UpdateCameraProjection(camera);
    const mat4* projection = &camera->projectionTransformation;
    const mat4* view = &camera->viewTransformation;
    const mat4  model = GetCameraModelTransformation(camera) *
                        *modelTransformation;

    const mat4 modelView = *view * model;
    const mat4 modelViewProjection = *projection * modelView;

    // These are almost always used:
    SetUniform(program,
               "View",
               MAT4_UNIFORM,
               (const UniformValue*)view);
    SetUniform(program,
               "ModelView",
               MAT4_UNIFORM,
               (const UniformValue*)&modelView);
    SetUniform(program,
               "ModelViewProjection",
               MAT4_UNIFORM,
               (const UniformValue*)&modelViewProjection);

    // Same set, but inversed:
    CalcUniform(program, "InverseModelView", [&]{
        return glm::inverse(modelView);
    });
    CalcUniform(program, "InverseModelViewProjection", [&]{
        return glm::inverse(modelViewProjection);
    });

    // Same set, but inversed and transposed:
    CalcUniform(program, "InverseTransposeModelView", [&]{
        return glm::inverseTranspose(modelView);
    });
    CalcUniform(program, "InverseTransposeModelViewProjection", [&]{
        return glm::inverseTranspose(modelViewProjection);
    });
}

void DrawCameraView( Camera* camera, ShaderProgramSet* set )
{
    DrawModelWorld(camera->world, set, camera);
}
<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#ifdef CLEVER_WIN32
# include <direct.h>
# include <windows.h>
#else
# include <dirent.h>
# include <unistd.h>
# include <sys/resource.h>
# include <sys/time.h>
#endif

#include "core/clever.h"
#include "core/value.h"
#include "modules/std/events/events.h"
#include "types/type.h"
#include "core/vm.h"

namespace clever { namespace modules { namespace std {

CLEVER_THREAD_FUNC(_events_handler)
{
	EventData* intern = static_cast<EventData*>(arg);

	while (true) {
		intern->mutex.lock();

		while (!intern->m_event_queue.empty()) {
			Signal u = intern->m_event_queue.front();
			intern->m_event_queue.pop();

			Actions& a = intern->m_event_map[u.first];

			for (Actions::iterator it = a.begin(); it != a.end(); ++it) {
				intern->m_vm->runFunction(*it, &u.second)->delRef();
			}

			if (u.first == "exit") {
				intern->mutex.unlock();
				return NULL;
			}
		}

		intern->mutex.unlock();

#ifdef CLEVER_WIN32
			SleepEx(intern->m_sleep_time, false);
#else
			usleep(intern->m_sleep_time * 1000);
#endif
	}

	return NULL;
}

TypeObject* Events::allocData(CLEVER_TYPE_CTOR_ARGS) const
{
	EventData* intern = new EventData;

	if (args->size() > 0) {
		intern->m_sleep_time = static_cast<int>(args->at(0)->getInt());
	} else {
		intern->m_sleep_time = 500;
	}

	intern->handler.create(_events_handler, intern);
	return intern;
}

EventData::~EventData()
{
	if (this->handler.isRunning()) {
		this->mutex.lock();

		Signal s;

		s.first = "exit";

		this->m_event_queue.push(s);

		this->mutex.unlock();
		this->handler.wait();
	}

	if (this->m_vm) {
		delete this->m_vm;
		this->m_vm = 0;
	}
}

// Events.new([Int sleep_time])
// Constructs a new Events handler object to manage some events
CLEVER_METHOD(Events::ctor)
{
	if (args.size() > 0) {
		if (!clever_check_args("i")) {
			return;
		}
	}

	EventData* intern = static_cast<EventData*>(allocData(&args));

	intern->m_vm = new VM();
	intern->m_vm->copy(vm, true);
	intern->m_vm->setChild();

	result->setObj(this, intern);
}

// Events.connect(String name, Function func)
CLEVER_METHOD(Events::connect)
{
	if (!clever_check_args("sf")) {
		return;
	}

	EventData* intern = CLEVER_GET_OBJECT(EventData*, CLEVER_THIS());

	intern->m_event_map[*args.at(0)->getStr()]
			.push_back(static_cast<Function*>(args.at(1)->getObj()));
}

// Events.emit(String name)
CLEVER_METHOD(Events::emit)
{
	EventData* intern = CLEVER_GET_OBJECT(EventData*, CLEVER_THIS());

	intern->mutex.lock();

	Signal s;

	s.first = *args.at(0)->getStr();

	for (size_t i = 1, j = args.size(); i < j; ++i) {
		s.second.push_back(args.at(i));
	}
	intern->m_event_queue.push(s);

	intern->mutex.unlock();
}

// Events.wait()
CLEVER_METHOD(Events::wait)
{
	if (!clever_check_no_args()) {
		return;
	}
	EventData* intern = CLEVER_GET_OBJECT(EventData*, CLEVER_THIS());

	intern->handler.wait();
}

// Events.finalize()
CLEVER_METHOD(Events::finalize)
{
	if (!clever_check_no_args()) {
		return;
	}

	EventData* intern = CLEVER_GET_OBJECT(EventData*, CLEVER_THIS());

	intern->mutex.lock();

	Signal s;

	s.first = "exit";

	intern->m_event_queue.push(s);

	intern->mutex.unlock();
	intern->handler.wait();
}

// Events type initialization
CLEVER_TYPE_INIT(Events::init)
{
	setConstructor((MethodPtr)&Events::ctor);

	addMethod(new Function("connect",    (MethodPtr)&Events::connect));
	addMethod(new Function("emit",      (MethodPtr)&Events::emit));
	addMethod(new Function("wait",       (MethodPtr)&Events::wait));
	addMethod(new Function("finalize",   (MethodPtr)&Events::finalize));
}

// FFI module initialization
CLEVER_MODULE_INIT(EventsModule)
{
	addType(new Events);
}

}}} // clever::modules::std
<commit_msg>- Added missing parameter checking<commit_after>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#ifdef CLEVER_WIN32
# include <direct.h>
# include <windows.h>
#else
# include <dirent.h>
# include <unistd.h>
# include <sys/resource.h>
# include <sys/time.h>
#endif

#include "core/clever.h"
#include "core/value.h"
#include "modules/std/events/events.h"
#include "types/type.h"
#include "core/vm.h"

namespace clever { namespace modules { namespace std {

CLEVER_THREAD_FUNC(_events_handler)
{
	EventData* intern = static_cast<EventData*>(arg);

	while (true) {
		intern->mutex.lock();

		while (!intern->m_event_queue.empty()) {
			Signal u = intern->m_event_queue.front();
			intern->m_event_queue.pop();

			Actions& a = intern->m_event_map[u.first];

			for (Actions::iterator it = a.begin(); it != a.end(); ++it) {
				intern->m_vm->runFunction(*it, &u.second)->delRef();
			}

			if (u.first == "exit") {
				intern->mutex.unlock();
				return NULL;
			}
		}

		intern->mutex.unlock();

#ifdef CLEVER_WIN32
			SleepEx(intern->m_sleep_time, false);
#else
			usleep(intern->m_sleep_time * 1000);
#endif
	}

	return NULL;
}

TypeObject* Events::allocData(CLEVER_TYPE_CTOR_ARGS) const
{
	EventData* intern = new EventData;

	if (args->size() > 0) {
		intern->m_sleep_time = static_cast<int>(args->at(0)->getInt());
	} else {
		intern->m_sleep_time = 500;
	}

	intern->handler.create(_events_handler, intern);
	return intern;
}

EventData::~EventData()
{
	if (handler.isRunning()) {
		mutex.lock();

		Signal s;

		s.first = "exit";

		m_event_queue.push(s);

		mutex.unlock();
		handler.wait();
	}

	if (m_vm) {
		delete m_vm;
		m_vm = 0;
	}
}

// Events.new([Int sleep_time])
// Constructs a new Events handler object to manage some events
CLEVER_METHOD(Events::ctor)
{
	if (!clever_check_args("|i")) {
		return;
	}

	EventData* intern = static_cast<EventData*>(allocData(&args));

	intern->m_vm = new VM();
	intern->m_vm->copy(vm, true);
	intern->m_vm->setChild();

	result->setObj(this, intern);
}

// Events.connect(String name, Function func)
CLEVER_METHOD(Events::connect)
{
	if (!clever_check_args("sf")) {
		return;
	}

	EventData* intern = CLEVER_GET_OBJECT(EventData*, CLEVER_THIS());

	intern->m_event_map[*args.at(0)->getStr()]
			.push_back(static_cast<Function*>(args.at(1)->getObj()));
}

// Events.emit(String name, ...)
CLEVER_METHOD(Events::emit)
{
	if (!clever_check_args("s*")) {
		return;
	}

	EventData* intern = CLEVER_GET_OBJECT(EventData*, CLEVER_THIS());

	intern->mutex.lock();

	Signal s;

	s.first = *args.at(0)->getStr();

	for (size_t i = 1, j = args.size(); i < j; ++i) {
		s.second.push_back(args.at(i));
	}
	intern->m_event_queue.push(s);

	intern->mutex.unlock();
}

// Events.wait()
CLEVER_METHOD(Events::wait)
{
	if (!clever_check_no_args()) {
		return;
	}
	EventData* intern = CLEVER_GET_OBJECT(EventData*, CLEVER_THIS());

	intern->handler.wait();
}

// Events.finalize()
CLEVER_METHOD(Events::finalize)
{
	if (!clever_check_no_args()) {
		return;
	}

	EventData* intern = CLEVER_GET_OBJECT(EventData*, CLEVER_THIS());

	intern->mutex.lock();

	Signal s;

	s.first = "exit";

	intern->m_event_queue.push(s);

	intern->mutex.unlock();
	intern->handler.wait();
}

// Events type initialization
CLEVER_TYPE_INIT(Events::init)
{
	setConstructor((MethodPtr)&Events::ctor);

	addMethod(new Function("connect",    (MethodPtr)&Events::connect));
	addMethod(new Function("emit",      (MethodPtr)&Events::emit));
	addMethod(new Function("wait",       (MethodPtr)&Events::wait));
	addMethod(new Function("finalize",   (MethodPtr)&Events::finalize));
}

// FFI module initialization
CLEVER_MODULE_INIT(EventsModule)
{
	addType(new Events);
}

}}} // clever::modules::std
<|endoftext|>


<commit_before>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <iostream>

#include "storage/StorageImpl.h"
#include "storage/Environment.h"
#include "storage/Devicegraph.h"
#include "storage/Utils/SystemCmd.h"
#include "storage/Utils/Logger.h"

using namespace std;
using namespace storage;

bool display_devicegraph = false;
bool save_devicegraph = false;
bool save_mockup = false;

void
doit()
{
    set_logger(get_logfile_logger());

    Environment environment(true, save_mockup ? ProbeMode::STANDARD_WRITE_MOCKUP : ProbeMode::STANDARD,
			    TargetMode::DIRECT);

    environment.set_mockup_filename("mockup.xml");

    Storage storage(environment);
    storage.probe();

    const Devicegraph* probed = storage.get_probed();

    cout.setf(ios::boolalpha);
    cout.setf(ios::showbase);

    cout << *probed << endl;

    probed->check();

    if (save_devicegraph)
	probed->save("devicegraph.xml");

    if (display_devicegraph)
    {
	const TmpDir& tmp_dir = storage.get_impl().get_tmp_dir();

	probed->write_graphviz(tmp_dir.get_fullname() + "/probe.gv", GraphvizFlags::CLASSNAME |
			       GraphvizFlags::SID | GraphvizFlags::SIZE);
	system(string("dot -Tsvg < " + quote(tmp_dir.get_fullname() + "/probe.gv") + " > " +
		      quote(tmp_dir.get_fullname() + "/probe.svg")).c_str());
	unlink(string(tmp_dir.get_fullname() + "/probe.gv").c_str());
	system(string("display " + quote(tmp_dir.get_fullname() + "/probe.svg")).c_str());
	unlink(string(tmp_dir.get_fullname() + "/probe.svg").c_str());
    }
}

void usage() __attribute__ ((__noreturn__));

void
usage()
{
    cerr << "probe [--display-devicegraph] [--save-devicegraph] [--save-mockup]" << endl;
    exit(EXIT_FAILURE);
}

int
main(int argc, char **argv)
{
    const struct option options[] = {
	{ "display-devicegraph",	no_argument,	0,	1 },
	{ "save-devicegraph",		no_argument,	0,	2 },
	{ "save-mockup",		no_argument,	0,	3 },
	{ 0, 0, 0, 0 }
    };

    while (true)
    {
	int option_index = 0;
	int c = getopt_long(argc, argv, "", options, &option_index);
	if (c == -1)
	    break;

	if (c == '?')
	    usage();

	switch (c)
	{
	    case 1:
		display_devicegraph = true;
		break;

	    case 2:
		save_devicegraph = true;
		break;

	    case 3:
		save_mockup = true;
		break;

	    default:
		usage();
	}
    }

    if (optind < argc)
	usage();

    try
    {
	doit();
    }
    catch (const exception& e)
    {
	cerr << "exception occured: " << e.what() << endl;
	exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}
<commit_msg>- allow to load mockup<commit_after>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <iostream>

#include "storage/StorageImpl.h"
#include "storage/Environment.h"
#include "storage/Devicegraph.h"
#include "storage/Utils/SystemCmd.h"
#include "storage/Utils/Logger.h"

using namespace std;
using namespace storage;

bool display_devicegraph = false;
bool save_devicegraph = false;
bool save_mockup = false;
bool load_mockup = false;

void
doit()
{
    set_logger(get_logfile_logger());

    ProbeMode probe_mode = ProbeMode::STANDARD;
    if (save_mockup)
	probe_mode = ProbeMode::STANDARD_WRITE_MOCKUP;
    else if (load_mockup)
	probe_mode = ProbeMode::READ_MOCKUP;

    Environment environment(true, probe_mode, TargetMode::DIRECT);

    environment.set_mockup_filename("mockup.xml");

    Storage storage(environment);
    storage.probe();

    const Devicegraph* probed = storage.get_probed();

    cout.setf(ios::boolalpha);
    cout.setf(ios::showbase);

    cout << *probed << endl;

    probed->check();

    if (save_devicegraph)
	probed->save("devicegraph.xml");

    if (display_devicegraph)
    {
	const TmpDir& tmp_dir = storage.get_impl().get_tmp_dir();

	probed->write_graphviz(tmp_dir.get_fullname() + "/probe.gv", GraphvizFlags::CLASSNAME |
			       GraphvizFlags::SID | GraphvizFlags::SIZE);
	system(string("dot -Tsvg < " + quote(tmp_dir.get_fullname() + "/probe.gv") + " > " +
		      quote(tmp_dir.get_fullname() + "/probe.svg")).c_str());
	unlink(string(tmp_dir.get_fullname() + "/probe.gv").c_str());
	system(string("display " + quote(tmp_dir.get_fullname() + "/probe.svg")).c_str());
	unlink(string(tmp_dir.get_fullname() + "/probe.svg").c_str());
    }
}

void usage() __attribute__ ((__noreturn__));

void
usage()
{
    cerr << "probe [--display-devicegraph] [--save-devicegraph] [--save-mockup] [--load-mockup]" << endl;
    exit(EXIT_FAILURE);
}

int
main(int argc, char **argv)
{
    const struct option options[] = {
	{ "display-devicegraph",	no_argument,	0,	1 },
	{ "save-devicegraph",		no_argument,	0,	2 },
	{ "save-mockup",		no_argument,	0,	3 },
	{ "load-mockup",		no_argument,	0,	4 },
	{ 0, 0, 0, 0 }
    };

    while (true)
    {
	int option_index = 0;
	int c = getopt_long(argc, argv, "", options, &option_index);
	if (c == -1)
	    break;

	if (c == '?')
	    usage();

	switch (c)
	{
	    case 1:
		display_devicegraph = true;
		break;

	    case 2:
		save_devicegraph = true;
		break;

	    case 3:
		save_mockup = true;
		break;

	    case 4:
		load_mockup = true;
		break;

	    default:
		usage();
	}
    }

    if (optind < argc)
	usage();

    try
    {
	doit();
    }
    catch (const exception& e)
    {
	cerr << "exception occured: " << e.what() << endl;
	exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}
<|endoftext|>


<commit_before>#include <build-bot/worker.h>

#include <boost/filesystem.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>

#include <boost/process.hpp>

namespace fs = boost::filesystem;

namespace dsn {
namespace build_bot {
    namespace priv {
        class Worker : public dsn::log::Base<Worker> {
        private:
            std::string m_url;
            std::string m_branch;
            std::string m_revision;
            std::string m_configFile;
            std::string m_profileName;
            std::string m_buildDir;
            std::string m_repoName;
            std::string m_macroFile;

            std::string generateBuildId()
            {
                std::string res;
                boost::random::random_device rng;
                boost::random::uniform_int_distribution<> dist(0, BUILD_ID_CHARS.size() - 1);

                for (size_t i = 0; i < BUILD_ID_LENGTH; i++)
                    res += BUILD_ID_CHARS[dist(rng)];

                return res;
            }

            std::string m_buildId;

            static const std::string BUILD_ID_CHARS;
            static const size_t BUILD_ID_LENGTH;

            std::string m_toplevelDirectory;

            bool initToplevelDirectory()
            {
                std::stringstream ss;
                ss << m_buildDir << "/" << m_profileName << "/" << m_repoName << "/" << m_buildId;
                m_toplevelDirectory = ss.str();
                fs::path path(m_toplevelDirectory);

                BOOST_LOG_SEV(log, severity::info) << "Toplevel build directory is " << m_toplevelDirectory;

                if (!fs::exists(path)) {
                    try {
                        fs::create_directories(path);
                    }

                    catch (boost::system::system_error& ex) {
                        BOOST_LOG_SEV(log, severity::error) << "Failed to create toplevel directory " << m_toplevelDirectory << ": " << ex.what();
                        return false;
                    }
                }

                return true;
            }

            std::string m_gitExecutable;
            bool findGitExecutable()
            {
                try {
                    m_gitExecutable = boost::process::search_path("git");
                }
                catch (std::runtime_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to locate git executable in PATH: " << ex.what();
                    return false;
                }

                if (m_gitExecutable.size() == 0) {
                    BOOST_LOG_SEV(log, severity::error) << "No git executable found in PATH!";
                    return false;
                }

                BOOST_LOG_SEV(log, severity::debug) << "Using git executable from " << m_gitExecutable;
                return true;
            }

            std::string m_sourceDirectory;
            bool checkoutSources()
            {
                m_sourceDirectory = m_toplevelDirectory + "/repo";
                BOOST_LOG_SEV(log, severity::info) << "Checking out sources from " << m_url << " to " << m_sourceDirectory;

                try {
                    std::stringstream ssArgs;
                    ssArgs << m_gitExecutable << " clone --recursive -b " << m_branch << " " << m_url << " " << m_sourceDirectory;
                    std::string args = ssArgs.str();
                    BOOST_LOG_SEV(log, severity::debug) << "Git command line is " << args;

                    boost::process::child child = boost::process::execute(boost::process::initializers::run_exe(m_gitExecutable),
                                                                          boost::process::initializers::set_cmd_line(args));
                    auto exit_code = boost::process::wait_for_exit(child);

                    if (exit_code != 0) {
                        BOOST_LOG_SEV(log, severity::error) << "Got non-zero exit status from '" << args << "': " << exit_code;
                        return false;
                    }
                }

                catch (boost::system::system_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to run git to check out sources: " << ex.what();
                    return false;
                }

                BOOST_LOG_SEV(log, severity::info) << "Repository cloned successfully. Checking out revision " << m_revision;

                try {
                    std::stringstream ssArgs;
                    ssArgs << m_gitExecutable << " checkout " << m_revision << " .";
                    std::string args = ssArgs.str();
                    BOOST_LOG_SEV(log, severity::debug) << "Git command line is " << args;
                    boost::process::child child = boost::process::execute(boost::process::initializers::run_exe(m_gitExecutable),
                                                                          boost::process::initializers::set_cmd_line(args),
                                                                          boost::process::initializers::start_in_dir(m_sourceDirectory));
                    auto exit_code = boost::process::wait_for_exit(child);
                    if (exit_code != 0) {
                        BOOST_LOG_SEV(log, severity::error) << "Got non-zero exit status from '" << args << "': " << exit_code;
                        return false;
                    }
                }

                catch (boost::system::system_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to run git to check out revision " << m_revision << ": " << ex.what();
                    return false;
                }

                BOOST_LOG_SEV(log, severity::info) << "Checked out revision " << m_revision;

                return true;
            }

            boost::property_tree::ptree m_macros;
            bool loadMacroFile()
            {
                fs::path path(m_macroFile);
                if (!fs::exists(path)) {
                    BOOST_LOG_SEV(log, severity::warning) << "Macro file " << m_macroFile << " doesn't exist!";
                    return true;
                }

                if (!fs::is_regular_file(path)) {
                    BOOST_LOG_SEV(log, severity::error) << "Macro configuration " << m_macroFile << " exists but isn't a regular file!";
                    return false;
                }

                try {
                    boost::property_tree::read_ini(m_macroFile, m_macros);
                }

                catch (boost::property_tree::ptree_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to parse macros from " << m_macroFile << ": " << ex.what();
                    return false;
                }

                return true;
            }

            boost::property_tree::ptree m_buildSettings;
            bool loadBuildConfig()
            {
                std::string configFile = m_sourceDirectory + "/" + m_configFile;
                fs::path path(configFile);
                if (!fs::exists(path)) {
                    BOOST_LOG_SEV(log, severity::error) << "Build config file " << m_configFile << " doesn't exist in " << m_sourceDirectory;
                    return false;
                }

                if (!fs::is_regular_file(path)) {
                    BOOST_LOG_SEV(log, severity::error) << "Build config file " << configFile << " exists but isn't a regular file!";
                    return false;
                }

                try {
                    boost::property_tree::read_ini(configFile, m_buildSettings);
                }

                catch (boost::property_tree::ini_parser_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to parse build configuration in " << m_configFile << ": " << ex.what();
                    return false;
                }

                return true;
            }

            std::string m_binaryDir;
            bool createBinaryDir()
            {
                m_binaryDir = m_toplevelDirectory + "/build";
                fs::path path(m_binaryDir);

                if (!fs::exists(path)) {
                    BOOST_LOG_SEV(log, severity::info) << "Creating binary dir: " << m_binaryDir;
                    try {
                        fs::create_directories(path);
                    }
                    catch (boost::system::system_error& ex) {
                        BOOST_LOG_SEV(log, severity::error) << "Failed to create binary dir " << m_binaryDir << ": " << ex.what();
                        return false;
                    }
                }

                return true;
            }

        public:
            Worker(const std::string& macro_file, const std::string& build_directory,
                   const std::string& repo_name,
                   const std::string& url, const std::string& branch, const std::string& revision,
                   const std::string& config_file, const std::string& profile_name)
                : m_buildDir(build_directory)
                , m_macroFile(macro_file)
                , m_url(url)
                , m_branch(branch)
                , m_revision(revision)
                , m_configFile(config_file)
                , m_profileName(profile_name)
                , m_repoName(repo_name)
            {
            }

            void run()
            {
                if (!findGitExecutable()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to find git; build FAILED!";
                    return;
                }

                m_buildId = generateBuildId();
                BOOST_LOG_SEV(log, severity::info) << "Worker started for repo " << m_repoName
                                                   << " (profile: " << m_profileName << ", config: " << m_configFile << ") - Build ID: " << m_buildId;
                if (!initToplevelDirectory()) {
                    BOOST_LOG_SEV(log, severity::error) << "Unable to create build directory; build FAILED!";
                    return;
                }

                if (!loadMacroFile()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to load macro file; build FAILED!";
                    return;
                }

                if (!checkoutSources()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to checkout sources from " << m_url << "; build FAILED!";
                    return;
                }

                if (!createBinaryDir()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to create build directory; build FAILED!";
                    return;
                }

                if (!loadBuildConfig()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to load build configuration; build FAILED!";
                    return;
                }
            }
        };

        const std::string Worker::BUILD_ID_CHARS{ "0123456789abcdef" };
        const size_t Worker::BUILD_ID_LENGTH{ 8 };
    }
}
}

using namespace dsn::build_bot;

Worker::Worker(const std::string& macro_file, const std::string& build_directory,
               const std::string& repo_name,
               const std::string& url, const std::string& branch, const std::string& revision,
               const std::string& config_file, const std::string& profile_name)
    : m_impl(new priv::Worker(macro_file, build_directory, repo_name, url, branch, revision, config_file, profile_name))
{
}

Worker::~Worker()
{
}

void Worker::run()
{
    return m_impl->run();
}
<commit_msg>Add stub for configure step<commit_after>#include <build-bot/worker.h>

#include <boost/filesystem.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>

#include <boost/process.hpp>

namespace fs = boost::filesystem;

namespace dsn {
namespace build_bot {
    namespace priv {
        class Worker : public dsn::log::Base<Worker> {
        private:
            std::string m_url;
            std::string m_branch;
            std::string m_revision;
            std::string m_configFile;
            std::string m_profileName;
            std::string m_buildDir;
            std::string m_repoName;
            std::string m_macroFile;

            std::string generateBuildId()
            {
                std::string res;
                boost::random::random_device rng;
                boost::random::uniform_int_distribution<> dist(0, BUILD_ID_CHARS.size() - 1);

                for (size_t i = 0; i < BUILD_ID_LENGTH; i++)
                    res += BUILD_ID_CHARS[dist(rng)];

                return res;
            }

            std::string m_buildId;

            static const std::string BUILD_ID_CHARS;
            static const size_t BUILD_ID_LENGTH;

            std::string m_toplevelDirectory;

            bool initToplevelDirectory()
            {
                std::stringstream ss;
                ss << m_buildDir << "/" << m_profileName << "/" << m_repoName << "/" << m_buildId;
                m_toplevelDirectory = ss.str();
                fs::path path(m_toplevelDirectory);

                BOOST_LOG_SEV(log, severity::info) << "Toplevel build directory is " << m_toplevelDirectory;

                if (!fs::exists(path)) {
                    try {
                        fs::create_directories(path);
                    }

                    catch (boost::system::system_error& ex) {
                        BOOST_LOG_SEV(log, severity::error) << "Failed to create toplevel directory " << m_toplevelDirectory << ": " << ex.what();
                        return false;
                    }
                }

                return true;
            }

            std::string m_gitExecutable;
            bool findGitExecutable()
            {
                try {
                    m_gitExecutable = boost::process::search_path("git");
                }
                catch (std::runtime_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to locate git executable in PATH: " << ex.what();
                    return false;
                }

                if (m_gitExecutable.size() == 0) {
                    BOOST_LOG_SEV(log, severity::error) << "No git executable found in PATH!";
                    return false;
                }

                BOOST_LOG_SEV(log, severity::debug) << "Using git executable from " << m_gitExecutable;
                return true;
            }

            std::string m_sourceDirectory;
            bool checkoutSources()
            {
                m_sourceDirectory = m_toplevelDirectory + "/repo";
                BOOST_LOG_SEV(log, severity::info) << "Checking out sources from " << m_url << " to " << m_sourceDirectory;

                try {
                    std::stringstream ssArgs;
                    ssArgs << m_gitExecutable << " clone --recursive -b " << m_branch << " " << m_url << " " << m_sourceDirectory;
                    std::string args = ssArgs.str();
                    BOOST_LOG_SEV(log, severity::debug) << "Git command line is " << args;

                    boost::process::child child = boost::process::execute(boost::process::initializers::run_exe(m_gitExecutable),
                                                                          boost::process::initializers::set_cmd_line(args));
                    auto exit_code = boost::process::wait_for_exit(child);

                    if (exit_code != 0) {
                        BOOST_LOG_SEV(log, severity::error) << "Got non-zero exit status from '" << args << "': " << exit_code;
                        return false;
                    }
                }

                catch (boost::system::system_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to run git to check out sources: " << ex.what();
                    return false;
                }

                BOOST_LOG_SEV(log, severity::info) << "Repository cloned successfully. Checking out revision " << m_revision;

                try {
                    std::stringstream ssArgs;
                    ssArgs << m_gitExecutable << " checkout " << m_revision << " .";
                    std::string args = ssArgs.str();
                    BOOST_LOG_SEV(log, severity::debug) << "Git command line is " << args;
                    boost::process::child child = boost::process::execute(boost::process::initializers::run_exe(m_gitExecutable),
                                                                          boost::process::initializers::set_cmd_line(args),
                                                                          boost::process::initializers::start_in_dir(m_sourceDirectory));
                    auto exit_code = boost::process::wait_for_exit(child);
                    if (exit_code != 0) {
                        BOOST_LOG_SEV(log, severity::error) << "Got non-zero exit status from '" << args << "': " << exit_code;
                        return false;
                    }
                }

                catch (boost::system::system_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to run git to check out revision " << m_revision << ": " << ex.what();
                    return false;
                }

                BOOST_LOG_SEV(log, severity::info) << "Checked out revision " << m_revision;

                return true;
            }

            boost::property_tree::ptree m_macros;
            bool loadMacroFile()
            {
                fs::path path(m_macroFile);
                if (!fs::exists(path)) {
                    BOOST_LOG_SEV(log, severity::warning) << "Macro file " << m_macroFile << " doesn't exist!";
                    return true;
                }

                if (!fs::is_regular_file(path)) {
                    BOOST_LOG_SEV(log, severity::error) << "Macro configuration " << m_macroFile << " exists but isn't a regular file!";
                    return false;
                }

                try {
                    boost::property_tree::read_ini(m_macroFile, m_macros);
                }

                catch (boost::property_tree::ptree_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to parse macros from " << m_macroFile << ": " << ex.what();
                    return false;
                }

                return true;
            }

            boost::property_tree::ptree m_buildSettings;
            bool loadBuildConfig()
            {
                std::string configFile = m_sourceDirectory + "/" + m_configFile;
                fs::path path(configFile);
                if (!fs::exists(path)) {
                    BOOST_LOG_SEV(log, severity::error) << "Build config file " << m_configFile << " doesn't exist in " << m_sourceDirectory;
                    return false;
                }

                if (!fs::is_regular_file(path)) {
                    BOOST_LOG_SEV(log, severity::error) << "Build config file " << configFile << " exists but isn't a regular file!";
                    return false;
                }

                try {
                    boost::property_tree::read_ini(configFile, m_buildSettings);
                }

                catch (boost::property_tree::ini_parser_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to parse build configuration in " << m_configFile << ": " << ex.what();
                    return false;
                }

                return true;
            }

            std::string m_binaryDir;
            bool createBinaryDir()
            {
                m_binaryDir = m_toplevelDirectory + "/build";
                fs::path path(m_binaryDir);

                if (!fs::exists(path)) {
                    BOOST_LOG_SEV(log, severity::info) << "Creating binary dir: " << m_binaryDir;
                    try {
                        fs::create_directories(path);
                    }
                    catch (boost::system::system_error& ex) {
                        BOOST_LOG_SEV(log, severity::error) << "Failed to create binary dir " << m_binaryDir << ": " << ex.what();
                        return false;
                    }
                }

                return true;
            }

            bool configureSources()
            {
                BOOST_LOG_SEV(log, severity::info) << "Trying to configure sources";
                std::string configureCommand;
                try {
                    configureCommand = m_buildSettings.get<std::string>(m_profileName + ".cmd_configure");
                }

                catch (boost::property_tree::ptree_error& ex) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to get configure command from build settings: " << ex.what();
                    return false;
                }

                return true;
            }

        public:
            Worker(const std::string& macro_file, const std::string& build_directory,
                   const std::string& repo_name,
                   const std::string& url, const std::string& branch, const std::string& revision,
                   const std::string& config_file, const std::string& profile_name)
                : m_buildDir(build_directory)
                , m_macroFile(macro_file)
                , m_url(url)
                , m_branch(branch)
                , m_revision(revision)
                , m_configFile(config_file)
                , m_profileName(profile_name)
                , m_repoName(repo_name)
            {
            }

            void run()
            {
                if (!findGitExecutable()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to find git; build FAILED!";
                    return;
                }

                m_buildId = generateBuildId();
                BOOST_LOG_SEV(log, severity::info) << "Worker started for repo " << m_repoName
                                                   << " (profile: " << m_profileName << ", config: " << m_configFile << ") - Build ID: " << m_buildId;
                if (!initToplevelDirectory()) {
                    BOOST_LOG_SEV(log, severity::error) << "Unable to create build directory; build FAILED!";
                    return;
                }

                if (!loadMacroFile()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to load macro file; build FAILED!";
                    return;
                }

                if (!checkoutSources()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to checkout sources from " << m_url << "; build FAILED!";
                    return;
                }

                if (!createBinaryDir()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to create build directory; build FAILED!";
                    return;
                }

                if (!loadBuildConfig()) {
                    BOOST_LOG_SEV(log, severity::error) << "Failed to load build configuration; build FAILED!";
                    return;
                }

                if (!configureSources()) {
                    BOOST_LOG_SEV(log, severity::error) << "Configure step aborted; build FAILED!";
                    return;
                }
            }
        };

        const std::string Worker::BUILD_ID_CHARS{ "0123456789abcdef" };
        const size_t Worker::BUILD_ID_LENGTH{ 8 };
    }
}
}

using namespace dsn::build_bot;

Worker::Worker(const std::string& macro_file, const std::string& build_directory,
               const std::string& repo_name,
               const std::string& url, const std::string& branch, const std::string& revision,
               const std::string& config_file, const std::string& profile_name)
    : m_impl(new priv::Worker(macro_file, build_directory, repo_name, url, branch, revision, config_file, profile_name))
{
}

Worker::~Worker()
{
}

void Worker::run()
{
    return m_impl->run();
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include "aes.h"

namespace i2p
{
namespace crypto
{

#ifdef __x86_64__

	#define KeyExpansion256 \
		"pshufd	$0xff, %%xmm2, %%xmm2 \n" \
		"movaps	%%xmm1, %%xmm4 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm1 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm1 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm1 \n" \
		"pxor %%xmm2, %%xmm1 \n" \
		"movups	%%xmm1, (%%rcx) \n" \
		"aeskeygenassist $0, %%xmm1, %%xmm4 \n" \
		"pshufd	$0xaa, %%xmm4, %%xmm2 \n" \
		"movaps	%%xmm3, %%xmm4 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm3 \n" \
	    "pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm3 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm3 \n" \
		"pxor %%xmm2, %%xmm3 \n" \
		"movups	%%xmm3, 16(%%rcx) \n" \
		"add $32, %%rcx \n"

	void ECBCryptoAESNI::SetKey (const uint8_t * key)
	{
		__asm__
		(
			"movups (%%rsi), %%xmm1 \n"
			"movups 16(%%rsi), %%xmm3 \n"
			"movups %%xmm1, (%%rdi) \n"
			"movups %%xmm3, 16(%%rdi) \n"
			"lea 32(%%rdi), %%rcx \n"
			"aeskeygenassist $1, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $2, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $4, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $8, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $10, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $20, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $40, %%xmm3, %%xmm2 \n"
			// key expansion final
			"pshufd	$0xff, %%xmm2, %%xmm2 \n"
			"movaps	%%xmm1, %%xmm4 \n"
			"pslldq	$4, %%xmm4 \n"
			"pxor %%xmm4, %%xmm1 \n"
			"pslldq	$4, %%xmm4 \n"
			"pxor %%xmm4, %%xmm1 \n"
			"pslldq	$4, %%xmm4 \n"
			"pxor %%xmm4, %%xmm1 \n"
			"pxor %%xmm2, %%xmm1 \n"
			"movups	%%xmm1, (%%rcx) \n"
			: // output
			: "S" (key), "D" (m_KeySchedule) // input
			: "%rcx" // modified
		);
	}

	void ECBCryptoAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out)
	{
		__asm__
		(
			"movq %0, %%rdx \n"
			"movups	(%%rsi), %%xmm0 \n"
			"pxor (%%rdx), %%xmm0 \n"
			"aesenc	16(%%rdx), %%xmm0 \n"
			"aesenc	32(%%rdx), %%xmm0 \n"
			"aesenc	64(%%rdx), %%xmm0 \n"
			"aesenc	80(%%rdx), %%xmm0 \n"
			"aesenc	96(%%rdx), %%xmm0 \n"
			"aesenc	112(%%rdx), %%xmm0 \n"
			"aesenc	128(%%rdx), %%xmm0 \n"
			"aesenc	144(%%rdx), %%xmm0 \n"
			"aesenc	160(%%rdx), %%xmm0 \n"
			"aesenc	176(%%rdx), %%xmm0 \n"
			"aesenc	192(%%rdx), %%xmm0 \n"
			"aesenc	208(%%rdx), %%xmm0 \n"
			"aesenclast	224(%%rdx), %%xmm0 \n"
			"movups	%%xmm0, (%%rdi) \n"
			:
			: "r" ((uint64_t)m_KeySchedule), "S" (in), "D" (out)
			: "%rdx"
		);
	}

	void ECBCryptoAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out)
	{
		__asm__
		(
			"movq %0, %%rdx \n"
			"movups	(%%rsi), %%xmm0 \n"
			"pxor 224(%%rdx), %%xmm0 \n"
			"aesdec	208(%%rdx), %%xmm0 \n"
			"aesdec	192(%%rdx), %%xmm0 \n"
			"aesdec	176(%%rdx), %%xmm0 \n"
			"aesdec	160(%%rdx), %%xmm0 \n"
			"aesdec	144(%%rdx), %%xmm0 \n"
			"aesdec	128(%%rdx), %%xmm0 \n"
			"aesdec	112(%%rdx), %%xmm0 \n"
			"aesdec	96(%%rdx), %%xmm0 \n"
			"aesdec	80(%%rdx), %%xmm0 \n"
			"aesdec	64(%%rdx), %%xmm0 \n"
			"aesdec	32(%%rdx), %%xmm0 \n"
			"aesdec	16(%%rdx), %%xmm0 \n"
			"aesdeclast (%%rdx), %%xmm0 \n"
			"movups	%%xmm0, (%%rdi) \n"
			:
			: "r" ((uint64_t)m_KeySchedule), "S" (in), "D" (out)
			: "%rdx"
		);
	}

#endif

	void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
	{
		for (int i = 0; i < numBlocks; i++)
		{
			m_LastBlock.ll[0] ^= in[i].ll[0];
			m_LastBlock.ll[1] ^= in[i].ll[1];
			m_ECBEncryption.ProcessData (m_LastBlock.buf, m_LastBlock.buf, 16);
			out[i] = m_LastBlock;
		}
	}

	bool CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out)
	{
		div_t d = div (len, 16);
		if (d.rem) return false; // len is not multipple of 16
		Encrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out);
		return true;
	}

	void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
	{
		for (int i = 0; i < numBlocks; i++)
		{
			ChipherBlock tmp = in[i];
			m_ECBDecryption.ProcessData (out[i].buf, in[i].buf, 16);
			out[i].ll[0] ^= m_IV.ll[0];
			out[i].ll[1] ^= m_IV.ll[1];
			m_IV = tmp;
		}
	}

	bool CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out)
	{
		div_t d = div (len, 16);
		if (d.rem) return false; // len is not multipple of 16
		Decrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out);
		return true;
	}
}
}

<commit_msg>load pointer to rdx directly<commit_after>#include <stdlib.h>
#include "aes.h"

namespace i2p
{
namespace crypto
{

#ifdef __x86_64__

	#define KeyExpansion256 \
		"pshufd	$0xff, %%xmm2, %%xmm2 \n" \
		"movaps	%%xmm1, %%xmm4 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm1 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm1 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm1 \n" \
		"pxor %%xmm2, %%xmm1 \n" \
		"movups	%%xmm1, (%%rcx) \n" \
		"aeskeygenassist $0, %%xmm1, %%xmm4 \n" \
		"pshufd	$0xaa, %%xmm4, %%xmm2 \n" \
		"movaps	%%xmm3, %%xmm4 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm3 \n" \
	    "pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm3 \n" \
		"pslldq	$4, %%xmm4 \n" \
		"pxor %%xmm4, %%xmm3 \n" \
		"pxor %%xmm2, %%xmm3 \n" \
		"movups	%%xmm3, 16(%%rcx) \n" \
		"add $32, %%rcx \n"

	void ECBCryptoAESNI::SetKey (const uint8_t * key)
	{
		__asm__
		(
			"movups (%%rsi), %%xmm1 \n"
			"movups 16(%%rsi), %%xmm3 \n"
			"movups %%xmm1, (%%rdi) \n"
			"movups %%xmm3, 16(%%rdi) \n"
			"lea 32(%%rdi), %%rcx \n"
			"aeskeygenassist $1, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $2, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $4, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $8, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $10, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $20, %%xmm3, %%xmm2 \n"
			KeyExpansion256
			"aeskeygenassist $40, %%xmm3, %%xmm2 \n"
			// key expansion final
			"pshufd	$0xff, %%xmm2, %%xmm2 \n"
			"movaps	%%xmm1, %%xmm4 \n"
			"pslldq	$4, %%xmm4 \n"
			"pxor %%xmm4, %%xmm1 \n"
			"pslldq	$4, %%xmm4 \n"
			"pxor %%xmm4, %%xmm1 \n"
			"pslldq	$4, %%xmm4 \n"
			"pxor %%xmm4, %%xmm1 \n"
			"pxor %%xmm2, %%xmm1 \n"
			"movups	%%xmm1, (%%rcx) \n"
			: // output
			: "S" (key), "D" (m_KeySchedule) // input
			: "%rcx" // modified
		);
	}

	void ECBCryptoAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out)
	{
		__asm__
		(
			"movups	(%%rsi), %%xmm0 \n"
			"pxor (%%rdx), %%xmm0 \n"
			"aesenc	16(%%rdx), %%xmm0 \n"
			"aesenc	32(%%rdx), %%xmm0 \n"
			"aesenc	64(%%rdx), %%xmm0 \n"
			"aesenc	80(%%rdx), %%xmm0 \n"
			"aesenc	96(%%rdx), %%xmm0 \n"
			"aesenc	112(%%rdx), %%xmm0 \n"
			"aesenc	128(%%rdx), %%xmm0 \n"
			"aesenc	144(%%rdx), %%xmm0 \n"
			"aesenc	160(%%rdx), %%xmm0 \n"
			"aesenc	176(%%rdx), %%xmm0 \n"
			"aesenc	192(%%rdx), %%xmm0 \n"
			"aesenc	208(%%rdx), %%xmm0 \n"
			"aesenclast	224(%%rdx), %%xmm0 \n"
			"movups	%%xmm0, (%%rdi) \n"
			: : "d" ((uint64_t)m_KeySchedule), "S" (in), "D" (out)
		);
	}

	void ECBCryptoAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out)
	{
		__asm__
		(
			"movups	(%%rsi), %%xmm0 \n"
			"pxor 224(%%rdx), %%xmm0 \n"
			"aesdec	208(%%rdx), %%xmm0 \n"
			"aesdec	192(%%rdx), %%xmm0 \n"
			"aesdec	176(%%rdx), %%xmm0 \n"
			"aesdec	160(%%rdx), %%xmm0 \n"
			"aesdec	144(%%rdx), %%xmm0 \n"
			"aesdec	128(%%rdx), %%xmm0 \n"
			"aesdec	112(%%rdx), %%xmm0 \n"
			"aesdec	96(%%rdx), %%xmm0 \n"
			"aesdec	80(%%rdx), %%xmm0 \n"
			"aesdec	64(%%rdx), %%xmm0 \n"
			"aesdec	32(%%rdx), %%xmm0 \n"
			"aesdec	16(%%rdx), %%xmm0 \n"
			"aesdeclast (%%rdx), %%xmm0 \n"
			"movups	%%xmm0, (%%rdi) \n"
			: : "d" ((uint64_t)m_KeySchedule), "S" (in), "D" (out)
		);
	}

#endif

	void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
	{
		for (int i = 0; i < numBlocks; i++)
		{
			m_LastBlock.ll[0] ^= in[i].ll[0];
			m_LastBlock.ll[1] ^= in[i].ll[1];
			m_ECBEncryption.ProcessData (m_LastBlock.buf, m_LastBlock.buf, 16);
			out[i] = m_LastBlock;
		}
	}

	bool CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out)
	{
		div_t d = div (len, 16);
		if (d.rem) return false; // len is not multipple of 16
		Encrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out);
		return true;
	}

	void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
	{
		for (int i = 0; i < numBlocks; i++)
		{
			ChipherBlock tmp = in[i];
			m_ECBDecryption.ProcessData (out[i].buf, in[i].buf, 16);
			out[i].ll[0] ^= m_IV.ll[0];
			out[i].ll[1] ^= m_IV.ll[1];
			m_IV = tmp;
		}
	}

	bool CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out)
	{
		div_t d = div (len, 16);
		if (d.rem) return false; // len is not multipple of 16
		Decrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out);
		return true;
	}
}
}

<|endoftext|>