%PDF- %PDF-
| Direktori : /backups/router/usr/local/include/syslog-ng/stats/ |
| Current File : //backups/router/usr/local/include/syslog-ng/stats/stats-compat.h |
/*
* Copyright (c) 2023 László Várady
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As an additional exemption you are allowed to compile & link against the
* OpenSSL libraries as published by the OpenSSL project. See the file
* COPYING for details.
*
*/
#ifndef STATS_COMPAT_H
#define STATS_COMPAT_H
#include "syslog-ng.h"
#include "stats-counter.h"
#include "stats-cluster.h"
#include "stats-cluster-single.h"
#include "stats-registry.h"
#include "atomic-gssize.h"
#include <stdint.h>
/*
* StatsByteCounter allows representing "big" accumulating byte-based metrics
* even on 32-bit architectures, where a simple stats-counter would overflow
* after 4 GiB.
*
* When 64-bit counters are available, they will be used.
* If not, the counters lose precision but are able to represent larger values.
*
* The current implementation is not thread-safe, reimplement it using a CAS
* loop when needed.
*/
typedef enum _StatsByteCounterPrecision
{
SBCP_KIB,
SBCP_MIB,
SBCP_GIB,
} StatsByteCounterPrecision;
typedef struct _StatsByteCounter
{
StatsCounterItem *counter;
#if STATS_COUNTER_MAX_VALUE < UINT64_MAX
atomic_gssize counter_cache;
gsize precision;
#endif
} StatsByteCounter;
static inline void
stats_byte_counter_init(StatsByteCounter *self, StatsClusterKey *key, gint stats_level,
StatsByteCounterPrecision min_precision)
{
*self = (StatsByteCounter)
{
0
};
#if STATS_COUNTER_MAX_VALUE < UINT64_MAX
StatsClusterUnit unit = SCU_BYTES;
switch (min_precision)
{
case SBCP_KIB:
self->precision = 1024;
unit = SCU_KIB;
break;
case SBCP_MIB:
self->precision = 1024 * 1024;
unit = SCU_MIB;
break;
case SBCP_GIB:
self->precision = 1024 * 1024 * 1024;
unit = SCU_GIB;
break;
default:
g_assert_not_reached();
}
stats_cluster_single_key_add_unit(key, unit);
#endif
stats_lock();
stats_register_counter(stats_level, key, SC_TYPE_SINGLE_VALUE, &self->counter);
stats_unlock();
}
static inline void
stats_byte_counter_deinit(StatsByteCounter *self, StatsClusterKey *key)
{
stats_lock();
stats_unregister_counter(key, SC_TYPE_SINGLE_VALUE, &self->counter);
stats_unlock();
}
/* this is currently NOT thread-safe */
static inline void
stats_byte_counter_add(StatsByteCounter *self, gsize add)
{
#if STATS_COUNTER_MAX_VALUE < UINT64_MAX
if (!self->counter)
return;
self->counter_cache.value += add;
if (self->counter_cache.value > self->precision)
{
stats_counter_add(self->counter, self->counter_cache.value / self->precision);
self->counter_cache.value %= self->precision;
}
#else
stats_counter_add(self->counter, add);
#endif
}
#endif