Exemple #1
0
		bool PipeClient::WriteLengthEncodedBuffer(pGina::Memory::Buffer *buffer)
		{
			pGina::Memory::Buffer lengthBuffer(4);
			pGina::Memory::BinaryWriter writer(lengthBuffer);
			writer.Write(buffer->Length());

			if(WriteBuffer(&lengthBuffer))
			{
				return WriteBuffer(buffer);
			}

			return false;
		}
void ClientImpl::regularReadCallback(struct bufferevent *bev) {
    struct evbuffer *evbuf = bufferevent_get_input(bev);
    boost::shared_ptr<CxnContext> context = m_contexts[bev];
    int32_t remaining = static_cast<int32_t>(evbuffer_get_length(evbuf));
    bool breakEventLoop = false;

    if (context->m_lengthOrMessage && remaining < 4) {
        return;
    }

    while (true) {
        if (context->m_lengthOrMessage && remaining >= 4) {
            char lengthBytes[4];
            ByteBuffer lengthBuffer(lengthBytes, 4);
            evbuffer_remove( evbuf, lengthBytes, 4);
            context->m_nextLength = static_cast<size_t>(lengthBuffer.getInt32());
            context->m_lengthOrMessage = false;
            remaining -= 4;
        } else if (remaining >= context->m_nextLength) {
            boost::shared_array<char> messageBytes = boost::shared_array<char>(new char[context->m_nextLength]);
            context->m_lengthOrMessage = true;
            evbuffer_remove( evbuf, messageBytes.get(), static_cast<size_t>(context->m_nextLength));
            remaining -= context->m_nextLength;
            InvocationResponse response(messageBytes, context->m_nextLength);
            boost::shared_ptr<CallbackMap> callbackMap = m_callbacks[bev];
            CallbackMap::iterator i = callbackMap->find(response.clientData());
            if(i != callbackMap->end()){
                try {
                    m_ignoreBackpressure = true;
                    breakEventLoop |= i->second->callback(response);
                    m_ignoreBackpressure = false;
                } catch (std::exception &e) {
                    if (m_listener.get() != NULL) {
                        try {
                            m_ignoreBackpressure = true;
                            breakEventLoop |= m_listener->uncaughtException( e, i->second, response);
                            m_ignoreBackpressure = false;
                        } catch (const std::exception& e) {
                            std::cerr << "Uncaught exception handler threw exception: " << e.what() << std::endl;
                        }
                    }
                }
                /*
                 * When Volt sends us out a notification, it comes with the ClientData
                 * filled in with a known 64-bit number.
                 * In this case, we don't want to remove the callback. We need a static
                 * callback here to continually process notifications.
                 */
                if(response.clientData() != VOLT_NOTIFICATION_MAGIC_NUMBER){
                    callbackMap->erase(i);
                    m_outstandingRequests--;
                }
            }

            //If the client is draining and it just drained the last request, break the loop
            if (m_isDraining && m_outstandingRequests == 0) {
                breakEventLoop = true;
            } else if (m_loopBreakRequested && (m_outstandingRequests <= m_maxOutstandingRequests)) {
                // ignore break requested until we have too many outstanding requests
                breakEventLoop = true;
            }
        } else {
            if (context->m_lengthOrMessage) {
                bufferevent_setwatermark( bev, EV_READ, 4, HIGH_WATERMARK);
            } else {
                bufferevent_setwatermark( bev, EV_READ, static_cast<size_t>(context->m_nextLength), HIGH_WATERMARK);
            }
            breakEventLoop |= (m_loopBreakRequested && (m_outstandingRequests <= m_maxOutstandingRequests));
            break;
        }
    }

    if (breakEventLoop) {
        event_base_loopbreak( m_base );
    }
}