<commit_before>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/

#include <DTK_DetailsDistributedSearchTreeImpl.hpp>

#include <Teuchos_UnitTestHarness.hpp>

#include <algorithm> // fill
#include <set>
#include <vector>

TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DetailsDistributedSearchTreeImpl,
                                   sort_results, DeviceType )
{
    std::vector<int> ids_ = {4, 3, 2, 1, 4, 3, 2, 4, 3, 4};
    std::vector<int> sorted_ids = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
    std::vector<int> offset = {0, 1, 3, 6, 10};
    int const n = 10;
    int const m = 4;
    TEST_EQUALITY( ids_.size(), n );
    TEST_EQUALITY( sorted_ids.size(), n );
    TEST_EQUALITY( offset.size(), m + 1 );
    std::vector<int> results_ = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::vector<std::set<int>> sorted_results = {
        {3},
        {6, 2},
        {8, 5, 1},
        {9, 7, 4, 0},
    };
    std::vector<int> ranks_ = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
    std::vector<std::set<int>> sorted_ranks = {
        {13},
        {16, 12},
        {18, 15, 11},
        {19, 17, 14, 10},
    };
    TEST_EQUALITY( results_.size(), n );
    TEST_EQUALITY( ranks_.size(), n );

    Kokkos::View<int *, DeviceType> ids( "query_ids", n );
    auto ids_host = Kokkos::create_mirror_view( ids );
    for ( int i = 0; i < n; ++i )
        ids_host( i ) = ids_[i];
    Kokkos::deep_copy( ids, ids_host );

    Kokkos::View<int *, DeviceType> results( "results", n );
    auto results_host = Kokkos::create_mirror_view( results );
    for ( int i = 0; i < n; ++i )
        results_host( i ) = results_[i];
    Kokkos::deep_copy( results, results_host );

    Kokkos::View<int *, DeviceType> ranks( "ranks", n );
    auto ranks_host = Kokkos::create_mirror_view( ranks );
    for ( int i = 0; i < n; ++i )
        ranks_host( i ) = ranks_[i];
    Kokkos::deep_copy( ranks, ranks_host );

    DataTransferKit::Details::DistributedSearchTreeImpl<
        DeviceType>::sortResults( ids, results, ranks );

    // COMMENT: ids are untouched
    Kokkos::deep_copy( ids_host, ids );
    TEST_COMPARE_ARRAYS( ids_host, ids_ );

    Kokkos::deep_copy( results_host, results );
    Kokkos::deep_copy( ranks_host, ranks );
    for ( int q = 0; q < m; ++q )
        for ( int i = offset[q]; i < offset[q + 1]; ++i )
        {
            TEST_EQUALITY( sorted_results[q].count( results_host[i] ), 1 );
            TEST_EQUALITY( sorted_ranks[q].count( ranks_host[i] ), 1 );
        }

    Kokkos::View<int *, DeviceType> not_sized_properly( "", m );
    TEST_THROW( DataTransferKit::Details::DistributedSearchTreeImpl<
                    DeviceType>::sortResults( ids, not_sized_properly ),
                DataTransferKit::DataTransferKitException );
}

TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DetailsDistributedSearchTreeImpl,
                                   count_results, DeviceType )
{
    std::vector<int> ids_ref = {4, 3, 2, 1, 4, 3, 2, 4, 3, 4};
    std::vector<int> offset_ref = {
        0, 0, 1, 3, 6, 10,
    };
    int const m = 5;
    int const nnz = 10;
    TEST_EQUALITY( ids_ref.size(), nnz );
    TEST_EQUALITY( offset_ref.size(), m + 1 );

    Kokkos::View<int *, DeviceType> ids( "query_ids", nnz );
    auto ids_host = Kokkos::create_mirror_view( ids );
    for ( int i = 0; i < nnz; ++i )
        ids_host( i ) = ids_ref[i];
    Kokkos::deep_copy( ids, ids_host );

    Kokkos::View<int *, DeviceType> offset( "offset" );

    DataTransferKit::Details::DistributedSearchTreeImpl<
        DeviceType>::countResults( m, ids, offset );

    auto offset_host = Kokkos::create_mirror_view( offset );
    Kokkos::deep_copy( offset_host, offset );
    TEST_COMPARE_ARRAYS( offset_host, offset_ref );
}

template <typename View1, typename View2>
inline void checkViewWasNotAllocated( View1 const &v1, View2 const &v2,
                                      bool &success,
                                      Teuchos::FancyOStream &out )
{
    // NOTE: cannot use operator== here because array layout may "change" for
    // rank-1 views
    TEST_EQUALITY( v1.data(), v2.data() );
    TEST_EQUALITY( v1.span(), v2.span() );

    TEST_EQUALITY( (int)View1::rank, (int)View2::rank );
    TEST_ASSERT( ( std::is_same<typename View1::const_value_type,
                                typename View2::const_value_type>::value ) );
    TEST_ASSERT( ( std::is_same<typename View1::memory_space,
                                typename View2::memory_space>::value ) );

    TEST_EQUALITY( v1.dimension_0(), v2.dimension_0() );
    TEST_EQUALITY( v1.dimension_1(), v2.dimension_1() );
    TEST_EQUALITY( v1.dimension_2(), v2.dimension_2() );
    TEST_EQUALITY( v1.dimension_3(), v2.dimension_3() );
    TEST_EQUALITY( v1.dimension_4(), v2.dimension_4() );
    TEST_EQUALITY( v1.dimension_5(), v2.dimension_5() );
    TEST_EQUALITY( v1.dimension_6(), v2.dimension_6() );
    TEST_EQUALITY( v1.dimension_7(), v2.dimension_7() );
}

template <typename View1, typename View2>
inline void checkNewViewWasAllocated( View1 const &v1, View2 const &v2,
                                      bool &success,
                                      Teuchos::FancyOStream &out )
{
    TEST_INEQUALITY( v1.data(), v2.data() );

    TEST_EQUALITY( (int)View1::rank, (int)View2::rank );
    TEST_ASSERT( ( std::is_same<typename View1::const_value_type,
                                typename View2::const_value_type>::value ) );

    TEST_EQUALITY( v1.dimension_0(), v2.dimension_0() );
    TEST_EQUALITY( v1.dimension_1(), v2.dimension_1() );
    TEST_EQUALITY( v1.dimension_2(), v2.dimension_2() );
    TEST_EQUALITY( v1.dimension_3(), v2.dimension_3() );
    TEST_EQUALITY( v1.dimension_4(), v2.dimension_4() );
    TEST_EQUALITY( v1.dimension_5(), v2.dimension_5() );
    TEST_EQUALITY( v1.dimension_6(), v2.dimension_6() );
    TEST_EQUALITY( v1.dimension_7(), v2.dimension_7() );
}

TEUCHOS_UNIT_TEST( DetailsDistributedSearchTreeImpl,
                   create_layout_right_mirror_view )
{
    using DataTransferKit::Details::create_layout_right_mirror_view;
    using Kokkos::ALL;
    using Kokkos::LayoutLeft;
    using Kokkos::LayoutRight;
    using Kokkos::make_pair;
    using Kokkos::subview;
    using Kokkos::View;

    // rank-1 and not strided -> do not allocate
    View<int *, LayoutLeft> u( "u", 255 );
    auto u_h = create_layout_right_mirror_view( u );
    checkViewWasNotAllocated( u, u_h, success, out );

    // right layout -> do not allocate
    View<int **, LayoutRight> v( "v", 2, 3 );
    auto v_h = create_layout_right_mirror_view( v );
    checkViewWasNotAllocated( v, v_h, success, out );

    // left layout and rank > 1 -> allocate
    View<int **, LayoutLeft> w( "w", 4, 5 );
    auto w_h = create_layout_right_mirror_view( w );
    checkNewViewWasAllocated( w, w_h, success, out );

    // strided layout -> allocate
    auto x = subview( v, ALL, 0 );
    auto x_h = create_layout_right_mirror_view( x );
    checkNewViewWasAllocated( x, x_h, success, out );

    // subview is rank-1 and not strided -> do not allocate
    auto y = subview( u, make_pair( 8, 16 ) );
    auto y_h = create_layout_right_mirror_view( y );
    checkViewWasNotAllocated( y, y_h, success, out );
}

// Include the test macros.
#include "DataTransferKit_ETIHelperMacros.h"

// Create the test group
#define UNIT_TEST_GROUP( NODE )                                                \
    using DeviceType##NODE = typename NODE::device_type;                       \
    TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DetailsDistributedSearchTreeImpl,    \
                                          sort_results, DeviceType##NODE )     \
    TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DetailsDistributedSearchTreeImpl,    \
                                          count_results, DeviceType##NODE )

// Demangle the types
DTK_ETI_MANGLING_TYPEDEFS()

// Instantiate the tests
DTK_INSTANTIATE_N( UNIT_TEST_GROUP )
<commit_msg>Add tests for sortAndDetermineBufferLayout()<commit_after>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/

#include <DTK_DetailsDistributedSearchTreeImpl.hpp>

#include <Teuchos_UnitTestHarness.hpp>

#include <algorithm> // fill
#include <set>
#include <vector>

TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DetailsDistributedSearchTreeImpl,
                                   sort_results, DeviceType )
{
    std::vector<int> ids_ = {4, 3, 2, 1, 4, 3, 2, 4, 3, 4};
    std::vector<int> sorted_ids = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
    std::vector<int> offset = {0, 1, 3, 6, 10};
    int const n = 10;
    int const m = 4;
    TEST_EQUALITY( ids_.size(), n );
    TEST_EQUALITY( sorted_ids.size(), n );
    TEST_EQUALITY( offset.size(), m + 1 );
    std::vector<int> results_ = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::vector<std::set<int>> sorted_results = {
        {3},
        {6, 2},
        {8, 5, 1},
        {9, 7, 4, 0},
    };
    std::vector<int> ranks_ = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
    std::vector<std::set<int>> sorted_ranks = {
        {13},
        {16, 12},
        {18, 15, 11},
        {19, 17, 14, 10},
    };
    TEST_EQUALITY( results_.size(), n );
    TEST_EQUALITY( ranks_.size(), n );

    Kokkos::View<int *, DeviceType> ids( "query_ids", n );
    auto ids_host = Kokkos::create_mirror_view( ids );
    for ( int i = 0; i < n; ++i )
        ids_host( i ) = ids_[i];
    Kokkos::deep_copy( ids, ids_host );

    Kokkos::View<int *, DeviceType> results( "results", n );
    auto results_host = Kokkos::create_mirror_view( results );
    for ( int i = 0; i < n; ++i )
        results_host( i ) = results_[i];
    Kokkos::deep_copy( results, results_host );

    Kokkos::View<int *, DeviceType> ranks( "ranks", n );
    auto ranks_host = Kokkos::create_mirror_view( ranks );
    for ( int i = 0; i < n; ++i )
        ranks_host( i ) = ranks_[i];
    Kokkos::deep_copy( ranks, ranks_host );

    DataTransferKit::Details::DistributedSearchTreeImpl<
        DeviceType>::sortResults( ids, results, ranks );

    // COMMENT: ids are untouched
    Kokkos::deep_copy( ids_host, ids );
    TEST_COMPARE_ARRAYS( ids_host, ids_ );

    Kokkos::deep_copy( results_host, results );
    Kokkos::deep_copy( ranks_host, ranks );
    for ( int q = 0; q < m; ++q )
        for ( int i = offset[q]; i < offset[q + 1]; ++i )
        {
            TEST_EQUALITY( sorted_results[q].count( results_host[i] ), 1 );
            TEST_EQUALITY( sorted_ranks[q].count( ranks_host[i] ), 1 );
        }

    Kokkos::View<int *, DeviceType> not_sized_properly( "", m );
    TEST_THROW( DataTransferKit::Details::DistributedSearchTreeImpl<
                    DeviceType>::sortResults( ids, not_sized_properly ),
                DataTransferKit::DataTransferKitException );
}

TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DetailsDistributedSearchTreeImpl,
                                   count_results, DeviceType )
{
    std::vector<int> ids_ref = {4, 3, 2, 1, 4, 3, 2, 4, 3, 4};
    std::vector<int> offset_ref = {
        0, 0, 1, 3, 6, 10,
    };
    int const m = 5;
    int const nnz = 10;
    TEST_EQUALITY( ids_ref.size(), nnz );
    TEST_EQUALITY( offset_ref.size(), m + 1 );

    Kokkos::View<int *, DeviceType> ids( "query_ids", nnz );
    auto ids_host = Kokkos::create_mirror_view( ids );
    for ( int i = 0; i < nnz; ++i )
        ids_host( i ) = ids_ref[i];
    Kokkos::deep_copy( ids, ids_host );

    Kokkos::View<int *, DeviceType> offset( "offset" );

    DataTransferKit::Details::DistributedSearchTreeImpl<
        DeviceType>::countResults( m, ids, offset );

    auto offset_host = Kokkos::create_mirror_view( offset );
    Kokkos::deep_copy( offset_host, offset );
    TEST_COMPARE_ARRAYS( offset_host, offset_ref );
}

template <typename View1, typename View2>
inline void checkViewWasNotAllocated( View1 const &v1, View2 const &v2,
                                      bool &success,
                                      Teuchos::FancyOStream &out )
{
    // NOTE: cannot use operator== here because array layout may "change" for
    // rank-1 views
    TEST_EQUALITY( v1.data(), v2.data() );
    TEST_EQUALITY( v1.span(), v2.span() );

    TEST_EQUALITY( (int)View1::rank, (int)View2::rank );
    TEST_ASSERT( ( std::is_same<typename View1::const_value_type,
                                typename View2::const_value_type>::value ) );
    TEST_ASSERT( ( std::is_same<typename View1::memory_space,
                                typename View2::memory_space>::value ) );

    TEST_EQUALITY( v1.dimension_0(), v2.dimension_0() );
    TEST_EQUALITY( v1.dimension_1(), v2.dimension_1() );
    TEST_EQUALITY( v1.dimension_2(), v2.dimension_2() );
    TEST_EQUALITY( v1.dimension_3(), v2.dimension_3() );
    TEST_EQUALITY( v1.dimension_4(), v2.dimension_4() );
    TEST_EQUALITY( v1.dimension_5(), v2.dimension_5() );
    TEST_EQUALITY( v1.dimension_6(), v2.dimension_6() );
    TEST_EQUALITY( v1.dimension_7(), v2.dimension_7() );
}

template <typename View1, typename View2>
inline void checkNewViewWasAllocated( View1 const &v1, View2 const &v2,
                                      bool &success,
                                      Teuchos::FancyOStream &out )
{
    TEST_INEQUALITY( v1.data(), v2.data() );

    TEST_EQUALITY( (int)View1::rank, (int)View2::rank );
    TEST_ASSERT( ( std::is_same<typename View1::const_value_type,
                                typename View2::const_value_type>::value ) );

    TEST_EQUALITY( v1.dimension_0(), v2.dimension_0() );
    TEST_EQUALITY( v1.dimension_1(), v2.dimension_1() );
    TEST_EQUALITY( v1.dimension_2(), v2.dimension_2() );
    TEST_EQUALITY( v1.dimension_3(), v2.dimension_3() );
    TEST_EQUALITY( v1.dimension_4(), v2.dimension_4() );
    TEST_EQUALITY( v1.dimension_5(), v2.dimension_5() );
    TEST_EQUALITY( v1.dimension_6(), v2.dimension_6() );
    TEST_EQUALITY( v1.dimension_7(), v2.dimension_7() );
}

TEUCHOS_UNIT_TEST( DetailsDistributedSearchTreeImpl,
                   create_layout_right_mirror_view )
{
    using DataTransferKit::Details::create_layout_right_mirror_view;
    using Kokkos::ALL;
    using Kokkos::LayoutLeft;
    using Kokkos::LayoutRight;
    using Kokkos::make_pair;
    using Kokkos::subview;
    using Kokkos::View;

    // rank-1 and not strided -> do not allocate
    View<int *, LayoutLeft> u( "u", 255 );
    auto u_h = create_layout_right_mirror_view( u );
    checkViewWasNotAllocated( u, u_h, success, out );

    // right layout -> do not allocate
    View<int **, LayoutRight> v( "v", 2, 3 );
    auto v_h = create_layout_right_mirror_view( v );
    checkViewWasNotAllocated( v, v_h, success, out );

    // left layout and rank > 1 -> allocate
    View<int **, LayoutLeft> w( "w", 4, 5 );
    auto w_h = create_layout_right_mirror_view( w );
    checkNewViewWasAllocated( w, w_h, success, out );

    // strided layout -> allocate
    auto x = subview( v, ALL, 0 );
    auto x_h = create_layout_right_mirror_view( x );
    checkNewViewWasAllocated( x, x_h, success, out );

    // subview is rank-1 and not strided -> do not allocate
    auto y = subview( u, make_pair( 8, 16 ) );
    auto y_h = create_layout_right_mirror_view( y );
    checkViewWasNotAllocated( y, y_h, success, out );
}

void checkBufferLayout( std::vector<int> const &ranks,
                        std::vector<int> const &permute_ref,
                        std::vector<int> const &unique_ref,
                        std::vector<int> const &counts_ref,
                        std::vector<int> const &offsets_ref, bool &success,
                        Teuchos::FancyOStream &out )
{
    std::vector<int> permute( ranks.size() );
    std::vector<int> unique;
    std::vector<int> counts;
    std::vector<int> offsets;
    DataTransferKit::Details::sortAndDetermineBufferLayout(
        Kokkos::View<int const *, Kokkos::HostSpace,
                     Kokkos::MemoryTraits<Kokkos::Unmanaged>>( ranks.data(),
                                                               ranks.size() ),
        Kokkos::View<int *, Kokkos::HostSpace,
                     Kokkos::MemoryTraits<Kokkos::Unmanaged>>( permute.data(),
                                                               permute.size() ),
        unique, counts, offsets );
    TEST_COMPARE_ARRAYS( permute_ref, permute );
    TEST_COMPARE_ARRAYS( unique_ref, unique );
    TEST_COMPARE_ARRAYS( counts_ref, counts );
    TEST_COMPARE_ARRAYS( offsets_ref, offsets );
}

TEUCHOS_UNIT_TEST( DetailsDistributor, sort_and_determine_buffer_layout )
{
    checkBufferLayout( {}, {}, {}, {}, {0}, success, out );
    checkBufferLayout( {2, 2}, {0, 1}, {2}, {2}, {0, 2}, success, out );
    checkBufferLayout( {3, 3, 2, 3, 2, 1}, {0, 1, 3, 2, 4, 5}, {3, 2, 1},
                       {3, 2, 1}, {0, 3, 5, 6}, success, out );
    checkBufferLayout( {1, 2, 3, 2, 3, 3}, {5, 3, 0, 4, 1, 2}, {3, 2, 1},
                       {3, 2, 1}, {0, 3, 5, 6}, success, out );
    checkBufferLayout( {0, 1, 2, 3}, {3, 2, 1, 0}, {3, 2, 1, 0}, {1, 1, 1, 1},
                       {0, 1, 2, 3, 4}, success, out );
}

// Include the test macros.
#include "DataTransferKit_ETIHelperMacros.h"

// Create the test group
#define UNIT_TEST_GROUP( NODE )                                                \
    using DeviceType##NODE = typename NODE::device_type;                       \
    TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DetailsDistributedSearchTreeImpl,    \
                                          sort_results, DeviceType##NODE )     \
    TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DetailsDistributedSearchTreeImpl,    \
                                          count_results, DeviceType##NODE )

// Demangle the types
DTK_ETI_MANGLING_TYPEDEFS()

// Instantiate the tests
DTK_INSTANTIATE_N( UNIT_TEST_GROUP )
<|endoftext|>


<commit_before>#include "sendcoinsdialog.h"
#include "ui_sendcoinsdialog.h"
#include "walletmodel.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "optionsmodel.h"
#include "sendcoinsentry.h"
#include "guiutil.h"
#include "askpassphrasedialog.h"
#include "base58.h"

#include <QMessageBox>
#include <QLocale>
#include <QTextDocument>
#include <QScrollBar>

SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SendCoinsDialog),
    model(0)
{
    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->addButton->setIcon(QIcon());
    ui->clearButton->setIcon(QIcon());
    ui->sendButton->setIcon(QIcon());
#endif

    addEntry();

    connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    fNewRecipientAllowed = true;
}

void SendCoinsDialog::setModel(WalletModel *model)
{
    this->model = model;

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            entry->setModel(model);
        }
    }
    if(model && model->getOptionsModel())
    {
        setBalance(model->getBalance(), model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance());
        connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64)));
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
    }
}

SendCoinsDialog::~SendCoinsDialog()
{
    delete ui;
}

void SendCoinsDialog::on_sendButton_clicked()
{
    QList<SendCoinsRecipient> recipients;
    bool valid = true;

    if(!model)
        return;

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            if(entry->validate())
            {
                recipients.append(entry->getValue());
            }
            else
            {
                valid = false;
            }
        }
    }

    if(!valid || recipients.isEmpty())
    {
        return;
    }

    // Format confirmation message
    QStringList formatted;
    foreach(const SendCoinsRecipient &rcp, recipients)
    {
        formatted.append(tr("%1 to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), Qt::escape(rcp.label), rcp.address));
    }

    fNewRecipientAllowed = false;

    QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
                          tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))),
          QMessageBox::Yes|QMessageBox::Cancel,
          QMessageBox::Cancel);

    if(retval != QMessageBox::Yes)
    {
        fNewRecipientAllowed = true;
        return;
    }

    WalletModel::UnlockContext ctx(model->requestUnlock());
    if(!ctx.isValid())
    {
        // Unlock wallet was cancelled
        fNewRecipientAllowed = true;
        return;
    }

    WalletModel::SendCoinsReturn sendstatus = model->sendCoins(recipients);
    switch(sendstatus.status)
    {
    case WalletModel::InvalidAddress:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("The recipient address is not valid, please recheck."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::InvalidAmount:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("The amount to pay must be larger than 0."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::AmountExceedsBalance:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("The amount exceeds your balance."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::AmountWithFeeExceedsBalance:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("The total exceeds your balance when the %1 transaction fee is included.").
            arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::DuplicateAddress:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("Duplicate address found, can only send to each address once per send operation."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::TransactionCreationFailed:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("Error: Transaction creation failed."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::TransactionCommitFailed:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::Aborted: // User aborted, nothing to do
        break;
    case WalletModel::OK:
        accept();
        break;
    }
    fNewRecipientAllowed = true;
}

void SendCoinsDialog::clear()
{
    // Remove entries until only one left
    while(ui->entries->count())
    {
        delete ui->entries->takeAt(0)->widget();
    }
    addEntry();

    updateRemoveEnabled();

    ui->sendButton->setDefault(true);
}

void SendCoinsDialog::reject()
{
    clear();
}

void SendCoinsDialog::accept()
{
    clear();
}

SendCoinsEntry *SendCoinsDialog::addEntry()
{
    SendCoinsEntry *entry = new SendCoinsEntry(this);
    entry->setModel(model);
    ui->entries->addWidget(entry);
    connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*)));

    updateRemoveEnabled();

    // Focus the field, so that entry can start immediately
    entry->clear();
    entry->setFocus();
    ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
    QCoreApplication::instance()->processEvents();
    QScrollBar* bar = ui->scrollArea->verticalScrollBar();
    if(bar)
        bar->setSliderPosition(bar->maximum());
    return entry;
}

void SendCoinsDialog::updateRemoveEnabled()
{
    // Remove buttons are enabled as soon as there is more than one send-entry
    bool enabled = (ui->entries->count() > 1);
    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            entry->setRemoveEnabled(enabled);
        }
    }
    setupTabChain(0);
}

void SendCoinsDialog::removeEntry(SendCoinsEntry* entry)
{
    delete entry;
    updateRemoveEnabled();
}

QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
{
    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            prev = entry->setupTabChain(prev);
        }
    }
    QWidget::setTabOrder(prev, ui->addButton);
    QWidget::setTabOrder(ui->addButton, ui->sendButton);
    return ui->sendButton;
}

void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
{
    if(!fNewRecipientAllowed)
        return;

    SendCoinsEntry *entry = 0;
    // Replace the first entry if it is still unused
    if(ui->entries->count() == 1)
    {
        SendCoinsEntry *first = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
        if(first->isClear())
        {
            entry = first;
        }
    }
    if(!entry)
    {
        entry = addEntry();
    }

    entry->setValue(rv);
}

bool SendCoinsDialog::handleURI(const QString &uri)
{
    SendCoinsRecipient rv;
    // URI has to be valid
    if (GUIUtil::parseBitcoinURI(uri, &rv))
    {
        CBitcoinAddress address(rv.address.toStdString());
        if (!address.IsValid())
            return false;
        pasteEntry(rv);
        return true;
    }

    return false;
}

void SendCoinsDialog::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance)
{
    Q_UNUSED(stake);
    Q_UNUSED(unconfirmedBalance);
    Q_UNUSED(immatureBalance);
    if(!model || !model->getOptionsModel())
        return;

    int unit = model->getOptionsModel()->getDisplayUnit();
    ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
}

void SendCoinsDialog::updateDisplayUnit()
{
    if(model && model->getOptionsModel())
    {
        // Update labelBalance with the current balance and the current unit
        ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->getBalance()));
    }
}
<commit_msg>Update sendcoinsdialog.cpp<commit_after>#include "sendcoinsdialog.h"
#include "ui_sendcoinsdialog.h"
#include "walletmodel.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "optionsmodel.h"
#include "sendcoinsentry.h"
#include "guiutil.h"
#include "askpassphrasedialog.h"
#include "base58.h"

#include <QMessageBox>
#include <QLocale>
#include <QTextDocument>
#include <QScrollBar>

SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SendCoinsDialog),
    model(0)
{
    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->addButton->setIcon(QIcon());
    ui->clearButton->setIcon(QIcon());
    ui->sendButton->setIcon(QIcon());
#endif

    addEntry();

    connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    fNewRecipientAllowed = true;
}

void SendCoinsDialog::setModel(WalletModel *model)
{
    this->model = model;

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            entry->setModel(model);
        }
    }
    if(model && model->getOptionsModel())
    {
        setBalance(model->getBalance(), model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance());
        connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64)));
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
    }
}

SendCoinsDialog::~SendCoinsDialog()
{
    delete ui;
}

void SendCoinsDialog::on_sendButton_clicked()
{
    QList<SendCoinsRecipient> recipients;
    bool valid = true;

    if(!model)
        return;

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            if(entry->validate())
            {
                recipients.append(entry->getValue());
            }
            else
            {
                valid = false;
            }
        }
    }

    if(!valid || recipients.isEmpty())
    {
        return;
    }

    // Format confirmation message
    QStringList formatted;
    foreach(const SendCoinsRecipient &rcp, recipients)
    {
    #if QT_VERSION < 0x050000
        formatted.append(tr("%1 to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), Qt::escape(rcp.label), rcp.address));
    #else
	formatted.append(tr("%1 to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), rcp.label.toHtmlEscaped(), rcp.address));
    #endif
    }

    fNewRecipientAllowed = false;

    QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
                          tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))),
          QMessageBox::Yes|QMessageBox::Cancel,
          QMessageBox::Cancel);

    if(retval != QMessageBox::Yes)
    {
        fNewRecipientAllowed = true;
        return;
    }

    WalletModel::UnlockContext ctx(model->requestUnlock());
    if(!ctx.isValid())
    {
        // Unlock wallet was cancelled
        fNewRecipientAllowed = true;
        return;
    }

    WalletModel::SendCoinsReturn sendstatus = model->sendCoins(recipients);
    switch(sendstatus.status)
    {
    case WalletModel::InvalidAddress:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("The recipient address is not valid, please recheck."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::InvalidAmount:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("The amount to pay must be larger than 0."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::AmountExceedsBalance:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("The amount exceeds your balance."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::AmountWithFeeExceedsBalance:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("The total exceeds your balance when the %1 transaction fee is included.").
            arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::DuplicateAddress:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("Duplicate address found, can only send to each address once per send operation."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::TransactionCreationFailed:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("Error: Transaction creation failed."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::TransactionCommitFailed:
        QMessageBox::warning(this, tr("Send Coins"),
            tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case WalletModel::Aborted: // User aborted, nothing to do
        break;
    case WalletModel::OK:
        accept();
        break;
    }
    fNewRecipientAllowed = true;
}

void SendCoinsDialog::clear()
{
    // Remove entries until only one left
    while(ui->entries->count())
    {
        delete ui->entries->takeAt(0)->widget();
    }
    addEntry();

    updateRemoveEnabled();

    ui->sendButton->setDefault(true);
}

void SendCoinsDialog::reject()
{
    clear();
}

void SendCoinsDialog::accept()
{
    clear();
}

SendCoinsEntry *SendCoinsDialog::addEntry()
{
    SendCoinsEntry *entry = new SendCoinsEntry(this);
    entry->setModel(model);
    ui->entries->addWidget(entry);
    connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*)));

    updateRemoveEnabled();

    // Focus the field, so that entry can start immediately
    entry->clear();
    entry->setFocus();
    ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
    QCoreApplication::instance()->processEvents();
    QScrollBar* bar = ui->scrollArea->verticalScrollBar();
    if(bar)
        bar->setSliderPosition(bar->maximum());
    return entry;
}

void SendCoinsDialog::updateRemoveEnabled()
{
    // Remove buttons are enabled as soon as there is more than one send-entry
    bool enabled = (ui->entries->count() > 1);
    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            entry->setRemoveEnabled(enabled);
        }
    }
    setupTabChain(0);
}

void SendCoinsDialog::removeEntry(SendCoinsEntry* entry)
{
    delete entry;
    updateRemoveEnabled();
}

QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
{
    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            prev = entry->setupTabChain(prev);
        }
    }
    QWidget::setTabOrder(prev, ui->addButton);
    QWidget::setTabOrder(ui->addButton, ui->sendButton);
    return ui->sendButton;
}

void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
{
    if(!fNewRecipientAllowed)
        return;

    SendCoinsEntry *entry = 0;
    // Replace the first entry if it is still unused
    if(ui->entries->count() == 1)
    {
        SendCoinsEntry *first = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
        if(first->isClear())
        {
            entry = first;
        }
    }
    if(!entry)
    {
        entry = addEntry();
    }

    entry->setValue(rv);
}

bool SendCoinsDialog::handleURI(const QString &uri)
{
    SendCoinsRecipient rv;
    // URI has to be valid
    if (GUIUtil::parseBitcoinURI(uri, &rv))
    {
        CBitcoinAddress address(rv.address.toStdString());
        if (!address.IsValid())
            return false;
        pasteEntry(rv);
        return true;
    }

    return false;
}

void SendCoinsDialog::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance)
{
    Q_UNUSED(stake);
    Q_UNUSED(unconfirmedBalance);
    Q_UNUSED(immatureBalance);
    if(!model || !model->getOptionsModel())
        return;

    int unit = model->getOptionsModel()->getDisplayUnit();
    ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
}

void SendCoinsDialog::updateDisplayUnit()
{
    if(model && model->getOptionsModel())
    {
        // Update labelBalance with the current balance and the current unit
        ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->getBalance()));
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Ray Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "ray/rpc/grpc_server.h"

#include <grpcpp/impl/service_type.h>

#include <boost/asio/detail/socket_holder.hpp>

#include "ray/common/ray_config.h"

namespace ray {
namespace rpc {

GrpcServer::GrpcServer(std::string name, const uint32_t port, int num_threads)
    : name_(std::move(name)), port_(port), is_closed_(true), num_threads_(num_threads) {
  cqs_.resize(num_threads_);
}

void GrpcServer::Run() {
  uint32_t specified_port = port_;
  std::string server_address("0.0.0.0:" + std::to_string(port_));
  int num_retries = RayConfig::instance().grpc_server_num_retries();
  while (num_retries >= 0) {
    grpc::ServerBuilder builder;
    // Disable the SO_REUSEPORT option. We don't need it in ray. If the option is enabled
    // (default behavior in grpc), we may see multiple workers listen on the same port and
    // the requests sent to this port may be handled by any of the workers.
    builder.AddChannelArgument(GRPC_ARG_ALLOW_REUSEPORT, 0);
    builder.AddChannelArgument(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH,
                               RayConfig::instance().max_grpc_message_size());
    builder.AddChannelArgument(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH,
                               RayConfig::instance().max_grpc_message_size());
    // TODO(hchen): Add options for authentication.
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials(), &port_);
    // Register all the services to this server.
    if (services_.empty()) {
      RAY_LOG(WARNING) << "No service is found when start grpc server " << name_;
    }
    for (auto &entry : services_) {
      builder.RegisterService(&entry.get());
    }
    // Get hold of the completion queue used for the asynchronous communication
    // with the gRPC runtime.
    for (int i = 0; i < num_threads_; i++) {
      cqs_[i] = builder.AddCompletionQueue();
    }
    // Build and start server.
    server_ = builder.BuildAndStart();
    if (port_ > 0) {
      break;
    }
    usleep(RayConfig::instance().grpc_server_retry_timeout_milliseconds() * 1000);
    num_retries--;
  }

  // If the grpc server failed to bind the port, the `port_` will be set to 0.
  RAY_CHECK(port_ > 0)
      << "Port " << specified_port
      << " specified by caller already in use. Try passing node_manager_port=... into "
         "ray.init() to pick a specific port";
  RAY_LOG(INFO) << name_ << " server started, listening on port " << port_ << ".";

  // Create calls for all the server call factories.
  for (auto &entry : server_call_factories_) {
    for (int i = 0; i < num_threads_; i++) {
      // Create a buffer of 100 calls for each RPC handler.
      // TODO(edoakes): a small buffer should be fine and seems to have better
      // performance, but we don't currently handle backpressure on the client.
      for (int j = 0; j < 100; j++) {
        entry->CreateCall();
      }
    }
  }
  // Start threads that polls incoming requests.
  for (int i = 0; i < num_threads_; i++) {
    polling_threads_.emplace_back(&GrpcServer::PollEventsFromCompletionQueue, this, i);
  }
  // Set the server as running.
  is_closed_ = false;
}

void GrpcServer::RegisterService(GrpcService &service) {
  services_.emplace_back(service.GetGrpcService());

  for (int i = 0; i < num_threads_; i++) {
    service.InitServerCallFactories(cqs_[i], &server_call_factories_);
  }
}

void GrpcServer::PollEventsFromCompletionQueue(int index) {
  void *tag;
  bool ok;

  // Keep reading events from the `CompletionQueue` until it's shutdown.
  while (cqs_[index]->Next(&tag, &ok)) {
    auto *server_call = static_cast<ServerCall *>(tag);
    bool delete_call = false;
    if (ok) {
      switch (server_call->GetState()) {
      case ServerCallState::PENDING:
        // We've received a new incoming request. Now this call object is used to
        // track this request.
        server_call->SetState(ServerCallState::PROCESSING);
        server_call->HandleRequest();
        break;
      case ServerCallState::SENDING_REPLY:
        // GRPC has sent reply successfully, invoking the callback.
        server_call->OnReplySent();
        // The rpc call has finished and can be deleted now.
        delete_call = true;
        break;
      default:
        RAY_LOG(FATAL) << "Shouldn't reach here.";
        break;
      }
    } else {
      // `ok == false` will occur in two situations:
      // First, the server has been shut down, the server call's status is PENDING
      // Second, server has sent reply to client and failed, the server call's status is
      // SENDING_REPLY
      if (server_call->GetState() == ServerCallState::SENDING_REPLY) {
        server_call->OnReplyFailed();
      }
      delete_call = true;
    }
    if (delete_call) {
      delete server_call;
    }
  }
}

}  // namespace rpc
}  // namespace ray
<commit_msg>Fix Windows build (#8905)<commit_after>// Copyright 2017 The Ray Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "ray/rpc/grpc_server.h"

#include <grpcpp/impl/service_type.h>
#include <unistd.h>

#include <boost/asio/detail/socket_holder.hpp>

#include "ray/common/ray_config.h"

namespace ray {
namespace rpc {

GrpcServer::GrpcServer(std::string name, const uint32_t port, int num_threads)
    : name_(std::move(name)), port_(port), is_closed_(true), num_threads_(num_threads) {
  cqs_.resize(num_threads_);
}

void GrpcServer::Run() {
  uint32_t specified_port = port_;
  std::string server_address("0.0.0.0:" + std::to_string(port_));
  int num_retries = RayConfig::instance().grpc_server_num_retries();
  while (num_retries >= 0) {
    grpc::ServerBuilder builder;
    // Disable the SO_REUSEPORT option. We don't need it in ray. If the option is enabled
    // (default behavior in grpc), we may see multiple workers listen on the same port and
    // the requests sent to this port may be handled by any of the workers.
    builder.AddChannelArgument(GRPC_ARG_ALLOW_REUSEPORT, 0);
    builder.AddChannelArgument(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH,
                               RayConfig::instance().max_grpc_message_size());
    builder.AddChannelArgument(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH,
                               RayConfig::instance().max_grpc_message_size());
    // TODO(hchen): Add options for authentication.
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials(), &port_);
    // Register all the services to this server.
    if (services_.empty()) {
      RAY_LOG(WARNING) << "No service is found when start grpc server " << name_;
    }
    for (auto &entry : services_) {
      builder.RegisterService(&entry.get());
    }
    // Get hold of the completion queue used for the asynchronous communication
    // with the gRPC runtime.
    for (int i = 0; i < num_threads_; i++) {
      cqs_[i] = builder.AddCompletionQueue();
    }
    // Build and start server.
    server_ = builder.BuildAndStart();
    if (port_ > 0) {
      break;
    }
    usleep(RayConfig::instance().grpc_server_retry_timeout_milliseconds() * 1000);
    num_retries--;
  }

  // If the grpc server failed to bind the port, the `port_` will be set to 0.
  RAY_CHECK(port_ > 0)
      << "Port " << specified_port
      << " specified by caller already in use. Try passing node_manager_port=... into "
         "ray.init() to pick a specific port";
  RAY_LOG(INFO) << name_ << " server started, listening on port " << port_ << ".";

  // Create calls for all the server call factories.
  for (auto &entry : server_call_factories_) {
    for (int i = 0; i < num_threads_; i++) {
      // Create a buffer of 100 calls for each RPC handler.
      // TODO(edoakes): a small buffer should be fine and seems to have better
      // performance, but we don't currently handle backpressure on the client.
      for (int j = 0; j < 100; j++) {
        entry->CreateCall();
      }
    }
  }
  // Start threads that polls incoming requests.
  for (int i = 0; i < num_threads_; i++) {
    polling_threads_.emplace_back(&GrpcServer::PollEventsFromCompletionQueue, this, i);
  }
  // Set the server as running.
  is_closed_ = false;
}

void GrpcServer::RegisterService(GrpcService &service) {
  services_.emplace_back(service.GetGrpcService());

  for (int i = 0; i < num_threads_; i++) {
    service.InitServerCallFactories(cqs_[i], &server_call_factories_);
  }
}

void GrpcServer::PollEventsFromCompletionQueue(int index) {
  void *tag;
  bool ok;

  // Keep reading events from the `CompletionQueue` until it's shutdown.
  while (cqs_[index]->Next(&tag, &ok)) {
    auto *server_call = static_cast<ServerCall *>(tag);
    bool delete_call = false;
    if (ok) {
      switch (server_call->GetState()) {
      case ServerCallState::PENDING:
        // We've received a new incoming request. Now this call object is used to
        // track this request.
        server_call->SetState(ServerCallState::PROCESSING);
        server_call->HandleRequest();
        break;
      case ServerCallState::SENDING_REPLY:
        // GRPC has sent reply successfully, invoking the callback.
        server_call->OnReplySent();
        // The rpc call has finished and can be deleted now.
        delete_call = true;
        break;
      default:
        RAY_LOG(FATAL) << "Shouldn't reach here.";
        break;
      }
    } else {
      // `ok == false` will occur in two situations:
      // First, the server has been shut down, the server call's status is PENDING
      // Second, server has sent reply to client and failed, the server call's status is
      // SENDING_REPLY
      if (server_call->GetState() == ServerCallState::SENDING_REPLY) {
        server_call->OnReplyFailed();
      }
      delete_call = true;
    }
    if (delete_call) {
      delete server_call;
    }
  }
}

}  // namespace rpc
}  // namespace ray
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>

#include "viennautils/enum_pp.hpp"

VIENNAUTILS_ENUM_PP(element_tag, (edge,1),(triangle),(rectangle,4));

template <typename T>
void foo(T my_tag)
{
  std::cout << "name of enum: " << viennautils::enum_pp::name<T>() << std::endl;
  for ( element_tag::ToStringMap::const_iterator it = viennautils::enum_pp::to_string_map<T>().begin()
      ; it != viennautils::enum_pp::to_string_map<T>().end()
      ; ++it
      )
  {
    std::cout << "value: " << it->first << " name: " << it->second << std::endl;
  }

  std::cout << "using value 'rectangle' to retrieve string: " << viennautils::enum_pp::to_string(my_tag) << std::endl;
  std::cout << "using string \"rectangle\" to retrieve value: " << viennautils::enum_pp::from_string<T>("rectangle") << std::endl;

  try
  {
    T fail = viennautils::enum_pp::from_string<T>("not a valid enum value");
  }
  catch(std::exception const & e)
  {
    std::cout << "caught expected exception: " << e.what() << std::endl;
  }
}

int main()
{
  //notice how T is of type element_tag::type in foo and not element_tag itself
  //so the enum itself is associated with the functions that it needs
  foo(element_tag::rectangle);
}
<commit_msg>enum_pp_demo example is now removed (forgot to stage it with previous checkin)<commit_after><|endoftext|>


<commit_before>#include "..\guid.h"
#include <cassert>
#include <string>

int main()
{
    /* api documentation */

    // create a guid using the static guid::create_new function
    guid g = guid::create_new();
    // check if empty
    bool empty = g.empty();
    // convert the guid to a string like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    std::string s = g.to_string('a');

    // Create a guid using guid::create member function
    guid g2;
    g2.create();

    /* tests */

    guid g3("2AC3E955-939F-4756-8BC1-940BB7C882C3");
    assert(g3.empty() == false);
    assert(g3 != g);
    assert(!(g3 == g));
    std::string s2 = g3.to_string();
    assert(s2.compare("{2AC3E955-939F-4756-8BC1-940BB7C882C3}") == 0);
    assert(g3.to_string(guid_format::uppercase_no_brackets).compare("2AC3E955-939F-4756-8BC1-940BB7C882C3") == 0);

    guid g4(g3);
    assert(g4 == g3);
    guid g5 = g4;
    assert(g5 == g4);
    guid g6;
    g6 = g5;
    assert(g6 == g5);
    g6.swap(g);
    assert(g6 != g5);
    assert(g == g3);

    guid g7 = guid::create_new();
    assert(g7.empty() == false);
    guid g8;
    assert(g8.empty());
    g8.create();
    assert(g8.empty() == false);
    guid g9(g8);
    assert(g9 == g8);
    g9.create();
    assert(g9 == g8);

    guid g10("2AC3E955-939F-4756-8BC1-940BB7C882C3");
    assert(g10.empty() == false);
}<commit_msg>space<commit_after>#include "..\guid.h"

#include <cassert>
#include <string>

int main()
{
    /* api documentation */

    // create a guid using the static guid::create_new function
    guid g = guid::create_new();
    // check if empty
    bool empty = g.empty();
    // convert the guid to a string like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    std::string s = g.to_string('a');

    // Create a guid using guid::create member function
    guid g2;
    g2.create();

    /* tests */

    guid g3("2AC3E955-939F-4756-8BC1-940BB7C882C3");
    assert(g3.empty() == false);
    assert(g3 != g);
    assert(!(g3 == g));
    std::string s2 = g3.to_string();
    assert(s2.compare("{2AC3E955-939F-4756-8BC1-940BB7C882C3}") == 0);
    assert(g3.to_string(guid_format::uppercase_no_brackets).compare("2AC3E955-939F-4756-8BC1-940BB7C882C3") == 0);

    guid g4(g3);
    assert(g4 == g3);
    guid g5 = g4;
    assert(g5 == g4);
    guid g6;
    g6 = g5;
    assert(g6 == g5);
    g6.swap(g);
    assert(g6 != g5);
    assert(g == g3);

    guid g7 = guid::create_new();
    assert(g7.empty() == false);
    guid g8;
    assert(g8.empty());
    g8.create();
    assert(g8.empty() == false);
    guid g9(g8);
    assert(g9 == g8);
    g9.create();
    assert(g9 == g8);

    guid g10("2AC3E955-939F-4756-8BC1-940BB7C882C3");
    assert(g10.empty() == false);
}<|endoftext|>


<commit_before>// belle http example

#include "../../../include/belle.hh"
namespace Belle = OB::Belle;

#include <ctime>

#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>

// prototypes
std::string http_routes(Belle::Server::Http_Routes& routes);

// return string containing all http routes
std::string http_routes(Belle::Server::Http_Routes& routes)
{
  std::stringstream res;

  for (auto const& e : routes)
  {
    res << "Route:  " << (*e).first << "\nMethod:";

    for (auto const& m : (*e).second)
    {
      if (static_cast<Belle::Method>(m.first) == Belle::Method::unknown)
      {
        res << " All";
      }
      else
      {
        res << " " << Belle::http::to_string(static_cast<Belle::Method>(m.first));
      }
    }

    res << "\n\n";
  }

  return res.str();
}

int main(int argc, char *argv[])
{
  // init the server
  Belle::Server app;

  // set the listening address
  std::string address {"127.0.0.1"};
  app.address(address);

  // set the listening port
  int port {8080};
  app.port(port);

  // disable websocket upgrades
  app.websocket(false);

  // set the number of threads to 2
  app.threads(2);

  // enable serving static files from a public directory
  // if the path is relative, make sure to run the program
  // in the right working directory
  app.public_dir("../public");

  // set default http headers
  Belle::Headers headers;
  headers.set(Belle::Header::server, "Belle");
  headers.set(Belle::Header::cache_control, "private; max-age=0");
  app.http_headers(headers);

  // handle the following signals
  app.signals({SIGINT, SIGTERM});

  // set the on signal callback
  app.on_signal([&](auto ec, auto sig)
  {
    // print out the signal received
    std::cerr << "\nSignal " << sig << "\n";

    // get the io_context and safely stop the server
    app.io().stop();
  });

  // handle route GET '/'
  app.on_http("/", Belle::Method::get, [&](Belle::Server::Http_Ctx& ctx)
  {
    // the response string
    std::string res {R"(
      home

      methods

      query parameters

      regex route

      custom error

      static page

    )"};

    // set http response headers
    ctx.res.set("content-type", "text/html");

    // set the http status code
    ctx.res.result(200);

    // set the http body
    ctx.res.body() = res;
  });

  // handle route '/method'
  // matches all methods
  app.on_http("/method", [](Belle::Server::Http_Ctx& ctx)
  {
    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // set the http status code
    ctx.res.result(200);

    // get the request method type
    std::string method {ctx.req.method_string()};

    // echo back the matched http method
    ctx.res.body() = "Method: " + method + "\n";
  });

  // handle route POST '/'
  app.on_http("/post", Belle::Method::post, [](Belle::Server::Http_Ctx& ctx)
  {
    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // set the http status code
    ctx.res.result(200);

    // echo back the request body
    ctx.res.body() = "Body: " + ctx.req.body() + "\n";
  });

  // handle route GET '/params' with query parameters
  // ex. http://localhost:8080/?q=test&page=2
  app.on_http("/params", Belle::Method::get, [](Belle::Server::Http_Ctx& ctx)
  {
    // stringstream to hold the response
    std::stringstream res;
    res << "Query Parameters:\n";

    // access the query parameters
    for (auto const& e : ctx.req.params())
    {
      // add each key value pair to the response
      res << e.first << " | " << e.second << "\n";
    }

    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // set the http status code
    ctx.res.result(200);

    // echo back the query parameters
    ctx.res.body() = res.str();
  });

  // handle route GET '/<400-500 errors>' with query parameters
  // match a regex url
  // ex. http://localhost:8080/404
  app.on_http("^/([45]{1}[0-9]{2})$", Belle::Method::get, [](Belle::Server::Http_Ctx& ctx)
  {
    // access the url regex capture groups
    // using req.url() which is a vector of strings
    // index 0 contains the full matched url
    // index 1 to n contain the value of the capture groups if any
    std::string match {ctx.req.url().at(1)};

    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // set the http status code
    ctx.res.result(200);

    // echo back the captured url path
    ctx.res.body() = "match: " + match;
  });

  // handle an error
  app.on_http("/error", Belle::Method::get, [](Belle::Server::Http_Ctx& ctx)
  {
    // trigger the custom error callback
    throw 500;
  });

  // set custom error callback
  app.on_http_error([&](Belle::Server::Http_Ctx& ctx)
  {
    // stringstream to hold the response
    std::stringstream res; res
    << "Status: " << ctx.res.result_int() << "\n"
    << "Reason: " << ctx.res.result() << "\n";

    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // echo the http status code
    ctx.res.body() = res.str();
  });

  // set http connect callback
  // called at the beginning of every request
  app.on_http_connect([&](Belle::Server::Http_Ctx& ctx)
  {
    // print notification
    std::cerr << "New Request!\n";
  });

  // set http disconnect callback
  // called at the end of every request
  app.on_http_disconnect([&](Belle::Server::Http_Ctx& ctx)
  {
    // access http request headers
    std::string ip {std::string(ctx.req["X-Real-IP"]).empty() ? "localhost" : ctx.req["X-Real-IP"]};
    std::string ua {std::string(ctx.req["user-agent"])};
    std::string rf {std::string(ctx.req["referer"])};

    // get the current time
    std::time_t t {std::time(nullptr)};
    std::tm tm {*std::localtime(&t)};

    // log output
    std::cerr
    << "[" << std::put_time(&tm, "%H:%M:%S %e %b %Y") << "] "
    << "[" << ip << "] "
    << "[" << ctx.res.result_int() << "] "
    << "[" << ctx.req.method() << "] "
    << "[" << ctx.req.target().to_string() << "] "
    << "[" << rf << "] "
    << "[" << ua << "]\n\n";
  });

  // print out the address and port
  // along with all registered http routes
  // followed by the log output
  std::cout
  << "Server: " << address << ":" << port << "\n\n"
  << "Navigate to the following url:\n"
  << "  http://127.0.0.1:8080/\n\n"
  << "Try running the following commands:\n"
  << "  curl -X PUT http://127.0.0.1:8080/method\n"
  << "  curl -X POST --data 'post body message here' http://127.0.0.1:8080/post\n\n"
  << "Begin Routes>\n\n"
  << http_routes(app.http_routes())
  << "Begin Log>\n\n";

  // start the server
  app.listen();

  // the server blocks until a signal is received

  return 0;
}
<commit_msg>update http example<commit_after>// belle http example

#include "../../../include/belle.hh"
namespace Belle = OB::Belle;

#include <ctime>

#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>

// prototypes
std::string http_routes(Belle::Server::Http_Routes& routes);

// return string containing all http routes
std::string http_routes(Belle::Server::Http_Routes& routes)
{
  std::stringstream res;

  for (auto const& e : routes)
  {
    res << "Route:  " << (*e).first << "\nMethod:";

    for (auto const& m : (*e).second)
    {
      if (static_cast<Belle::Method>(m.first) == Belle::Method::unknown)
      {
        res << " ALL";
      }
      else
      {
        res << " " << Belle::http::to_string(static_cast<Belle::Method>(m.first));
      }
    }

    res << "\n\n";
  }

  return res.str();
}

int main(int argc, char *argv[])
{
  // init the server
  Belle::Server app;

  // set the listening address
  std::string address {"127.0.0.1"};
  app.address(address);

  // set the listening port
  int port {8080};
  app.port(port);

  // set the number of threads
  // default value is 1 single thread
  app.threads(std::thread::hardware_concurrency());

  // multithreading can be enabled on an http only server
  // websocket upgrades must be disabled to use multithreading
  // the websocket channel implementation is not thread safe
  // default value is true
  app.websocket(false);

  // enable serving static files from a public directory
  // if the path is relative, make sure to run the program
  // in the right working directory
  app.public_dir("../public");

  // set default http headers
  Belle::Headers headers;
  headers.set(Belle::Header::server, "Belle");
  headers.set(Belle::Header::cache_control, "private; max-age=0");
  app.http_headers(headers);

  // handle the following signals
  app.signals({SIGINT, SIGTERM});

  // set the on signal callback
  app.on_signal([&](auto ec, auto sig)
  {
    // print out the signal received
    std::cerr << "\nSignal " << sig << "\n";

    // get the io_context and safely stop the server
    app.io().stop();
  });

  // handle route GET '/'
  app.on_http("/", Belle::Method::get, [](Belle::Server::Http_Ctx& ctx)
  {
    // the response string
    std::string res {R"(
      home

      methods

      query parameters

      regex route

      custom error

      static page

    )"};

    // set http response headers
    ctx.res.set("content-type", "text/html");

    // set the http status code
    // the http status code can be either an integer or
    // its respective enum representation
    // the default status is 200 OK
    ctx.res.result(Belle::Status::ok);

    // set the http body
    ctx.res.body() = std::move(res);
  });

  // handle route ALL '/method'
  // matches all methods
  app.on_http("/method", [](Belle::Server::Http_Ctx& ctx)
  {
  // get the request method type as a string
    std::stringstream res; res
    << "HTTP Method\n"
    << "method: " << ctx.req.method_string() << "\n";

    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // set the http status code
    ctx.res.result(Belle::Status::ok);

    // echo back the matched http method
    ctx.res.body() = res.str();
  });

  // handle route POST '/post'
  // echo back the posted data
  app.on_http("/post", Belle::Method::post, [](Belle::Server::Http_Ctx& ctx)
  {
    // get the request body data
    std::stringstream res; res
    << "Post Data\n"
    << "Body: " << ctx.req.body() << "\n";

    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // set the http status code
    ctx.res.result(Belle::Status::ok);

    // echo back the request body
    ctx.res.body() = res.str();
  });

  // handle route GET '/params'
  // with query parameters
  // ex. http://localhost:8080/params?q=test&page=2
  app.on_http("/params", Belle::Method::get, [](Belle::Server::Http_Ctx& ctx)
  {
    // stringstream to hold the response
    std::stringstream res;
    res << "Query Parameters\n";

    // access the query parameters
    for (auto const& [key, val] : ctx.req.params())
    {
      // add each key value pair to the response
      res << key << " | " << val << "\n";
    }

    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // set the http status code
    ctx.res.result(Belle::Status::ok);

    // echo back the query parameters
    ctx.res.body() = res.str();
  });

  // handle route GET '/regex/([a-z]+)'
  // match a regex url
  // one or more lowercase characters in the range of a-z
  // ex. http://localhost:8080/regex/hello
  // ex. http://localhost:8080/regex/belle
  app.on_http("^/regex/([a-z]+)$", Belle::Method::get, [](Belle::Server::Http_Ctx& ctx)
  {
    // access the url regex capture groups
    // using req.url() which is a vector of strings
    // index 0 contains the matched url, minus any query parameters
    // index 1 to n contain the value of the capture groups if any
    // the full url with query parameters is in req.target()
    std::string url {ctx.req.url().at(0)};
    std::string match {ctx.req.url().at(1)};

    // stringstream to hold the response
    std::stringstream res; res
    << "Regex Captures\n"
    << "url:   " << url << "\n"
    << "match: " << match << "\n";

    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // set the http status code
    ctx.res.result(Belle::Status::ok);

    // echo back the captured url path
    ctx.res.body() = res.str();
  });

  // trigger the custom error callback
  app.on_http("/error", Belle::Method::get, [](Belle::Server::Http_Ctx& ctx)
  {
    // the thrown value sets the http status code and
    // calls the Belle::Server::on_http_error callback
    // the http status code can be either an integer or
    // its respective enum representation
    throw Belle::Status::internal_server_error;
  });

  // set custom error callback
  app.on_http_error([](Belle::Server::Http_Ctx& ctx)
  {
    // stringstream to hold the response
    // get the http status code represented as an int and string
    std::stringstream res; res
    << "Custom Error\n"
    << "Status: " << ctx.res.result_int() << "\n"
    << "Reason: " << ctx.res.result() << "\n";

    // set http response headers
    ctx.res.set("content-type", "text/plain");

    // send the custom error response
    ctx.res.body() = res.str();
  });

  // set http connect callback
  // called at the beginning of every request
  app.on_http_connect([](Belle::Server::Http_Ctx& ctx)
  {
    // print notification
    std::cerr << "New Request!\n";
  });

  // set http disconnect callback
  // called at the end of every request
  app.on_http_disconnect([](Belle::Server::Http_Ctx& ctx)
  {
    // access http request headers
    std::string ip {std::string(ctx.req["X-Real-IP"]).empty() ? "localhost" : ctx.req["X-Real-IP"]};
    std::string ua {std::string(ctx.req["user-agent"])};
    std::string rf {std::string(ctx.req["referer"])};

    // get the current time
    std::time_t t {std::time(nullptr)};
    std::tm tm {*std::localtime(&t)};

    // log output
    std::cerr
    // the current timestamp
    << "[" << std::put_time(&tm, "%H:%M:%S %e %b %Y") << "] "
    // the ip address
    << "[" << ip << "] "
    // the http status code as an integer
    << "[" << ctx.res.result_int() << "] "
    // the http method as a string
    << "[" << ctx.req.method_string() << "] "
    // the full request url as a string
    << "[" << ctx.req.target().to_string() << "] "
    // the http referer header
    << "[" << rf << "] "
    // the http user-agent header
    << "[" << ua << "]\n\n";
  });

  // print out the address and port
  // along with all registered http routes
  // followed by the log output
  std::cout
  << "Server: " << address << ":" << port << "\n\n"
  << "Navigate to the following url:\n"
  << "  http://" << address << ":" << port << "/\n\n"
  << "Try running the following commands:\n"
  << "  curl -X PUT http://" << address << ":" << port << "/method\n"
  << "  curl -X POST --data 'post body message here' http://"
  << address << ":" << port << "/post\n\n"
  << "Begin Routes>\n\n"
  << http_routes(app.http_routes())
  << "Begin Log>\n\n";

  // start the server
  app.listen();

  // the server blocks until a signal is received

  return 0;
}
<|endoftext|>


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

#include "irc.h"
#include "net.h"
#include "strlcpy.h"
#include "base58.h"

using namespace std;
using namespace boost;

int nGotIRCAddresses = 0;

void ThreadIRCSeed2(void* parg);

#pragma pack(push, 1)
struct ircaddr
{
    struct in_addr ip;
    short port;
};
#pragma pack(pop)

string EncodeAddress(const CService& addr)
{
    struct ircaddr tmp;
    if (addr.GetInAddr(&tmp.ip))
    {
        tmp.port = htons(addr.GetPort());

        vector<unsigned char> vch(UBEGIN(tmp), UEND(tmp));
        return string("u") + EncodeBase58Check(vch);
    }
    return "";
}

bool DecodeAddress(string str, CService& addr)
{
    vector<unsigned char> vch;
    if (!DecodeBase58Check(str.substr(1), vch))
        return false;

    struct ircaddr tmp;
    if (vch.size() != sizeof(tmp))
        return false;
    memcpy(&tmp, &vch[0], sizeof(tmp));

    addr = CService(tmp.ip, ntohs(tmp.port));
    return true;
}

static bool Send(SOCKET hSocket, const char* pszSend)
{
    if (strstr(pszSend, "PONG") != pszSend)
        printf("IRC SENDING: %s\n", pszSend);
    const char* psz = pszSend;
    const char* pszEnd = psz + strlen(psz);
    while (psz < pszEnd)
    {
        int ret = send(hSocket, psz, pszEnd - psz, MSG_NOSIGNAL);
        if (ret < 0)
            return false;
        psz += ret;
    }
    return true;
}

bool RecvLineIRC(SOCKET hSocket, string& strLine)
{
    loop
    {
        bool fRet = RecvLine(hSocket, strLine);
        if (fRet)
        {
            if (fShutdown)
                return false;
            vector<string> vWords;
            ParseString(strLine, ' ', vWords);
            if (vWords.size() >= 1 && vWords[0] == "PING")
            {
                strLine[1] = 'O';
                strLine += '\r';
                Send(hSocket, strLine.c_str());
                continue;
            }
        }
        return fRet;
    }
}

int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL, const char* psz4=NULL)
{
    loop
    {
        string strLine;
        strLine.reserve(10000);
        if (!RecvLineIRC(hSocket, strLine))
            return 0;
        printf("IRC %s\n", strLine.c_str());
        if (psz1 && strLine.find(psz1) != string::npos)
            return 1;
        if (psz2 && strLine.find(psz2) != string::npos)
            return 2;
        if (psz3 && strLine.find(psz3) != string::npos)
            return 3;
        if (psz4 && strLine.find(psz4) != string::npos)
            return 4;
    }
}

bool Wait(int nSeconds)
{
    if (fShutdown)
        return false;
    printf("IRC waiting %d seconds to reconnect\n", nSeconds);
    for (int i = 0; i < nSeconds; i++)
    {
        if (fShutdown)
            return false;
        Sleep(1000);
    }
    return true;
}

bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet)
{
    strRet.clear();
    loop
    {
        string strLine;
        if (!RecvLineIRC(hSocket, strLine))
            return false;

        vector<string> vWords;
        ParseString(strLine, ' ', vWords);
        if (vWords.size() < 2)
            continue;

        if (vWords[1] == psz1)
        {
            printf("IRC %s\n", strLine.c_str());
            strRet = strLine;
            return true;
        }
    }
}

bool GetIPFromIRC(SOCKET hSocket, string strMyName, CNetAddr& ipRet)
{
    Send(hSocket, strprintf("USERHOST %s\r", strMyName.c_str()).c_str());

    string strLine;
    if (!RecvCodeLine(hSocket, "302", strLine))
        return false;

    vector<string> vWords;
    ParseString(strLine, ' ', vWords);
    if (vWords.size() < 4)
        return false;

    string str = vWords[3];
    if (str.rfind("@") == string::npos)
        return false;
    string strHost = str.substr(str.rfind("@")+1);

    // Hybrid IRC used by lfnet always returns IP when you userhost yourself,
    // but in case another IRC is ever used this should work.
    printf("GetIPFromIRC() got userhost %s\n", strHost.c_str());
    CNetAddr addr(strHost, true);
    if (!addr.IsValid())
        return false;
    ipRet = addr;

    return true;
}

void ThreadIRCSeed(void* parg)
{
    // Make this thread recognisable as the IRC seeding thread
    RenameThread("bitcoin-ircseed");

    try
    {
        ThreadIRCSeed2(parg);
    }
    catch (std::exception& e) {
        PrintExceptionContinue(&e, "ThreadIRCSeed()");
    } catch (...) {
        PrintExceptionContinue(NULL, "ThreadIRCSeed()");
    }
    printf("ThreadIRCSeed exited\n");
}

void ThreadIRCSeed2(void* parg)
{
    // Don't connect to IRC if we won't use IPv4 connections.
    if (IsLimited(NET_IPV4))
        return;

    // ... or if we won't make outbound connections and won't accept inbound ones.
    if (mapArgs.count("-connect") && fNoListen)
        return;

    // ... or if IRC is not enabled.
    if (!GetBoolArg("-irc", true))
        return;

    printf("ThreadIRCSeed started\n");
    int nErrorWait = 10;
    int nRetryWait = 10;
    int nNameRetry = 0;

    while (!fShutdown)
    {
        CService addrConnect("188.122.74.140", 6667); // eu.undernet.org

        CService addrIRC("irc.rizon.net", 6667, true);
        if (addrIRC.IsValid())
            addrConnect = addrIRC;

        SOCKET hSocket;
        if (!ConnectSocket(addrConnect, hSocket))
        {
            printf("IRC connect failed\n");
            nErrorWait = nErrorWait * 11 / 10;
            if (Wait(nErrorWait += 60))
                continue;
            else
                return;
        }

        if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname"))
        {
            closesocket(hSocket);
            hSocket = INVALID_SOCKET;
            nErrorWait = nErrorWait * 11 / 10;
            if (Wait(nErrorWait += 60))
                continue;
            else
                return;
        }

        CNetAddr addrIPv4("1.2.3.4"); // arbitrary IPv4 address to make GetLocal prefer IPv4 addresses
        CService addrLocal;
        string strMyName;
        // Don't use our IP as our nick if we're not listening
        // or if it keeps failing because the nick is already in use.
        if (!fNoListen && GetLocal(addrLocal, &addrIPv4) && nNameRetry<3)
            strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
        if (strMyName == "")
            strMyName = strprintf("x%"PRI64u"", GetRand(1000000000));

        Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
        Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str());

        int nRet = RecvUntil(hSocket, " 004 ", " 433 ");
        if (nRet != 1)
        {
            closesocket(hSocket);
            hSocket = INVALID_SOCKET;
            if (nRet == 2)
            {
                printf("IRC name already in use\n");
                nNameRetry++;
                Wait(10);
                continue;
            }
            nErrorWait = nErrorWait * 11 / 10;
            if (Wait(nErrorWait += 60))
                continue;
            else
                return;
        }
        nNameRetry = 0;
        Sleep(500);

        // Get our external IP from the IRC server and re-nick before joining the channel
        CNetAddr addrFromIRC;
        if (GetIPFromIRC(hSocket, strMyName, addrFromIRC))
        {
            printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str());
            // Don't use our IP as our nick if we're not listening
            if (!fNoListen && addrFromIRC.IsRoutable())
            {
                // IRC lets you to re-nick
                AddLocal(addrFromIRC, LOCAL_IRC);
                strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
                Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
            }
        }

        if (fTestNet) {
            Send(hSocket, "JOIN #CryptogenicBullionTEST2\r");
            Send(hSocket, "WHO #CryptogenicBullionTEST2\r");
        } else {
            // randomly join #CryptogenicBullion00-#CryptogenicBullion05
            // int channel_number = GetRandInt(5);

            // Channel number is always 0 for initial release
            int channel_number = 0;
            Send(hSocket, strprintf("JOIN #CryptogenicBullion%02d\r", channel_number).c_str());
            Send(hSocket, strprintf("WHO #CryptogenicBullion%02d\r", channel_number).c_str());
        }

        int64 nStart = GetTime();
        string strLine;
        strLine.reserve(10000);
        while (!fShutdown && RecvLineIRC(hSocket, strLine))
        {
            if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':')
                continue;

            vector<string> vWords;
            ParseString(strLine, ' ', vWords);
            if (vWords.size() < 2)
                continue;

            char pszName[10000];
            pszName[0] = '\0';

            if (vWords[1] == "352" && vWords.size() >= 8)
            {
                // index 7 is limited to 16 characters
                // could get full length name at index 10, but would be different from join messages
                strlcpy(pszName, vWords[7].c_str(), sizeof(pszName));
                printf("IRC got who\n");
            }

            if (vWords[1] == "JOIN" && vWords[0].size() > 1)
            {
                // :username!username@50000007.F000000B.90000002.IP JOIN :#channelname
                strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName));
                if (strchr(pszName, '!'))
                    *strchr(pszName, '!') = '\0';
                printf("IRC got join\n");
            }

            if (pszName[0] == 'u')
            {
                CAddress addr;
                if (DecodeAddress(pszName, addr))
                {
                    addr.nTime = GetAdjustedTime();
                    if (addrman.Add(addr, addrConnect, 51 * 60))
                        printf("IRC got new address: %s\n", addr.ToString().c_str());
                    nGotIRCAddresses++;
                }
                else
                {
                    printf("IRC decode failed\n");
                }
            }
        }
        closesocket(hSocket);
        hSocket = INVALID_SOCKET;

        if (GetTime() - nStart > 20 * 60)
        {
            nErrorWait /= 3;
            nRetryWait /= 3;
        }

        nRetryWait = nRetryWait * 11 / 10;
        if (!Wait(nRetryWait += 60))
            return;
    }
}

#ifdef TEST
int main(int argc, char *argv[])
{
    WSADATA wsadata;
    if (WSAStartup(MAKEWORD(2,2), &wsadata) != NO_ERROR)
    {
        printf("Error at WSAStartup()\n");
        return false;
    }

    ThreadIRCSeed(NULL);

    WSACleanup();
    return 0;
}
#endif
<commit_msg>Fix IRC Bans<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "irc.h"
#include "net.h"
#include "strlcpy.h"
#include "base58.h"

using namespace std;
using namespace boost;

int nGotIRCAddresses = 0;

void ThreadIRCSeed2(void* parg);

#pragma pack(push, 1)
struct ircaddr
{
    struct in_addr ip;
    short port;
};
#pragma pack(pop)

string EncodeAddress(const CService& addr)
{
    struct ircaddr tmp;
    if (addr.GetInAddr(&tmp.ip))
    {
        tmp.port = htons(addr.GetPort());

        vector<unsigned char> vch(UBEGIN(tmp), UEND(tmp));
        return string("u") + EncodeBase58Check(vch);
    }
    return "";
}

bool DecodeAddress(string str, CService& addr)
{
    vector<unsigned char> vch;
    if (!DecodeBase58Check(str.substr(1), vch))
        return false;

    struct ircaddr tmp;
    if (vch.size() != sizeof(tmp))
        return false;
    memcpy(&tmp, &vch[0], sizeof(tmp));

    addr = CService(tmp.ip, ntohs(tmp.port));
    return true;
}

static bool Send(SOCKET hSocket, const char* pszSend)
{
    if (strstr(pszSend, "PONG") != pszSend)
        printf("IRC SENDING: %s\n", pszSend);
    const char* psz = pszSend;
    const char* pszEnd = psz + strlen(psz);
    while (psz < pszEnd)
    {
        int ret = send(hSocket, psz, pszEnd - psz, MSG_NOSIGNAL);
        if (ret < 0)
            return false;
        psz += ret;
    }
    return true;
}

bool RecvLineIRC(SOCKET hSocket, string& strLine)
{
    loop
    {
        bool fRet = RecvLine(hSocket, strLine);
        if (fRet)
        {
            if (fShutdown)
                return false;
            vector<string> vWords;
            ParseString(strLine, ' ', vWords);
            if (vWords.size() >= 1 && vWords[0] == "PING")
            {
                strLine[1] = 'O';
                strLine += '\r';
                Send(hSocket, strLine.c_str());
                continue;
            }
        }
        return fRet;
    }
}

int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL, const char* psz4=NULL)
{
    loop
    {
        string strLine;
        strLine.reserve(10000);
        if (!RecvLineIRC(hSocket, strLine))
            return 0;
        printf("IRC %s\n", strLine.c_str());
        if (psz1 && strLine.find(psz1) != string::npos)
            return 1;
        if (psz2 && strLine.find(psz2) != string::npos)
            return 2;
        if (psz3 && strLine.find(psz3) != string::npos)
            return 3;
        if (psz4 && strLine.find(psz4) != string::npos)
            return 4;
    }
}

bool Wait(int nSeconds)
{
    if (fShutdown)
        return false;
    printf("IRC waiting %d seconds to reconnect\n", nSeconds);
    for (int i = 0; i < nSeconds; i++)
    {
        if (fShutdown)
            return false;
        Sleep(1000);
    }
    return true;
}

bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet)
{
    strRet.clear();
    loop
    {
        string strLine;
        if (!RecvLineIRC(hSocket, strLine))
            return false;

        vector<string> vWords;
        ParseString(strLine, ' ', vWords);
        if (vWords.size() < 2)
            continue;

        if (vWords[1] == psz1)
        {
            printf("IRC %s\n", strLine.c_str());
            strRet = strLine;
            return true;
        }
    }
}

bool GetIPFromIRC(SOCKET hSocket, string strMyName, CNetAddr& ipRet)
{
    Send(hSocket, strprintf("USERHOST %s\r", strMyName.c_str()).c_str());

    string strLine;
    if (!RecvCodeLine(hSocket, "302", strLine))
        return false;

    vector<string> vWords;
    ParseString(strLine, ' ', vWords);
    if (vWords.size() < 4)
        return false;

    string str = vWords[3];
    if (str.rfind("@") == string::npos)
        return false;
    string strHost = str.substr(str.rfind("@")+1);

    // Hybrid IRC used by lfnet always returns IP when you userhost yourself,
    // but in case another IRC is ever used this should work.
    printf("GetIPFromIRC() got userhost %s\n", strHost.c_str());
    CNetAddr addr(strHost, true);
    if (!addr.IsValid())
        return false;
    ipRet = addr;

    return true;
}

void ThreadIRCSeed(void* parg)
{
    // Make this thread recognisable as the IRC seeding thread
    RenameThread("bitcoin-ircseed");

    try
    {
        ThreadIRCSeed2(parg);
    }
    catch (std::exception& e) {
        PrintExceptionContinue(&e, "ThreadIRCSeed()");
    } catch (...) {
        PrintExceptionContinue(NULL, "ThreadIRCSeed()");
    }
    printf("ThreadIRCSeed exited\n");
}

void ThreadIRCSeed2(void* parg)
{
    // Don't connect to IRC if we won't use IPv4 connections.
    if (IsLimited(NET_IPV4))
        return;

    // ... or if we won't make outbound connections and won't accept inbound ones.
    if (mapArgs.count("-connect") && fNoListen)
        return;

    // ... or if IRC is not enabled.
    if (!GetBoolArg("-irc", true))
        return;

    printf("ThreadIRCSeed started\n");
    int nErrorWait = 10;
    int nRetryWait = 10;
    int nNameRetry = 0;

    while (!fShutdown)
    {
        CService addrConnect("173.246.103.92", 6667); // eu.undernet.org

        CService addrIRC("pelican.heliacal.net", 6667, true);
        if (addrIRC.IsValid())
            addrConnect = addrIRC;

        SOCKET hSocket;
        if (!ConnectSocket(addrConnect, hSocket))
        {
            printf("IRC connect failed\n");
            nErrorWait = nErrorWait * 11 / 10;
            if (Wait(nErrorWait += 60))
                continue;
            else
                return;
        }

        if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname"))
        {
            closesocket(hSocket);
            hSocket = INVALID_SOCKET;
            nErrorWait = nErrorWait * 11 / 10;
            if (Wait(nErrorWait += 60))
                continue;
            else
                return;
        }

        CNetAddr addrIPv4("1.2.3.4"); // arbitrary IPv4 address to make GetLocal prefer IPv4 addresses
        CService addrLocal;
        string strMyName;
        // Don't use our IP as our nick if we're not listening
        // or if it keeps failing because the nick is already in use.
        if (!fNoListen && GetLocal(addrLocal, &addrIPv4) && nNameRetry<3)
            strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
        if (strMyName == "")
            strMyName = strprintf("x%"PRI64u"", GetRand(1000000000));

        Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
        Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str());

        int nRet = RecvUntil(hSocket, " 004 ", " 433 ");
        if (nRet != 1)
        {
            closesocket(hSocket);
            hSocket = INVALID_SOCKET;
            if (nRet == 2)
            {
                printf("IRC name already in use\n");
                nNameRetry++;
                Wait(10);
                continue;
            }
            nErrorWait = nErrorWait * 11 / 10;
            if (Wait(nErrorWait += 60))
                continue;
            else
                return;
        }
        nNameRetry = 0;
        Sleep(500);

        // Get our external IP from the IRC server and re-nick before joining the channel
        CNetAddr addrFromIRC;
        if (GetIPFromIRC(hSocket, strMyName, addrFromIRC))
        {
            printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str());
            // Don't use our IP as our nick if we're not listening
            if (!fNoListen && addrFromIRC.IsRoutable())
            {
                // IRC lets you to re-nick
                AddLocal(addrFromIRC, LOCAL_IRC);
                strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
                Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
            }
        }

        if (fTestNet) {
            Send(hSocket, "JOIN #CGBullionTEST2\r");
            Send(hSocket, "WHO #CGBullionTEST2\r");
        } else {
            // randomly join #CryptogenicBullion00-#CryptogenicBullion05
            // int channel_number = GetRandInt(5);

            // Channel number is always 0 for initial release
            int channel_number = 0;
            Send(hSocket, strprintf("JOIN #CGBullion%02d\r", channel_number).c_str());
            Send(hSocket, strprintf("WHO #CGBullion%02d\r", channel_number).c_str());
        }

        int64 nStart = GetTime();
        string strLine;
        strLine.reserve(10000);
        while (!fShutdown && RecvLineIRC(hSocket, strLine))
        {
            if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':')
                continue;

            vector<string> vWords;
            ParseString(strLine, ' ', vWords);
            if (vWords.size() < 2)
                continue;

            char pszName[10000];
            pszName[0] = '\0';

            if (vWords[1] == "352" && vWords.size() >= 8)
            {
                // index 7 is limited to 16 characters
                // could get full length name at index 10, but would be different from join messages
                strlcpy(pszName, vWords[7].c_str(), sizeof(pszName));
                printf("IRC got who\n");
            }

            if (vWords[1] == "JOIN" && vWords[0].size() > 1)
            {
                // :username!username@50000007.F000000B.90000002.IP JOIN :#channelname
                strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName));
                if (strchr(pszName, '!'))
                    *strchr(pszName, '!') = '\0';
                printf("IRC got join\n");
            }

            if (pszName[0] == 'u')
            {
                CAddress addr;
                if (DecodeAddress(pszName, addr))
                {
                    addr.nTime = GetAdjustedTime();
                    if (addrman.Add(addr, addrConnect, 51 * 60))
                        printf("IRC got new address: %s\n", addr.ToString().c_str());
                    nGotIRCAddresses++;
                }
                else
                {
                    printf("IRC decode failed\n");
                }
            }
        }
        closesocket(hSocket);
        hSocket = INVALID_SOCKET;

        if (GetTime() - nStart > 20 * 60)
        {
            nErrorWait /= 3;
            nRetryWait /= 3;
        }

        nRetryWait = nRetryWait * 11 / 10;
        if (!Wait(nRetryWait += 60))
            return;
    }
}

#ifdef TEST
int main(int argc, char *argv[])
{
    WSADATA wsadata;
    if (WSAStartup(MAKEWORD(2,2), &wsadata) != NO_ERROR)
    {
        printf("Error at WSAStartup()\n");
        return false;
    }

    ThreadIRCSeed(NULL);

    WSACleanup();
    return 0;
}
#endif
<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <globals.h>
#include <ugens.h>
#include <iostream.h>
#include "../rtstuff/Instrument.h"
#include "../rtstuff/rtdefs.h"
#include "../H/dbug.h"
#include <stdlib.h>

//extern double schedtime;

int Instrument::rtsetoutput(float start, float dur, Instrument *theInst)
{
// I know this is silly, but I wanted nsamps and I wanted it to
// look like "setnote" in orig cmix insts
  // DJT:  then perhaps we should call it rtsetnote?

  // DS: Adding check to be sure rtoutput() did not fail.

  if (rtfileit < 0) {
  	 die(theInst->name(), "rtsetoutput: No output file open for this instrument (rtoutput failed?)!");
  }

  // DJT:  made change to increment schedtime here ... not sure how it will work
//   if (rtInteractive) {
// #ifdef DBUG
//     cout << "rtsetoutput():  rtInteractive mode set\n";
// #endif
// 	pthread_mutex_lock(&schedtime_lock);
//     start += (float)schedtime;
// 	pthread_mutex_unlock(&schedtime_lock);
//   }

  theInst->_start = start;
  theInst->_dur = dur;
  theInst->nsamps = (int)(dur * SR);

  return(theInst->nsamps);
}
<commit_msg>Removed unused schedtime code.<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <globals.h>
#include <ugens.h>
#include <iostream.h>
#include "../rtstuff/Instrument.h"
#include "../rtstuff/rtdefs.h"
#include "../H/dbug.h"
#include <stdlib.h>

//extern double schedtime;

int Instrument::rtsetoutput(float start, float dur, Instrument *theInst)
{
// I know this is silly, but I wanted nsamps and I wanted it to
// look like "setnote" in orig cmix insts
  // DJT:  then perhaps we should call it rtsetnote?

  // DS: Adding check to be sure rtoutput() did not fail.

  if (rtfileit < 0) {
  	 die(theInst->name(), "rtsetoutput: No output file open for this instrument (rtoutput failed?)!");
  }

  theInst->_start = start;
  theInst->_dur = dur;
  theInst->nsamps = (int)(dur * SR);

  return(theInst->nsamps);
}
<|endoftext|>