void
RemoteNode::work_()
{
    {
        LOCK();
        // the socket was created by another thread, per ZMQs documentation ownership
        // transfer requires a full fence memory barrier which this lock should offer
        LOG_INFO(node_id() << ": starting worker");
    }

    zmq::pollitem_t items[2];
    bool wait_for_write = false;

    while (true)
    {
        try
        {
            ASSERT(zock_ != nullptr);

            items[0].socket = *zock_;
            items[0].fd = -1;
            items[0].events = ZMQ_POLLIN;
            if (wait_for_write)
            {
                items[0].events |= ZMQ_POLLOUT;
            }

            items[1].socket = nullptr;
            items[1].fd = event_fd_;
            items[1].events = ZMQ_POLLIN;

            const int ret = zmq::poll(items,
                                      2,
                                      -1);
            THROW_WHEN(ret <= 0);

            if (stop_)
            {
                LOCK();
                ASSERT(queued_work_.empty());
                ASSERT(submitted_work_.empty());
                break;
            }
            else
            {
                if ((items[0].revents bitand ZMQ_POLLIN))
                {
                    recv_responses_();
                }

                if ((items[0].revents bitand ZMQ_POLLOUT))
                {
                    wait_for_write = not send_requests_();
                }

                if (items[1].revents bitand ZMQ_POLLIN)
                {
                    wait_for_write = not send_requests_();
                }
            }
        }
        CATCH_STD_ALL_EWHAT({
                LOG_ERROR(node_id() << ": caught exception in event loop: " << EWHAT << ". Resetting.");
                init_zock_();
            });
    }
Beispiel #2
0
void
ClientNG::recv_(mdsproto::Tag txtag,
                size_t txoff,
                Read&& read)
{
    mdsproto::ResponseHeader rxhdr;

    client_.recv(ba::buffer(&rxhdr,
                            sizeof(rxhdr)),
                 timeout_);

    if (rxhdr.magic != mdsproto::magic)
    {
        LOG_ERROR("Response lacks our protocol magic, giving up");
        throw mdsproto::NoMagicException("no magic key in received header");
    }

    // LOG_TRACE("received hdr " << rxhdr.response_type <<
    //           ", tag " << rxhdr.tag <<
    //           ", size " << rxhdr.size <<
    //           ", flags " << rxhdr.flags);

    TODO("AR: better exceptions");
    THROW_WHEN(rxhdr.tag != txtag);

    ++in_counters_.messages;
    in_counters_.data_bytes += rxhdr.size;
    in_counters_.data_bytes_sqsum += rxhdr.size * rxhdr.size;

    if (rxhdr.size)
    {
        if ((rxhdr.flags bitand mdsproto::ResponseHeader::Flags::UseShmem) == 0)
        {
            if (use_shmem_())
            {
                ++in_counters_.shmem_overruns;
            }

            std::vector<capnp::word> rxbuf(rxhdr.size / sizeof(capnp::word));

            client_.recv(ba::buffer(rxbuf),
                         timeout_);

            capnp::FlatArrayMessageReader reader(kj::arrayPtr(rxbuf.data(),
                                                              rxbuf.size()));
            handle_response_<T>(rxhdr,
                                reader,
                                std::move(read));
        }
        else
        {
            THROW_UNLESS(use_shmem_());

            const uint8_t* addr = static_cast<const uint8_t*>(mr_->address()) + txoff;

            THROW_UNLESS(addr + rxhdr.size <=
                         static_cast<const uint8_t*>(mr_->address()) + mr_->size());

            auto seg(kj::arrayPtr(reinterpret_cast<const capnp::word*>(addr),
                                  rxhdr.size / sizeof(capnp::word)));

            capnp::SegmentArrayMessageReader reader(kj::arrayPtr(&seg, 1));

            handle_response_<T>(rxhdr,
                                reader,
                                std::move(read));
        }
    }
}