From 0ea601ab26d58ccf57a018b5545ee573572ec68e Mon Sep 17 00:00:00 2001 From: Colin Patrick McCabe Date: Fri, 5 Nov 2010 16:11:18 -0700 Subject: [PATCH] Create SyslogStreambuf SyslogStreambuf is a kind of stream buffer that allows you to output characters from an ostream to syslog. Most standard IO streams can make use of this Streambuf. Signed-off-by: Colin McCabe --- src/Makefile.am | 8 ++- src/common/SyslogStreambuf.cc | 98 +++++++++++++++++++++++++++++++++ src/common/SyslogStreambuf.h | 54 ++++++++++++++++++ src/test/TestSyslogStreambuf.cc | 70 +++++++++++++++++++++++ 4 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 src/common/SyslogStreambuf.cc create mode 100644 src/common/SyslogStreambuf.h create mode 100644 src/test/TestSyslogStreambuf.cc diff --git a/src/Makefile.am b/src/Makefile.am index e4ed5856b8d2d..ea4dc3e0dda07 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -193,6 +193,10 @@ testencoding_SOURCES = test/TestEncoding.cc testencoding_LDADD = libceph.la libcrush.la -lpthread -lm -lcrypto bin_PROGRAMS += testencoding +testsyslog_streambuf_SOURCES = test/TestSyslogStreambuf.cc +testsyslog_streambuf_LDADD = libceph.la libcrush.la -lpthread +bin_PROGRAMS += testsyslog_streambuf + endif # librados @@ -447,7 +451,8 @@ libcommon_files = \ include/ceph_frag.cc \ config.cc \ common/page.cc \ - common/lockdep.cc + common/lockdep.cc \ + common/SyslogStreambuf.cc libcrush_a_SOURCES = \ crush/builder.c \ @@ -580,6 +585,7 @@ noinst_HEADERS = \ common/Mutex.h\ common/RWLock.h\ common/Semaphore.h\ + common/SyslogStreambuf.h\ common/Thread.h\ common/Throttle.h\ common/Timer.h\ diff --git a/src/common/SyslogStreambuf.cc b/src/common/SyslogStreambuf.cc new file mode 100644 index 0000000000000..7c30c4f26b8f8 --- /dev/null +++ b/src/common/SyslogStreambuf.cc @@ -0,0 +1,98 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2010 Dreamhost + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include "common/SyslogStreambuf.h" + +#include +#include +#include +#include +#include +#include + +template +SyslogStreambuf::SyslogStreambuf() +{ + // Initialize get pointer to zero so that underflow is called on the first read. + this->setg(0, 0, 0); + + // Set up the put pointer. + // Overflow is called when this buffer is filled + this->setp(obuf, obuf + OBUF_SZ - 2); + + // Zero the output buffer + memset(obuf, 0, OBUF_SZ); +} + +// This function is called when the output buffer is filled. +// In this function, the buffer should be written to wherever it should +// be written to (in this case, the streambuf object that this is controlling). +template +typename SyslogStreambuf::int_type +SyslogStreambuf::overflow(SyslogStreambuf::int_type c) +{ + charT* end = this->pptr(); + + // Add an eof character to the buffer if we need to. + if(!traits_ty::eq_int_type(c, traits_ty::eof())) { + *end++ = traits_ty::to_char_type(c); + } + *end++ = '\0'; + + //std::cout << "overflow with '" << obuf << "'" << std::endl; + + // int_type ilen = end - obuf; // Compute the write length. + syslog(LOG_USER | LOG_NOTICE, "%s", obuf); + + // Reset put pointers + setp(obuf, obuf + OBUF_SZ - 1); + obuf[0] = '\0'; + + // A value different than EOF (or traits::eof() for other traits) signals success. + // If the function fails, either EOF (or traits::eof() for other traits) is returned or an + // exception is thrown. + return traits_ty::not_eof(c); +} + +// This is called to flush the buffer. +// This is called when we're done with the file stream (or when .flush() is called). +template +typename SyslogStreambuf::int_type +SyslogStreambuf::sync() +{ + //std::cout << "flush!" << std::endl; + + // Don't bother calling overflow if there's nothing to syslog + if (obuf[0] == '\0') + return 0; + + typename SyslogStreambuf::int_type + ret(this->overflow(traits_ty::eof())); + if (ret == traits_ty::eof()) + return -1; + + return 0; +} + +template +typename SyslogStreambuf::int_type +SyslogStreambuf::underflow() +{ + // We can't read from this + // TODO: some more elegant way of preventing callers from trying to get input from this stream + assert(0); +} + +// Explicit template instantiation +template class SyslogStreambuf ; diff --git a/src/common/SyslogStreambuf.h b/src/common/SyslogStreambuf.h new file mode 100644 index 0000000000000..c55db5cdece22 --- /dev/null +++ b/src/common/SyslogStreambuf.h @@ -0,0 +1,54 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2010 Dreamhost + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* + * SyslogStreambuf + * + * A stream buffer that writes its output to syslog. + */ +#ifndef CEPH_SYSLOG_STREAMBUF_H +#define CEPH_SYSLOG_STREAMBUF_H + +#include + +template > +class SyslogStreambuf : public std::basic_streambuf +{ +public: + typedef traits traits_ty; + typedef typename traits_ty::int_type int_type; + typedef typename traits_ty::pos_type pos_type; + typedef typename traits_ty::off_type off_type; + + // The size of the input and output buffers. + static const size_t OBUF_SZ = 32000; + + SyslogStreambuf(); + +protected: + // Called when the buffer fills up + virtual int_type overflow(int_type c); + + // Called when the buffer is flushed + virtual int_type sync(); + + // Called when we try to read, but there are no more chars in the buffer + virtual int_type underflow(); + +private: + // Output buffer + charT obuf[OBUF_SZ]; +}; + +#endif diff --git a/src/test/TestSyslogStreambuf.cc b/src/test/TestSyslogStreambuf.cc new file mode 100644 index 0000000000000..cd6469d8d2fe5 --- /dev/null +++ b/src/test/TestSyslogStreambuf.cc @@ -0,0 +1,70 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2010 Dreamhost + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* + * TestSyslogStreambuf + * + * Puts some output into the SyslogStreambuf class. + * Check your syslog to see what it did. + */ +#include "common/SyslogStreambuf.h" +#include "common/common_init.h" +#include "config.h" + +#include +#include +#include + +using std::cout; +using std::cerr; +using std::string; + +int main(int argc, const char **argv) +{ + vector args; + argv_to_vec(argc, argv, args); + env_to_vec(args); + + ceph_set_default_id("admin"); + common_set_defaults(false); + common_init(args, "ceph", true); + + std::ostream oss(new SyslogStreambuf); + + oss << "I am logging to syslog now!" << std::endl; + + oss << "And here is another line!" << std::endl; + + oss.flush(); + + oss << "Stuff "; + oss << "that "; + oss << "will "; + oss << "all "; + oss << "be "; + oss << "on "; + oss << "one "; + oss << "line."; + oss.flush(); + + oss << "There will be no blank lines here." << std::endl; + oss.flush(); + oss.flush(); + oss.flush(); + + oss << "But here is a blank line:" << std::endl; + oss << std::endl; + + return 0; +} -- 2.39.5