You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2017/10/19 12:36:43 UTC
[trafficserver] branch master updated: Add MIOBufferWriter class
which writes to an MIOBuffer instance.
This is an automated email from the ASF dual-hosted git repository.
amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 88431a4 Add MIOBufferWriter class which writes to an MIOBuffer instance.
88431a4 is described below
commit 88431a42abf1df769ceeb826bc4faea26fddbd0d
Author: Walt Karas <wk...@yahoo-inc.com>
AuthorDate: Thu Sep 21 22:40:52 2017 +0000
Add MIOBufferWriter class which writes to an MIOBuffer instance.
---
.gitignore | 1 +
iocore/eventsystem/I_MIOBufferWriter.h | 174 +++++++++++++++++
iocore/eventsystem/Makefile.am | 9 +-
.../eventsystem/unit-tests/test_MIOBufferWriter.cc | 217 +++++++++++++++++++++
4 files changed, 400 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index 2d9b5e0..885d6b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -92,6 +92,7 @@ iocore/net/test_UDPNet
iocore/aio/test_AIO
iocore/eventsystem/test_Buffer
iocore/eventsystem/test_Event
+iocore/eventsystem/test_MIOBufferWriter
iocore/hostdb/test_RefCountCache
proxy/config/records.config.default
diff --git a/iocore/eventsystem/I_MIOBufferWriter.h b/iocore/eventsystem/I_MIOBufferWriter.h
new file mode 100644
index 0000000..3943fc8
--- /dev/null
+++ b/iocore/eventsystem/I_MIOBufferWriter.h
@@ -0,0 +1,174 @@
+#if !defined I_MIOBUFFERWRITER_H_
+#define I_MIOBUFFERWRITER_H_
+
+/** @file
+
+ Buffer Writer for an MIOBuffer.
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#include <cstring>
+
+#include <ts/ink_assert.h>
+#include <ts/BufferWriter.h>
+
+#if !defined(UNIT_TEST_BUFFER_WRITER)
+#include <I_IOBuffer.h>
+#endif
+
+class MIOBufferWriter : public ts::BufferWriter
+{
+public:
+ MIOBufferWriter(MIOBuffer &miob) : _miob(miob) {}
+
+ MIOBufferWriter &
+ write(const void *data_, size_t length) override
+ {
+ const char *data = static_cast<const char *>(data_);
+
+ while (length) {
+ IOBufferBlock *iobbPtr = _miob.first_write_block();
+
+ if (!iobbPtr) {
+ addBlock();
+
+ iobbPtr = _miob.first_write_block();
+
+ ink_assert(iobbPtr);
+ }
+
+ size_t writeSize = iobbPtr->write_avail();
+
+ if (length < writeSize) {
+ writeSize = length;
+ }
+
+ std::memcpy(iobbPtr->end(), data, writeSize);
+ iobbPtr->fill(writeSize);
+
+ data += writeSize;
+ length -= writeSize;
+
+ _numWritten += writeSize;
+ }
+
+ return *this;
+ }
+
+ MIOBufferWriter &
+ write(char c) override
+ {
+ return write(&c, 1);
+ }
+
+ bool
+ error() const override
+ {
+ return false;
+ }
+
+ char *
+ auxBuffer() override
+ {
+ IOBufferBlock *iobbPtr = _miob.first_write_block();
+
+ if (!iobbPtr) {
+ return nullptr;
+ }
+
+ return iobbPtr->end();
+ }
+
+ size_t
+ auxBufferCapacity() const
+ {
+ IOBufferBlock *iobbPtr = _miob.first_write_block();
+
+ if (!iobbPtr) {
+ return 0;
+ }
+
+ return iobbPtr->write_avail();
+ }
+
+ // Write the first n characters that have been placed in the auxiliary buffer. This call invalidates the auxiliary buffer.
+ // This function should not be called if no auxiliary buffer is available.
+ //
+ MIOBufferWriter &
+ write(size_t n) override
+ {
+ if (n) {
+ IOBufferBlock *iobbPtr = _miob.first_write_block();
+
+ ink_assert(iobbPtr and (n <= size_t(iobbPtr->write_avail())));
+
+ iobbPtr->fill(n);
+
+ _numWritten += n;
+ }
+
+ return *this;
+ }
+
+ // No fixed limit on capacity.
+ //
+ size_t
+ capacity() const override
+ {
+ return (~size_t(0));
+ }
+
+ size_t
+ extent() const override
+ {
+ return _numWritten;
+ }
+
+ // Not useful in this derived class.
+ //
+ BufferWriter &clip(size_t) override { return *this; }
+
+ // Not useful in this derived class.
+ //
+ BufferWriter &extend(size_t) override { return *this; }
+
+ // This must not be called for this derived class.
+ //
+ const char *
+ data() const override
+ {
+ ink_assert(false);
+ return nullptr;
+ }
+
+protected:
+ MIOBuffer &_miob;
+
+private:
+ size_t _numWritten = 0;
+
+ virtual void
+ addBlock()
+ {
+ _miob.add_block();
+ }
+};
+
+#endif // include once
diff --git a/iocore/eventsystem/Makefile.am b/iocore/eventsystem/Makefile.am
index 20835e6..c1d24f0 100644
--- a/iocore/eventsystem/Makefile.am
+++ b/iocore/eventsystem/Makefile.am
@@ -68,7 +68,8 @@ libinkevent_a_SOURCES = \
UnixEvent.cc \
UnixEventProcessor.cc
-check_PROGRAMS = test_Buffer test_Event
+check_PROGRAMS = test_Buffer test_Event \
+ test_MIOBufferWriter
test_LD_FLAGS = \
@AM_LDFLAGS@ \
@@ -117,6 +118,12 @@ test_Event_LDFLAGS = $(test_LD_FLAGS)
test_Buffer_LDADD = $(test_LD_ADD)
test_Event_LDADD = $(test_LD_ADD)
+test_MIOBufferWriter_CPPFLAGS = $(AM_CPPFLAGS)\
+ -I$(abs_top_srcdir)/tests/include
+
+test_MIOBufferWriter_SOURCES = \
+ unit-tests/test_MIOBufferWriter.cc
+
include $(top_srcdir)/build/tidy.mk
tidy-local: $(DIST_SOURCES)
diff --git a/iocore/eventsystem/unit-tests/test_MIOBufferWriter.cc b/iocore/eventsystem/unit-tests/test_MIOBufferWriter.cc
new file mode 100644
index 0000000..5665359
--- /dev/null
+++ b/iocore/eventsystem/unit-tests/test_MIOBufferWriter.cc
@@ -0,0 +1,217 @@
+/** @file
+
+ Catch-based unit tests for MIOBufferWriter class.
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
+
+#include <cstdint>
+
+struct IOBufferBlock {
+ std::int64_t write_avail();
+
+ char *end();
+
+ void fill(int64_t);
+};
+
+struct MIOBuffer {
+ IOBufferBlock *first_write_block();
+
+ void add_block();
+};
+
+#define UNIT_TEST_BUFFER_WRITER
+#include "I_MIOBufferWriter.h"
+
+IOBufferBlock iobb[1];
+int iobbIdx{0};
+
+const int BlockSize = 11 * 11;
+char block[BlockSize];
+int blockUsed{0};
+
+std::int64_t
+IOBufferBlock::write_avail()
+{
+ REQUIRE(this == (iobb + iobbIdx));
+ return BlockSize - blockUsed;
+}
+
+char *
+IOBufferBlock::end()
+{
+ REQUIRE(this == (iobb + iobbIdx));
+ return block + blockUsed;
+}
+
+void
+IOBufferBlock::fill(int64_t len)
+{
+ static std::uint8_t dataCheck;
+
+ REQUIRE(this == (iobb + iobbIdx));
+
+ while (len-- and (blockUsed < BlockSize)) {
+ REQUIRE(block[blockUsed] == static_cast<char>(dataCheck));
+
+ ++blockUsed;
+
+ dataCheck += 7;
+ }
+
+ REQUIRE(len == -1);
+}
+
+MIOBuffer theMIOBuffer;
+
+IOBufferBlock *
+MIOBuffer::first_write_block()
+{
+ REQUIRE(this == &theMIOBuffer);
+
+ REQUIRE(blockUsed <= BlockSize);
+
+ if (blockUsed == BlockSize) {
+ return nullptr;
+ }
+
+ return iobb + iobbIdx;
+}
+
+void
+MIOBuffer::add_block()
+{
+ REQUIRE(this == &theMIOBuffer);
+
+ REQUIRE(blockUsed == BlockSize);
+
+ blockUsed = 0;
+
+ ++iobbIdx;
+}
+
+std::string
+genData(int numBytes)
+{
+ static std::uint8_t genData;
+
+ std::string s(numBytes, ' ');
+
+ for (int i{0}; i < numBytes; ++i) {
+ s[i] = genData;
+ genData += 7;
+ }
+
+ return s;
+}
+
+void
+writeOnce(MIOBufferWriter &bw, std::size_t len)
+{
+ static bool toggle;
+
+ std::string s{genData(len)};
+
+ if (len == 1) {
+ bw.write(s[0]);
+
+ } else if (toggle) {
+ std::size_t cap{bw.auxBufferCapacity()};
+
+ if (cap >= len) {
+ memcpy(bw.auxBuffer(), s.data(), len);
+ bw.write(len);
+
+ } else {
+ memcpy(bw.auxBuffer(), s.data(), cap);
+ bw.write(cap);
+ bw.write(s.data() + cap, len - cap);
+ }
+ } else {
+ bw.write(s.data(), len);
+ }
+
+ toggle = !toggle;
+
+ REQUIRE(bw.auxBufferCapacity() <= BlockSize);
+}
+
+class InkAssertExcept
+{
+};
+
+TEST_CASE("MIOBufferWriter", "[MIOBW]")
+{
+ MIOBufferWriter bw(theMIOBuffer);
+
+ REQUIRE(bw.auxBufferCapacity() == BlockSize);
+
+ writeOnce(bw, 0);
+ writeOnce(bw, 1);
+ writeOnce(bw, 1);
+ writeOnce(bw, 1);
+ writeOnce(bw, 10);
+ writeOnce(bw, 1000);
+ writeOnce(bw, 1);
+ writeOnce(bw, 0);
+ writeOnce(bw, 1);
+ writeOnce(bw, 2000);
+ writeOnce(bw, 69);
+ writeOnce(bw, 666);
+
+ for (int i = 0; i < 3000; i += 13) {
+ writeOnce(bw, i);
+ }
+
+ writeOnce(bw, 0);
+ writeOnce(bw, 1);
+
+ REQUIRE(bw.extent() == ((iobbIdx * BlockSize) + blockUsed));
+
+// These tests don't work properly with clang for some reason.
+#if !defined(__clang__)
+
+ try {
+ bw.write(bw.auxBufferCapacity() + 1);
+ REQUIRE(false);
+
+ } catch (InkAssertExcept) {
+ REQUIRE(true);
+ }
+
+ try {
+ bw.data();
+ REQUIRE(false);
+
+ } catch (InkAssertExcept) {
+ REQUIRE(true);
+ }
+
+#endif
+}
+
+void
+_ink_assert(const char *a, const char *f, int l)
+{
+ throw InkAssertExcept();
+}
--
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].