/* when a period comes, the request is processed here */ void handleRequest() { char firstChar = dequeue(&requestBuffer), secondChar = dequeue(&requestBuffer); if(firstChar == 'M' && secondChar == 'C') handleMessageCount(); else if(firstChar == 'R' && secondChar == 'M') handleReadMessage(); else if(firstChar == 'D' && secondChar == 'E') handleDeleteMessage(); else if(firstChar == 'S' && secondChar == 'M') handleSendMessage(); else if(firstChar == 'U' && secondChar == 'M') handleUpdateMessage(); else sendInvalidRequestReply(); /* then enqueue a period, flush the remainder of the request, and notify the send uart thread */ enqueue(&replyBuffer, '.'); while(dequeue(&requestBuffer) != '.'); tx_event_flags_set(&gUartSendEventFlags,1,TX_OR); }
void InnerTcpConnection::realSendMessage() { function_footprint(); static uint32_t BATCH_TCP_MESSAGES = InnerTcpConnection::innerTcpServer->getTcpBatchSize(); InnerTcpConnectionState expectedState = READY; if(!state.compare_exchange_strong(expectedState, WRITING)) { VLOG(3) << "Connection is not ready: " << state.load(); return; } auto conn = shared_from_this(); if(unlikely(!socket.is_open())) { terminate(); return; } idgs::actor::ActorMessagePtr msg; std::vector<idgs::actor::ActorMessagePtr>* msgs = new std::vector<idgs::actor::ActorMessagePtr>(); msgs->reserve(BATCH_TCP_MESSAGES); std::vector<asio::const_buffer> outBuffers; outBuffers.reserve(BATCH_TCP_MESSAGES * 2 + 1); uint32_t sendLength; sendLength = 0; outBuffers.push_back(asio::buffer(reinterpret_cast<void*>(&sendLength), sizeof(sendLength))); while(getQueue().try_pop(msg)) { DVLOG(2) << "send message: " << msg->toString(); DVLOG(3) << "Send head size: " << sizeof(idgs::net::TcpHeader) << ", content: " << dumpBinaryBuffer(std::string((char*)msg->getRpcBuffer()->getHeader(), sizeof(idgs::net::TcpHeader))); DVLOG(3) << "Send body size: " << msg->getRpcBuffer()->getBodyLength() << ", content: " << dumpBinaryBuffer(std::string(msg->getRpcBuffer()->getBody(), msg->getRpcBuffer()->getBodyLength())); msgs->push_back(msg); outBuffers.push_back(asio::buffer(reinterpret_cast<void*>(msg->getRpcBuffer()->getHeader()), sizeof(idgs::net::TcpHeader))); outBuffers.push_back(asio::buffer(reinterpret_cast<void*>(msg->getRpcBuffer()->getBody()), msg->getRpcBuffer()->getBodyLength())); sendLength += sizeof(idgs::net::TcpHeader) + msg->getRpcBuffer()->getBodyLength(); // if(msgs->size() >= BATCH_TCP_MESSAGES || sendLength > (1024 * 50)) { if(msgs->size() >= BATCH_TCP_MESSAGES) { break; } } if(msgs->empty()) { DVLOG(2) << "No availabe message to send."; state.store(READY); delete msgs; return; } try { DVLOG(2) << "Send " << msgs->size() << " messages"; if(unlikely(!socket.is_open())) { // @fixme messagea lost delete msgs; terminate(); return; } asio::async_write( socket, outBuffers, asio::transfer_all(), [msgs, conn] (const asio::error_code& error, const std::size_t& bytes_transferred) { DVLOG(2) << "Sent " << msgs->size() << " messages"; conn->handleSendMessage(error); static NetworkStatistics* stats = InnerTcpConnection::innerTcpServer->network->getNetworkStatistics(); stats->innerTcpBytesSent.fetch_add(bytes_transferred); stats->innerTcpPacketSent.fetch_add(msgs->size()); delete msgs; } ); } catch (std::exception& e) { LOG(ERROR) << "send message error, exception: " << e.what() << ", messages: " << msgs->size(); delete msgs; terminate(); } catch (...) { LOG(ERROR) << "send message error " << ", messages: " << msgs->size(); catchUnknownException(); delete msgs; terminate(); } }