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 ); } }