From a652b6bd5bb04e4be43dfb5c68a0dea979f63ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 8 May 2019 07:59:24 +0300 Subject: [PATCH] Add advance(int) to mxs::Buffer iterators This makes iterating over packets in buffers faster while still maintaining the requirements for forward iterators. Not using operator+= makes it clear that this is not a random access iterator. --- include/maxscale/buffer.hh | 36 ++++++++++++++++++++++ server/modules/protocol/MySQL/rwbackend.cc | 11 ++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/include/maxscale/buffer.hh b/include/maxscale/buffer.hh index 914c54c7a..cfe987e68 100644 --- a/include/maxscale/buffer.hh +++ b/include/maxscale/buffer.hh @@ -78,6 +78,42 @@ public: return &m_i; } + /** + * Advance the iterator + * + * This provides similar behavior to random access iterators with operator+= but does it in + * non-constant time. + * + * @param i Number of steps to advance the iterator + */ + void advance(int i) + { + mxb_assert(m_i != m_end); + mxb_assert(i >= 0); + + while (m_i && m_i + i >= m_end) + { + i -= m_end - m_i; + m_pBuffer = m_pBuffer->next; + + if (m_pBuffer) + { + m_i = GWBUF_DATA(m_pBuffer); + m_end = m_i + GWBUF_LENGTH(m_pBuffer); + } + else + { + m_i = NULL; + m_end = NULL; + } + } + + if (m_i) + { + m_i += i; + } + } + protected: iterator_base(buf_type pBuffer = NULL) : m_pBuffer(pBuffer) diff --git a/server/modules/protocol/MySQL/rwbackend.cc b/server/modules/protocol/MySQL/rwbackend.cc index 208192e8c..2dd8a9d22 100644 --- a/server/modules/protocol/MySQL/rwbackend.cc +++ b/server/modules/protocol/MySQL/rwbackend.cc @@ -196,19 +196,19 @@ Iter skip_encoded_int(Iter it) switch (*it) { case 0xfc: - std::advance(it, 3); + it.advance(3); break; case 0xfd: - std::advance(it, 4); + it.advance(4); break; case 0xfe: - std::advance(it, 9); + it.advance(9); break; default: - std::advance(it, 1); + ++it; break; } @@ -293,7 +293,8 @@ void RWBackend::process_packets(GWBUF* result) len |= (*it++) << 16; ++it; // Skip the sequence mxb_assert(it != buffer.end()); - auto end = std::next(it, len); + auto end = it; + end.advance(len); uint8_t cmd = *it; // Ignore the tail end of a large packet large packet. Only resultsets can generate packets this large