panthema / 2013 / parallel-string-sorting / parallel-string-sorting-0.6.5 / src / tools / stats_writer.h (Download File)
/******************************************************************************
 * examples/stats_writer.h
 *
 * Class to collect and output statistics as key=value pairs.
 *
 * The usual method to use this stats collector is to make a global object
 * stats_writer g_stats, which is filled by algorithms using sequences as.
 *
 * g_stats >> "key" << "value " << 42;
 *
 * After the program was run, the stats are formatted as a RESULT line using
 * get(), which can be outputted to a file or stdout.
 *
 ******************************************************************************
 * Copyright (C) 2012-2014 Timo Bingmann <tb@panthema.net>
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

#ifndef SQLPLOTS_STATS_WRITER_H
#define SQLPLOTS_STATS_WRITER_H

#include <string>
#include <sstream>

#include <unistd.h>
#include <time.h>

/*!
 * Collect key=value pairs, which are given by operator >> and operator <<
 * sequences. After all stats are set, the final output line can be fetched.
 */
class stats_writer
{
protected:

    //! All collected key=value values.
    std::ostringstream  m_line;

    //! An internal class to collect key=value pairs as a sequence of >> and <<
    //! operator calls.
    class entry
    {
    protected:
        //! Reference to parent stats writer object
        class stats_writer& m_sw;

        //! Collected key and value string items
        std::string m_key, m_value;

    public:

        //! Start entry collection for the given key
        entry(stats_writer& sw, const std::string& key)
            : m_sw(sw), m_key(key)
        { }

        //! Collect more information about the value
        entry& operator << (const std::string& v)
        {
            m_value += v;
            return *this;
        }

        //! Collect more information about the value
        template <typename ValueType>
        entry& operator << (const ValueType& v)
        {
            std::ostringstream vstr;
            vstr << v;
            return operator << (vstr.str());
        }

        //! Start another key= entry via parent
        template <typename ValueType>
        entry operator >> (const ValueType& v)
        {
            // put key=value into writer before returning next entry
            m_sw.put(m_key, m_value);
            m_key.clear(); m_value.clear();
            return m_sw.operator >> (v);
        }

        //! Output key=value to stats writer for the last entry
        ~entry()
        {
            if (m_key.size() || m_value.size())
                m_sw.put(m_key, m_value);
        }
    };

public:

    //! Clear all data in the stats writer.
    void clear()
    {
        m_line.str("");
    }

    //! Append a (key,value) pair as ">> key << value << more"
    entry operator >> (const std::string& k)
    {
        return entry(*this, k);
    }

    //! Append a (key,value) pair as ">> key << value << more"
    template <typename KeyType>
    entry operator >> (const KeyType& k)
    {
        std::ostringstream kstr;
        kstr << k;
        return operator >> (kstr.str());
    }

    //! Append a (key,value) pair as strings
    stats_writer& put(const std::string& k, const std::string& v)
    {
#if _OPENMP
#pragma omp critical
#endif
        m_line << '\t' << k << '=' << v;
        return *this;
    }

    //! Append a (key,value) pair with automatic conversion to strings
    template <typename KeyType, typename ValueType>
    stats_writer& put(const KeyType& k, const ValueType& v)
    {
        std::ostringstream kstr, vstr;
        kstr << k; vstr << v;
        return put(kstr.str(), vstr.str());
    }

    //! Return RESULT string for outputting.
    std::string get() const
    {
        std::ostringstream out;
        out << "RESULT";

        // output date, time and hostname

        char datetime[64];
        time_t tnow = time(NULL);

        strftime(datetime,sizeof(datetime),"%Y-%m-%d %H:%M:%S", localtime(&tnow));
        out << "\tdatetime=" << datetime;

        char hostname[128];
        gethostname(hostname, sizeof(hostname));

        out << "\thost=" << hostname;

        // output collected key=values

        out << m_line.str();

        return out.str();
    }

    //! Return RESULT string for outputting.
    friend std::ostream& operator << (std::ostream& os, const stats_writer& sw)
    {
        return os << sw.get();
    }
};

#endif // SQLPLOTS_STATS_WRITER_H