Beispiel #1
0
    void parcelport::send_parcels_or_reclaim_connection(
        naming::locality const& locality_id, 
        parcelport_connection_ptr const& client_connection)
    {
        typedef pending_parcels_map::iterator iterator;

        std::vector<parcel> parcels;
        std::vector<write_handler_type> handlers;

        {
            lcos::local::spinlock::scoped_lock l(mtx_);
            iterator it = pending_parcels_.find(locality_id);

            if (it != pending_parcels_.end())
            {
                BOOST_ASSERT(it->first == locality_id);
                std::swap(parcels, it->second.first);
                std::swap(handlers, it->second.second);

                if (parcels.empty())
                {
                    // if no parcels are pending re-add the connection to
                    // the cache
                    BOOST_ASSERT(handlers.empty());
                    BOOST_ASSERT(locality_id == client_connection->destination());
                    connection_cache_.reclaim(locality_id, client_connection);
                    return;
                }
            }
            else 
            {
                // Give this connection back to the cache as it's not
                // needed anymore.
                BOOST_ASSERT(locality_id == client_connection->destination());
                connection_cache_.reclaim(locality_id, client_connection);
                return;
            }
        }

        // send parcels if they didn't get sent by another connection
        send_pending_parcels(client_connection, parcels, handlers);
    }
Beispiel #2
0
    void parcelport::put_parcel(parcel const& p, write_handler_type f)
    {
        typedef pending_parcels_map::iterator iterator;
        naming::locality locality_id = p.get_destination_locality();

        parcelport_connection_ptr client_connection;

        // enqueue the incoming parcel ...
        {
            util::spinlock::scoped_lock l(mtx_);
            pending_parcels_[locality_id].first.push_back(p);
            pending_parcels_[locality_id].second.push_back(f);
        }

        // Get a connection or reserve space for a new connection. 
        if (!connection_cache_.get_or_reserve(locality_id, client_connection))
            return;

        // Check if we need to create the new connection.
        if (!client_connection)
        {
            client_connection.reset(new parcelport_connection(
                io_service_pool_.get_io_service(), locality_id,
                connection_cache_, timer_, parcels_sent_));

            // Connect to the target locality, retry if needed.
            boost::system::error_code error = boost::asio::error::try_again;
            for (int i = 0; i < HPX_MAX_NETWORK_RETRIES; ++i)
            {
                try {
                    naming::locality::iterator_type end = locality_id.connect_end();
                    for (naming::locality::iterator_type it =
                            locality_id.connect_begin(io_service_pool_.get_io_service());
                         it != end; ++it)
                    {
                        client_connection->socket().close();
                        client_connection->socket().connect(*it, error);
                        if (!error)
                            break;
                    }
                    if (!error)
                        break;

                    // we wait for a really short amount of time
                    // TODO: Should this be an hpx::threads::suspend?
                    boost::this_thread::sleep(boost::get_system_time() +
                        boost::posix_time::milliseconds(HPX_NETWORK_RETRIES_SLEEP));
                }
                catch (boost::system::error_code const& e) {
                    HPX_THROW_EXCEPTION(network_error,
                        "parcelport::send_parcel", e.message());
                }
            }

            if (error) {
                client_connection->socket().close();

                hpx::util::osstream strm;
                strm << error.message() << " (while trying to connect to: "
                     << locality_id << ")";
                HPX_THROW_EXCEPTION(network_error,
                    "parcelport::send_parcel",
                    hpx::util::osstream_get_string(strm));
            }
#if defined(HPX_DEBUG)
            else {
                std::string connection_addr = 
                    client_connection->socket().remote_endpoint().address().to_string();
                boost::uint16_t connection_port = 
                    client_connection->socket().remote_endpoint().port();
                BOOST_ASSERT(locality_id.get_address() == connection_addr);
                BOOST_ASSERT(locality_id.get_port() == connection_port);
            }
#endif
        }
#if defined(HPX_DEBUG)
        else {
            //LPT_(info) << "parcelport: reusing existing connection to: "
            //           << addr.locality_;
            BOOST_ASSERT(locality_id == client_connection->destination());

            std::string connection_addr = client_connection->socket().remote_endpoint().address().to_string();
            boost::uint16_t connection_port = client_connection->socket().remote_endpoint().port();
            BOOST_ASSERT(locality_id.get_address() == connection_addr);
            BOOST_ASSERT(locality_id.get_port() == connection_port);
        }
#endif

        std::vector<parcel> parcels;
        std::vector<write_handler_type> handlers;

        util::spinlock::scoped_lock l(mtx_);
        iterator it = pending_parcels_.find(locality_id);

        if (it != pending_parcels_.end())
        {
            BOOST_ASSERT(it->first == locality_id);
            std::swap(parcels, it->second.first);
            std::swap(handlers, it->second.second);
        }

        // If the parcels didn't get sent by another connection ...
        if (!parcels.empty() && !handlers.empty())
        {
            send_pending_parcels(client_connection, parcels, handlers);
        }
        else
        {
            // ... or re-add the stuff to the cache
            BOOST_ASSERT(locality_id == client_connection->destination());
            connection_cache_.reclaim(locality_id, client_connection);
        }
    }