BIND 10 master, updated. 5eeba2034481f043369f9a7f3f86ce606653387e Merge branch 'work/perf/obuffer'
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Apr 7 15:15:16 UTC 2011
The branch, master has been updated
via 5eeba2034481f043369f9a7f3f86ce606653387e (commit)
via 86ab4d3fabd2e551f90603d81ff2bce2368ea7af (commit)
via 865d62e9e58a3acf270f163a75ba713c134d82d2 (commit)
via aac391dda57b88507b8b10ac4bd1b068d3701b2d (commit)
via 501462d7b9850ddca6a3d0a2c7043e3fa0923759 (commit)
via 044c080dd3fc084f3ee7dcdcc70c8dc328bee9df (commit)
via 1cd8ba5e307c77ae9bc2563569366c43623bbc75 (commit)
via 8599f0c0c2ebe7043dd65458a2302837f7c43895 (commit)
via 902005dceae646aefc03c2005e1ff2896efb909c (commit)
from 3b6ddc0b213a61abf826d87351d97de9145a3fc4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 5eeba2034481f043369f9a7f3f86ce606653387e
Merge: 86ab4d3fabd2e551f90603d81ff2bce2368ea7af 865d62e9e58a3acf270f163a75ba713c134d82d2
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Thu Apr 7 17:03:27 2011 +0200
Merge branch 'work/perf/obuffer'
commit 86ab4d3fabd2e551f90603d81ff2bce2368ea7af
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Thu Apr 7 17:02:44 2011 +0200
[master] Hopefully fix Makefile
It failed to build a test, because the file was generated in another
directory and probably didn't yet exist at the time.
commit 865d62e9e58a3acf270f163a75ba713c134d82d2
Author: Shane Kerr <shane at isc.org>
Date: Thu Apr 7 15:16:46 2011 +0200
Added check for another malloc() that might try to allocate 0 bytes.
commit aac391dda57b88507b8b10ac4bd1b068d3701b2d
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Thu Apr 7 12:39:00 2011 +0200
[trac536] Handle empty buffers
commit 501462d7b9850ddca6a3d0a2c7043e3fa0923759
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jan 31 17:25:39 2011 +0100
[trac536] Some comments
commit 044c080dd3fc084f3ee7dcdcc70c8dc328bee9df
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jan 31 11:01:51 2011 +0100
[trac536] Smaller return value
commit 1cd8ba5e307c77ae9bc2563569366c43623bbc75
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jan 31 10:55:56 2011 +0100
[trac536] The access methods
Writes, reads.
commit 8599f0c0c2ebe7043dd65458a2302837f7c43895
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri Jan 28 20:37:15 2011 +0100
[trac536] Allocation and dealocation routines
The rest of class is still not updated, it doesn't compile yet.
commit 902005dceae646aefc03c2005e1ff2896efb909c
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri Jan 28 19:53:38 2011 +0100
[trac536] Test copy and assignment of OutputBuffer
-----------------------------------------------------------------------
Summary of changes:
src/bin/auth/tests/Makefile.am | 7 ++
src/lib/dns/buffer.h | 128 +++++++++++++++++++++++++++-------
src/lib/dns/tests/buffer_unittest.cc | 49 +++++++++++++
3 files changed, 159 insertions(+), 25 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/auth/tests/Makefile.am b/src/bin/auth/tests/Makefile.am
index 0e37da5..22c9c02 100644
--- a/src/bin/auth/tests/Makefile.am
+++ b/src/bin/auth/tests/Makefile.am
@@ -16,6 +16,12 @@ CLEANFILES = *.gcno *.gcda
TESTS =
if HAVE_GTEST
+../spec_config.h: ../spec_config.h.pre
+ $(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
+
+CLEANFILES += ../spec_config.h
+
+BUILT_SOURCES = ../spec_config.h
TESTS += run_unittests
run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
@@ -25,6 +31,7 @@ run_unittests_SOURCES += ../change_user.h ../change_user.cc
run_unittests_SOURCES += ../auth_config.h ../auth_config.cc
run_unittests_SOURCES += ../command.h ../command.cc
run_unittests_SOURCES += ../common.h ../common.cc
+run_unittests_SOURCES += ../spec_config.h
run_unittests_SOURCES += ../statistics.h ../statistics.cc
run_unittests_SOURCES += auth_srv_unittest.cc
run_unittests_SOURCES += config_unittest.cc
diff --git a/src/lib/dns/buffer.h b/src/lib/dns/buffer.h
index c824154..c451f1b 100644
--- a/src/lib/dns/buffer.h
+++ b/src/lib/dns/buffer.h
@@ -15,6 +15,8 @@
#ifndef __BUFFER_H
#define __BUFFER_H 1
+#include <cstdlib>
+#include <cstring>
#include <vector>
#include <string.h>
@@ -286,15 +288,58 @@ public:
/// \brief Constructor from the initial size of the buffer.
///
/// \param len The initial length of the buffer in bytes.
- OutputBuffer(size_t len) { data_.reserve(len); }
+ OutputBuffer(size_t len) :
+ buffer_(NULL),
+ size_(0),
+ allocated_(len)
+ {
+ // We use malloc and free instead of C++ new[] and delete[].
+ // This way we can use realloc, which may in fact do it without a copy.
+ buffer_ = static_cast<uint8_t*>(malloc(allocated_));
+ if (buffer_ == NULL && len != 0) {
+ throw std::bad_alloc();
+ }
+ }
+
+ /// \brief Copy constructor
+ OutputBuffer(const OutputBuffer& other) :
+ buffer_(NULL),
+ size_(other.size_),
+ allocated_(other.allocated_)
+ {
+ buffer_ = static_cast<uint8_t*>(malloc(allocated_));
+ if (buffer_ == NULL && allocated_ != 0) {
+ throw std::bad_alloc();
+ }
+ memcpy(buffer_, other.buffer_, size_);
+ }
+
+ /// \brief Destructor
+ ~ OutputBuffer() {
+ free(buffer_);
+ }
//@}
+ /// \brief Assignment operator
+ OutputBuffer& operator =(const OutputBuffer& other) {
+ uint8_t* newbuff(static_cast<uint8_t*>(malloc(other.allocated_)));
+ if (newbuff == NULL && other.allocated_ != 0) {
+ throw std::bad_alloc();
+ }
+ free(buffer_);
+ buffer_ = newbuff;
+ size_ = other.size_;
+ allocated_ = other.allocated_;
+ memcpy(buffer_, other.buffer_, size_);
+ return (*this);
+ }
+
///
/// \name Getter Methods
///
//@{
/// \brief Return the current capacity of the buffer.
- size_t getCapacity() const { return (data_.capacity()); }
+ size_t getCapacity() const { return (allocated_); }
/// \brief Return a pointer to the head of the data stored in the buffer.
///
/// The caller can assume that the subsequent \c getLength() bytes are
@@ -302,21 +347,21 @@ public:
///
/// Note: The pointer returned by this method may be invalidated after a
/// subsequent write operation.
- const void* getData() const { return (&data_[0]); }
+ const void* getData() const { return (buffer_); }
/// \brief Return the length of data written in the buffer.
- size_t getLength() const { return (data_.size()); }
+ size_t getLength() const { return (size_); }
/// \brief Return the value of the buffer at the specified position.
///
/// \c pos must specify the valid position of the buffer; otherwise an
/// exception class of \c InvalidBufferPosition will be thrown.
///
/// \param pos The position in the buffer to be returned.
- const uint8_t& operator[](size_t pos) const
+ uint8_t operator[](size_t pos) const
{
- if (pos >= data_.size()) {
+ if (pos >= size_) {
isc_throw(InvalidBufferPosition, "read at invalid position");
}
- return (data_[pos]);
+ return (buffer_[pos]);
}
//@}
@@ -330,7 +375,10 @@ public:
/// This method is provided as a shortcut to make a hole in the buffer
/// that is to be filled in later, e.g, by \ref writeUint16At().
/// \param len The length of the gap to be inserted in bytes.
- void skip(size_t len) { data_.insert(data_.end(), len, 0); }
+ void skip(size_t len) {
+ ensureAllocated(size_ + len);
+ size_ += len;
+ }
/// \brief Trim the specified length of data from the end of the buffer.
///
@@ -341,20 +389,23 @@ public:
/// \param len The length of data that should be trimmed.
void trim(size_t len)
{
- if (len > data_.size()) {
+ if (len > size_) {
isc_throw(OutOfRange, "trimming too large from output buffer");
}
- data_.resize(data_.size() - len);
+ size_ -= len;
}
/// \brief Clear buffer content.
///
/// This method can be used to re-initialize and reuse the buffer without
/// constructing a new one.
- void clear() { data_.clear(); }
+ void clear() { size_ = 0; }
/// \brief Write an unsigned 8-bit integer into the buffer.
///
/// \param data The 8-bit integer to be written into the buffer.
- void writeUint8(uint8_t data) { data_.push_back(data); }
+ void writeUint8(uint8_t data) {
+ ensureAllocated(size_ + 1);
+ buffer_[size_ ++] = data;
+ }
/// \brief Write an unsigned 8-bit integer into the buffer.
///
@@ -377,8 +428,9 @@ public:
/// \param data The 16-bit integer to be written into the buffer.
void writeUint16(uint16_t data)
{
- data_.push_back(static_cast<uint8_t>((data & 0xff00U) >> 8));
- data_.push_back(static_cast<uint8_t>(data & 0x00ffU));
+ ensureAllocated(size_ + sizeof(data));
+ buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff00U) >> 8);
+ buffer_[size_ ++] = static_cast<uint8_t>(data & 0x00ffU);
}
/// \brief Write an unsigned 16-bit integer in host byte order at the
/// specified position of the buffer in network byte order.
@@ -393,12 +445,12 @@ public:
/// \param pos The beginning position in the buffer to write the data.
void writeUint16At(uint16_t data, size_t pos)
{
- if (pos + sizeof(data) > data_.size()) {
+ if (pos + sizeof(data) > size_) {
isc_throw(InvalidBufferPosition, "write at invalid position");
}
- data_[pos] = static_cast<uint8_t>((data & 0xff00U) >> 8);
- data_[pos + 1] = static_cast<uint8_t>(data & 0x00ffU);
+ buffer_[pos] = static_cast<uint8_t>((data & 0xff00U) >> 8);
+ buffer_[pos + 1] = static_cast<uint8_t>(data & 0x00ffU);
}
/// \brief Write an unsigned 32-bit integer in host byte order
/// into the buffer in network byte order.
@@ -406,10 +458,11 @@ public:
/// \param data The 32-bit integer to be written into the buffer.
void writeUint32(uint32_t data)
{
- data_.push_back(static_cast<uint8_t>((data & 0xff000000) >> 24));
- data_.push_back(static_cast<uint8_t>((data & 0x00ff0000) >> 16));
- data_.push_back(static_cast<uint8_t>((data & 0x0000ff00) >> 8));
- data_.push_back(static_cast<uint8_t>(data & 0x000000ff));
+ ensureAllocated(size_ + sizeof(data));
+ buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff000000) >> 24);
+ buffer_[size_ ++] = static_cast<uint8_t>((data & 0x00ff0000) >> 16);
+ buffer_[size_ ++] = static_cast<uint8_t>((data & 0x0000ff00) >> 8);
+ buffer_[size_ ++] = static_cast<uint8_t>(data & 0x000000ff);
}
/// \brief Copy an arbitrary length of data into the buffer.
///
@@ -419,13 +472,38 @@ public:
/// \param len The length of the data in bytes.
void writeData(const void *data, size_t len)
{
- const uint8_t* cp = static_cast<const uint8_t*>(data);
- data_.insert(data_.end(), cp, cp + len);
+ ensureAllocated(size_ + len);
+ memcpy(buffer_ + size_, data, len);
+ size_ += len;
}
//@}
-
+
private:
- std::vector<uint8_t> data_;
+ // The actual data
+ uint8_t* buffer_;
+ // How many bytes are used
+ size_t size_;
+ // How many bytes do we have preallocated (eg. the capacity)
+ size_t allocated_;
+ // Make sure at last needed_size bytes are allocated in the buffer
+ void ensureAllocated(size_t needed_size) {
+ if (allocated_ < needed_size) {
+ // Guess some bigger size
+ size_t new_size = (allocated_ == 0) ? 1024 : allocated_;
+ while (new_size < needed_size) {
+ new_size *= 2;
+ }
+ // Allocate bigger space
+ uint8_t* new_buffer_(static_cast<uint8_t*>(realloc(buffer_,
+ new_size)));
+ if (new_buffer_ == NULL) {
+ // If it fails, the original block is left intact by it
+ throw std::bad_alloc();
+ }
+ buffer_ = new_buffer_;
+ allocated_ = new_size;
+ }
+ }
};
/// \brief Pointer-like types pointing to \c InputBuffer or \c OutputBuffer
diff --git a/src/lib/dns/tests/buffer_unittest.cc b/src/lib/dns/tests/buffer_unittest.cc
index 2fe5a10..0973912 100644
--- a/src/lib/dns/tests/buffer_unittest.cc
+++ b/src/lib/dns/tests/buffer_unittest.cc
@@ -190,4 +190,53 @@ TEST_F(BufferTest, outputBufferClear) {
obuffer.clear();
EXPECT_EQ(0, obuffer.getLength());
}
+
+TEST_F(BufferTest, outputBufferCopy) {
+ obuffer.writeData(testdata, sizeof(testdata));
+
+ EXPECT_NO_THROW({
+ OutputBuffer copy(obuffer);
+ ASSERT_EQ(sizeof(testdata), copy.getLength());
+ for (int i = 0; i < sizeof(testdata); i ++) {
+ EXPECT_EQ(testdata[i], copy[i]);
+ if (i + 1 < sizeof(testdata)) {
+ obuffer.writeUint16At(0, i);
+ }
+ EXPECT_EQ(testdata[i], copy[i]);
+ }
+ obuffer.clear();
+ ASSERT_EQ(sizeof(testdata), copy.getLength());
+ });
+}
+
+TEST_F(BufferTest, outputBufferAssign) {
+ OutputBuffer another(0);
+ another.clear();
+ obuffer.writeData(testdata, sizeof(testdata));
+
+ EXPECT_NO_THROW({
+ another = obuffer;
+ ASSERT_EQ(sizeof(testdata), another.getLength());
+ for (int i = 0; i < sizeof(testdata); i ++) {
+ EXPECT_EQ(testdata[i], another[i]);
+ if (i + 1 < sizeof(testdata)) {
+ obuffer.writeUint16At(0, i);
+ }
+ EXPECT_EQ(testdata[i], another[i]);
+ }
+ obuffer.clear();
+ ASSERT_EQ(sizeof(testdata), another.getLength());
+ });
+}
+
+TEST_F(BufferTest, outputBufferZeroSize) {
+ // Some OSes might return NULL on malloc for 0 size, so check it works
+ EXPECT_NO_THROW({
+ OutputBuffer first(0);
+ OutputBuffer copy(first);
+ OutputBuffer second(0);
+ second = first;
+ });
+}
+
}
More information about the bind10-changes
mailing list