From b86994e3f9315b203e927d420cd8def21dcb9e2f Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Mon, 27 Aug 2018 09:17:44 -0700 Subject: [PATCH] common: remove obsolete buffer classes In favor of the simpler StackStreamBuffer. Signed-off-by: Patrick Donnelly --- src/common/CMakeLists.txt | 2 - src/common/CachedPrebufferedStreambuf.cc | 149 ----------------------- src/common/CachedPrebufferedStreambuf.h | 73 ----------- src/common/PrebufferedStreambuf.cc | 102 ---------------- src/common/PrebufferedStreambuf.h | 46 ------- src/log/test.cc | 1 - src/test/CMakeLists.txt | 7 -- src/test/test_prebufferedstreambuf.cc | 95 --------------- 8 files changed, 475 deletions(-) delete mode 100644 src/common/CachedPrebufferedStreambuf.cc delete mode 100644 src/common/CachedPrebufferedStreambuf.h delete mode 100644 src/common/PrebufferedStreambuf.cc delete mode 100644 src/common/PrebufferedStreambuf.h delete mode 100644 src/test/test_prebufferedstreambuf.cc diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index fa85ea598509d..0ef903ef92826 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -7,7 +7,6 @@ add_library(common_texttable_obj OBJECT set(common_srcs AsyncOpTracker.cc BackTrace.cc - CachedPrebufferedStreambuf.cc ConfUtils.cc Cycles.cc DecayCounter.cc @@ -21,7 +20,6 @@ set(common_srcs Mutex.cc OutputDataSocket.cc PluginRegistry.cc - PrebufferedStreambuf.cc PriorityCache.cc Readahead.cc RefCountedObj.cc diff --git a/src/common/CachedPrebufferedStreambuf.cc b/src/common/CachedPrebufferedStreambuf.cc deleted file mode 100644 index 1675c0449a730..0000000000000 --- a/src/common/CachedPrebufferedStreambuf.cc +++ /dev/null @@ -1,149 +0,0 @@ -#include "common/CachedPrebufferedStreambuf.h" -#include - -// std::unique cannot be used here, as deletion will not clear value, -// but thread variable will still exist, causing free-memory-read -struct cached_os_t -{ - CachedPrebufferedStreambuf* streambuf; - cached_os_t() - : streambuf(new CachedPrebufferedStreambuf) - {} - ~cached_os_t() { - delete streambuf; - streambuf = nullptr; - } -}; - -thread_local cached_os_t t_os; - -CachedPrebufferedStreambuf::~CachedPrebufferedStreambuf() -{ - if (this == t_os.streambuf) { - // we are deleting thread's PrebufferedStreambuf, - // clear it so we can create it cleanly again without error - t_os.streambuf = nullptr; - } -} - -// lock state of streambuf and detach buffer -void CachedPrebufferedStreambuf::finish() -{ - data->m_pptr = this->pptr(); - data = nullptr; - if (this != t_os.streambuf) { - // this is extra formatter, not useful anymore - delete this; - } -} - -CachedPrebufferedStreambuf* -CachedPrebufferedStreambuf::create(prebuffered_data* data) -{ - CachedPrebufferedStreambuf* streambuf; - - if (t_os.streambuf == nullptr || /*this can happen only on process cleanup*/ - t_os.streambuf->in_use() /*this happens when we do recursion in logging*/ ) { - streambuf = new CachedPrebufferedStreambuf(); - } else { - streambuf = t_os.streambuf; - // reset ios flags (failbit, badbit) from previous use - streambuf->get_ostream().clear(); - } - streambuf->data = data; - streambuf->setp(data->m_buf, data->m_buf + data->m_buf_len); - // so we underflow on first read - streambuf->setg(0, 0, 0); - return streambuf; -} - -CachedPrebufferedStreambuf::int_type CachedPrebufferedStreambuf::overflow(int_type c) -{ - int old_len = data->m_overflow.size(); - if (old_len == 0) { - data->m_overflow.resize(80); - } else { - data->m_overflow.resize(old_len * 2); - } - data->m_overflow[old_len] = c; - this->setp(&data->m_overflow[old_len + 1], &*data->m_overflow.begin() + data->m_overflow.size()); - return traits_type::not_eof(c); -} - -CachedPrebufferedStreambuf::int_type CachedPrebufferedStreambuf::underflow() -{ - if (this->gptr() == 0) { - // first read; start with the static buffer - if (!data->m_overflow.empty()) - // there is overflow, so start with entire prealloc buffer - this->setg(data->m_buf, data->m_buf, data->m_buf + data->m_buf_len); - else if (this->pptr() == data->m_buf) - // m_buf is empty - return traits_type::eof(); // no data - else - // set up portion of m_buf we've filled - this->setg(data->m_buf, data->m_buf, this->pptr()); - return *this->gptr(); - } - if (this->gptr() == data->m_buf + data->m_buf_len && data->m_overflow.size()) { - // at end of m_buf; continue with the overflow string - this->setg(&data->m_overflow[0], &data->m_overflow[0], this->pptr()); - return *this->gptr(); - } - - // otherwise we must be at the end (of m_buf and/or m_overflow) - return traits_type::eof(); -} - -/// return a string copy (inefficiently) -std::string prebuffered_data::get_str() const -{ - if (!m_overflow.empty()) { - std::string s(m_buf, m_buf + m_buf_len); - s.append(&m_overflow[0], m_pptr - &m_overflow[0]); - return s; - } else if (m_pptr == m_buf) { - return std::string(); - } else { - return std::string(m_buf, m_pptr - m_buf); - } -} - -// returns current size of content -size_t prebuffered_data::size() const -{ - if (m_overflow.empty()) { - return m_pptr - m_buf; - } else { - return m_buf_len + m_pptr - &m_overflow[0]; - } -} - -// extracts up to avail chars of content -int prebuffered_data::snprintf(char* dst, size_t avail) const -{ - size_t len_a; - size_t len_b; - if (!m_overflow.empty()) { - len_a = m_buf_len; - len_b = m_pptr - &m_overflow[0]; - } else { - len_a = m_pptr - m_buf; - len_b = 0; - } - if (avail > len_a + len_b) { - memcpy(dst, m_buf, len_a); - memcpy(dst + m_buf_len, m_overflow.c_str(), len_b); - dst[len_a + len_b] = 0; - } else { - if (avail > len_a) { - memcpy(dst, m_buf, len_a); - memcpy(dst + m_buf_len, m_overflow.c_str(), avail - len_a - 1); - dst[avail - 1] = 0; - } else { - memcpy(dst, m_buf, avail - 1); - dst[avail - 1] = 0; - } - } - return len_a + len_b; -} diff --git a/src/common/CachedPrebufferedStreambuf.h b/src/common/CachedPrebufferedStreambuf.h deleted file mode 100644 index b6a80d6970b5f..0000000000000 --- a/src/common/CachedPrebufferedStreambuf.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef CEPH_COMMON_CACHED_PREBUFFEREDSTREAMBUF_H -#define CEPH_COMMON_CACHED_PREBUFFEREDSTREAMBUF_H - -#include -#include -#include - -/** - * streambuf using existing buffer, overflowing into a std::string - * - * A simple streambuf that uses a preallocated buffer for small - * strings, and overflows into a std::string when necessary. If the - * preallocated buffer size is chosen well, we can optimize for the - * common case and overflow to a slower heap-allocated buffer when - * necessary. - */ -struct prebuffered_data -{ -private: - char *m_buf; - size_t m_buf_len; - char *m_pptr; - std::string m_overflow; - -public: - prebuffered_data(char* buf, size_t buf_len) - : m_buf(buf), m_buf_len(buf_len), m_pptr(nullptr) {} - - /// return a string copy (inefficiently) - std::string get_str() const; - - // returns current size of content - size_t size() const; - - // extracts up to avail chars of content - int snprintf(char* dst, size_t avail) const; - friend class CachedPrebufferedStreambuf; -}; - -class CachedPrebufferedStreambuf final : public std::streambuf -{ -public: - static CachedPrebufferedStreambuf* create(prebuffered_data* d); - - std::ostream& get_ostream() { - return os; - } - - // called when the buffer fills up - int_type overflow(int_type c) override; - - // called when we read and need more data - int_type underflow() override; - - // signals that formatting log has finished - void finish(); - -private: - CachedPrebufferedStreambuf() - : data(nullptr), os(this) {} - ~CachedPrebufferedStreambuf(); - - // determines if instance is currently used for formatting log - bool in_use() const { - return data != nullptr; - } - - prebuffered_data* data; - std::ostream os; - friend class cached_os_t; -}; - -#endif diff --git a/src/common/PrebufferedStreambuf.cc b/src/common/PrebufferedStreambuf.cc deleted file mode 100644 index fe27ef5db0e57..0000000000000 --- a/src/common/PrebufferedStreambuf.cc +++ /dev/null @@ -1,102 +0,0 @@ - -#include "common/PrebufferedStreambuf.h" -#include -PrebufferedStreambuf::PrebufferedStreambuf(char *buf, size_t len) - : m_buf(buf), m_buf_len(len) -{ - // init output buffer - this->setp(m_buf, m_buf + m_buf_len); - - // so we underflow on first read - this->setg(0, 0, 0); -} - -PrebufferedStreambuf::int_type PrebufferedStreambuf::overflow(int_type c) -{ - int old_len = m_overflow.size(); - if (old_len == 0) { - m_overflow.resize(80); - } else { - m_overflow.resize(old_len * 2); - } - m_overflow[old_len] = c; - this->setp(&m_overflow[old_len + 1], &*m_overflow.begin() + m_overflow.size()); - return std::char_traits::not_eof(c); -} - -PrebufferedStreambuf::int_type PrebufferedStreambuf::underflow() -{ - if (this->gptr() == 0) { - // first read; start with the static buffer - if (m_overflow.size()) - // there is overflow, so start with entire prealloc buffer - this->setg(m_buf, m_buf, m_buf + m_buf_len); - else if (this->pptr() == m_buf) - // m_buf is empty - return traits_ty::eof(); // no data - else - // set up portion of m_buf we've filled - this->setg(m_buf, m_buf, this->pptr()); - return *this->gptr(); - } - if (this->gptr() == m_buf + m_buf_len && m_overflow.size()) { - // at end of m_buf; continue with the overflow string - this->setg(&m_overflow[0], &m_overflow[0], this->pptr()); - return *this->gptr(); - } - - // otherwise we must be at the end (of m_buf and/or m_overflow) - return traits_ty::eof(); -} - -std::string PrebufferedStreambuf::get_str() const -{ - if (m_overflow.size()) { - std::string s(m_buf, m_buf + m_buf_len); - s.append(&m_overflow[0], this->pptr() - &m_overflow[0]); - return s; - } else if (this->pptr() == m_buf) { - return std::string(); - } else { - return std::string(m_buf, this->pptr() - m_buf); - } -} -// returns current size of content -size_t PrebufferedStreambuf::size() const -{ - if (m_overflow.size() == 0) { - return this->pptr() - m_buf; - } else { - return m_buf_len + this->pptr() - &m_overflow[0]; - } -} - -// extracts up to avail chars of content -int PrebufferedStreambuf::snprintf(char* dst, size_t avail) const -{ - size_t o_size = m_overflow.size(); - size_t len_a; - size_t len_b; - if (o_size>0) { - len_a = m_buf_len; - len_b = this->pptr() - &m_overflow[0]; - } else { - len_a = this->pptr() - m_buf; - len_b = 0; - } - if (avail > len_a + len_b) { - memcpy(dst, m_buf, len_a); - memcpy(dst + m_buf_len, m_overflow.c_str(), len_b); - dst[len_a + len_b] = 0; - } else { - if (avail > len_a) { - memcpy(dst, m_buf, len_a); - memcpy(dst + m_buf_len, m_overflow.c_str(), avail - len_a - 1); - dst[avail - 1] = 0; - } else { - memcpy(dst, m_buf, avail - 1); - dst[avail - 1] = 0; - } - } - return len_a + len_b; -} diff --git a/src/common/PrebufferedStreambuf.h b/src/common/PrebufferedStreambuf.h deleted file mode 100644 index b7fa21d68b780..0000000000000 --- a/src/common/PrebufferedStreambuf.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef CEPH_COMMON_PREBUFFEREDSTREAMBUF_H -#define CEPH_COMMON_PREBUFFEREDSTREAMBUF_H - -#include - -/** - * streambuf using existing buffer, overflowing into a std::string - * - * A simple streambuf that uses a preallocated buffer for small - * strings, and overflows into a std::string when necessary. If the - * preallocated buffer size is chosen well, we can optimize for the - * common case and overflow to a slower heap-allocated buffer when - * necessary. - */ -class PrebufferedStreambuf - : public std::basic_streambuf::traits_type> -{ - char *m_buf; - size_t m_buf_len; - std::string m_overflow; - - typedef std::char_traits traits_ty; - typedef traits_ty::int_type int_type; - typedef traits_ty::pos_type pos_type; - typedef traits_ty::off_type off_type; - -public: - PrebufferedStreambuf(char *buf, size_t len); - - // called when the buffer fills up - int_type overflow(int_type c) override; - - // called when we read and need more data - int_type underflow() override; - - /// return a string copy (inefficiently) - std::string get_str() const; - - // returns current size of content - size_t size() const; - - // extracts up to avail chars of content - int snprintf(char* dst, size_t avail) const; -}; - -#endif diff --git a/src/log/test.cc b/src/log/test.cc index d127064bdb0b2..2e650cb993713 100644 --- a/src/log/test.cc +++ b/src/log/test.cc @@ -2,7 +2,6 @@ #include "log/Log.h" #include "common/Clock.h" -#include "common/PrebufferedStreambuf.h" #include "include/coredumpctl.h" #include "SubsystemMap.h" diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 89337178940ca..b9d67a1a3dee8 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -630,13 +630,6 @@ if(WITH_LIBRADOSSTRIPER) target_link_libraries(unittest_striper global ${BLKID_LIBRARIES}) endif() -# unittest_prebufferedstreambuf -add_executable(unittest_prebufferedstreambuf - test_prebufferedstreambuf.cc - ) -add_ceph_unittest(unittest_prebufferedstreambuf) -target_link_libraries(unittest_prebufferedstreambuf global) - # unittest_str_list add_executable(unittest_str_list test_str_list.cc diff --git a/src/test/test_prebufferedstreambuf.cc b/src/test/test_prebufferedstreambuf.cc deleted file mode 100644 index 489a985d8b430..0000000000000 --- a/src/test/test_prebufferedstreambuf.cc +++ /dev/null @@ -1,95 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "common/PrebufferedStreambuf.h" -#include "gtest/gtest.h" - -TEST(PrebufferedStreambuf, Empty) -{ - char buf[10]; - PrebufferedStreambuf sb(buf, sizeof(buf)); - - std::istream is(&sb); - std::string out; - getline(is, out); - ASSERT_EQ("", out); -} - -TEST(PrebufferedStreambuf, Simple) -{ - char buf[10]; - PrebufferedStreambuf sb(buf, sizeof(buf)); - - std::ostream os(&sb); - os << "test"; - - std::istream is(&sb); - std::string out; - getline(is, out); - ASSERT_EQ("test", out); -} - -TEST(PrebufferedStreambuf, Multiline) -{ - char buf[10]; - PrebufferedStreambuf sb(buf, sizeof(buf)); - - std::ostream os(&sb); - const char *s = "this is a line\nanother line\nand a third\nwhee!\n"; - os << s; - - std::istream is(&sb); - std::string out; - getline(is, out, is.widen(0)); - ASSERT_EQ(s, out); -} - -TEST(PrebufferedStreambuf, Withnull) -{ - char buf[10]; - PrebufferedStreambuf sb(buf, sizeof(buf)); - - std::ostream os(&sb); - std::string s("null \0 and more", 15); - os << s; - - std::istream is(&sb); - std::string out; - getline(is, out); - ASSERT_EQ(s, out); -} - -TEST(PrebufferedStreambuf, SimpleOverflow) -{ - char buf[10]; - PrebufferedStreambuf sb(buf, sizeof(buf)); - - std::ostream os(&sb); - const char *s = "hello, this is longer than buf[10]"; - os << s; - - ASSERT_EQ(s, sb.get_str()); - - std::istream is(&sb); - std::string out; - getline(is, out); - ASSERT_EQ(s, out); -} - -TEST(PrebufferedStreambuf, ManyOverflow) -{ - char buf[10]; - PrebufferedStreambuf sb(buf, sizeof(buf)); - - std::ostream os(&sb); - const char *s = "hello, this way way way way way way way way way way way way way way way way way way way way way way way way way _way_ longer than buf[10]"; - os << s; - - ASSERT_EQ(s, sb.get_str()); - - std::istream is(&sb); - std::string out; - getline(is, out); - ASSERT_EQ(s, out); -} - -- 2.39.5