MXS-1777 Create new utility library

The purpose of this library is to create a utility library that is not
dependent on maxscale for use in both maxscale and system test, and
possibly other apps. As time permits general purpose utilities from
maxscale-common can be moved to the new library.

Here are answers to questions you may have:
- A top level directory "maxutils" contains the libraries. The current
  structure is simply maxutils/maxbase. Each library has an 'include' and
  a 'scr' directory where public headers exist in 'include'
- Code is in a namespace with the same name as the directory.
- Headers are included like this: `#include <maxbase/stopwatch.hh>`
- In case the library is published on its own, the include directives stay
  the same (headers would be in /usr/include/maxutil, for example).
- I am not advocating many small libraries. But if some larger library
  is written, say a general purpose statemachine, it would not pollute
  util/maxutil but go to util/maxsm.
  Another example: Worker. It is a larger concept, but used so widely in
  code that it could very well live in maxutil.

NOTE: this was previously Review Request #6245.
This commit is contained in:
Niclas Antti
2018-06-07 17:22:21 +03:00
parent a812e02ba4
commit 2514c99d9e
7 changed files with 617 additions and 0 deletions

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2018 MariaDB Corporation Ab
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
*
* Change Date: 2020-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#pragma once
#include <maxbase/stopwatch.hh>
#include <iosfwd>
#include <vector>
namespace maxbase
{
/**
* @brief Keep a count of an events for a time period from "now" into the past.
*
* Events are stored, or distinguished, with timestamps of a given granularity.
* For example, if the granularity is set to 1s, each time an event is reported the current
* time is rounded down to the nearest whole second. All events that round down to the same
* second share a single entry in the EventCount. Granularity==0 causes all events (timestamps)
* to be stored in their own entry, which could use large amounts of memory.
*
*/
class EventCount
{
public:
EventCount(const EventCount&) = delete;
EventCount& operator=(const EventCount&) = delete;
explicit EventCount(const std::string& event_id, Duration time_window,
Duration granularity = Duration(std::chrono::milliseconds(10)));
EventCount(EventCount&&); // can't be defaulted in gcc 4.4
EventCount& operator=(EventCount&&); // can't be defaulted in gcc 4.4
const std::string& event_id() const
{
return m_event_id;
}
Duration time_window() const
{
return m_time_window;
}
void dump(std::ostream& os) const;
int count() const;
void increment();
// these defs need not be public once lambdas are available
struct Timestamp
{
TimePoint time_point;
int count;
Timestamp(TimePoint p, int c) : time_point(p), count(c) {}
};
private:
void purge() const; // remove out of window stats
std::string m_event_id;
Duration m_time_window;
Duration::rep m_granularity;
mutable std::vector<Timestamp> m_timestamps;
};
std::ostream& operator<<(std::ostream& os, const EventCount& stats);
// Time series statistics for a Session (a collection of related EventCount).
class SessionCount
{
public:
SessionCount(const SessionCount&) = delete;
SessionCount& operator=(const SessionCount&) = delete;
SessionCount(const std::string& sess_id, Duration time_window,
Duration granularity = Duration(std::chrono::milliseconds(10)));
SessionCount(SessionCount &&); // can't be defaulted in gcc 4.4
SessionCount& operator=(SessionCount&&); // can't be defaulted in gcc 4.4
const std::string& session_id() const
{
return m_sess_id;
}
Duration time_window() const
{
return m_time_window;
}
const std::vector<EventCount>& event_counts() const;
void dump(std::ostream& os) const;
bool empty() const; // no stats
void increment(const std::string& event_id);
private:
void purge() const; // remove out of window stats
std::string m_sess_id;
Duration m_time_window;
Duration m_granularity;
mutable int m_cleanup_countdown;
mutable std::vector<EventCount> m_event_counts;
};
// conveniece. Any real formatted output should go elsewhere.
std::ostream& operator<<(std::ostream& os, const SessionCount& stats);
void dump(std::ostream& os, const std::vector<SessionCount>& sessions);
void dumpTotals(std::ostream& os, const std::vector<SessionCount> &sessions);
} // maxbase

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2018 MariaDB Corporation Ab
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
*
* Change Date: 2020-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#pragma once
#include <chrono>
#include <iosfwd>
#include <string>
namespace maxbase
{
#if __cplusplus >= 201103
typedef std::chrono::steady_clock Clock;
#else
typedef std::chrono::system_clock Clock;
#endif
struct Duration : public Clock::duration // for ADL
{
// gcc 4.4 does not inherit constructors, so this is a bit limited.
Duration() = default;
Duration(long long l) : Clock::duration(l) {}
Duration(Clock::duration d) : Clock::duration(d) {}
};
typedef std::chrono::time_point<Clock, Duration> TimePoint;
class StopWatch
{
public:
// Starts the stopwatch, which is always running.
StopWatch();
// Get elapsed time.
Duration lap() const;
// Get elapsed time, restart StopWatch.
Duration restart();
private:
TimePoint m_start;
};
// Returns the value as a double and string adjusted to a suffix like ms for milliseconds.
std::pair<double, std::string> dur_to_human_readable(Duration dur);
// Human readable output. No standard library for it yet.
std::ostream& operator<<(std::ostream&, Duration dur);
// TimePoint
std::string time_point_to_string(TimePoint tp, const std::string& fmt = "%F %T");
std::ostream& operator<<(std::ostream&, TimePoint tp);
} // maxbase