Avoid unnecessary copies by recv()ing data directly into the expat buffer

This commit is contained in:
Florent Le Coz
2014-02-28 01:14:38 +01:00
parent df774d45a9
commit 86d4347af8
8 changed files with 93 additions and 18 deletions
+18 -3
View File
@@ -89,10 +89,20 @@ void XmppComponent::on_connection_close()
log_info("XMPP server closed connection");
}
void XmppComponent::parse_in_buffer()
void XmppComponent::parse_in_buffer(const size_t size)
{
this->parser.feed(this->in_buf.data(), this->in_buf.size(), false);
this->in_buf.clear();
if (!this->in_buf.empty())
{ // This may happen if the parser could not allocate enough space for
// us. We try to feed it the data that was read into our in_buf
// instead. If this fails again we are in trouble.
this->parser.feed(this->in_buf.data(), this->in_buf.size(), false);
this->in_buf.clear();
}
else
{ // Just tell the parser to parse the data that was placed into the
// buffer it provided to us with GetBuffer
this->parser.parse(size, false);
}
}
void XmppComponent::shutdown()
@@ -308,6 +318,11 @@ Bridge* XmppComponent::get_user_bridge(const std::string& user_jid)
}
}
void* XmppComponent::get_receive_buffer(const size_t size) const
{
return this->parser.get_buffer(size);
}
void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, const std::string& to)
{
XmlNode node("message");
+6 -2
View File
@@ -23,7 +23,7 @@ public:
void on_connection_failed(const std::string& reason) override final;
void on_connected() override final;
void on_connection_close() override final;
void parse_in_buffer() override final;
void parse_in_buffer(const size_t size) override final;
/**
* Send a "close" message to all our connected peers. That message
* depends on the protocol used (this may be a QUIT irc message, or a
@@ -142,7 +142,11 @@ private:
* if none already exist.
*/
Bridge* get_user_bridge(const std::string& user_jid);
/**
* Return a buffer provided by the XML parser, to read data directly into
* it, and avoiding some unnecessary copy.
*/
void* get_receive_buffer(const size_t size) const override final;
XmppParser parser;
std::string stream_id;
std::string served_hostname;
+20 -2
View File
@@ -1,6 +1,8 @@
#include <xmpp/xmpp_parser.hpp>
#include <xmpp/xmpp_stanza.hpp>
#include <logger/logger.hpp>
/**
* Expat handlers. Called by the Expat library, never by ourself.
* They just forward the call to the XmppParser corresponding methods.
@@ -45,9 +47,25 @@ XmppParser::~XmppParser()
XML_ParserFree(this->parser);
}
void XmppParser::feed(const char* data, const int len, const bool is_final)
int XmppParser::feed(const char* data, const int len, const bool is_final)
{
XML_Parse(this->parser, data, len, is_final);
int res = XML_Parse(this->parser, data, len, is_final);
if (res == 0)
log_error("Xml_Parse encountered an error");
return res;
}
int XmppParser::parse(const int len, const bool is_final)
{
int res = XML_ParseBuffer(this->parser, len, is_final);
if (res == 0)
log_error("Xml_Parsebuffer encountered an error");
return res;
}
void* XmppParser::get_buffer(const size_t size) const
{
return XML_GetBuffer(this->parser, static_cast<int>(size));
}
void XmppParser::start_element(const XML_Char* name, const XML_Char** attribute)
+9 -1
View File
@@ -37,7 +37,15 @@ public:
/**
* Feed the parser with some XML data
*/
void feed(const char* data, const int len, const bool is_final);
int feed(const char* data, const int len, const bool is_final);
/**
* Parse the data placed in the parser buffer
*/
int parse(const int size, const bool is_final);
/**
* Get a buffer provided by the xml parser.
*/
void* get_buffer(const size_t size) const;
/**
* Add one callback for the various events that this parser can spawn.
*/