Teaspeak-Server/server/src/ConnectionStatistics.h

106 lines
3.9 KiB
C
Raw Normal View History

#pragma once
#include <Properties.h>
#include <protocol/Packet.h>
#include <chrono>
#include "Definitions.h"
namespace ts {
namespace server {
class TSServer;
}
namespace stats {
struct StatisticEntry {
std::atomic<int8_t> use_count{0};
std::chrono::time_point<std::chrono::system_clock> timestamp;
uint16_t size = 0;
};
struct DataSummery {
uint32_t send_minute;
uint32_t send_second;
uint32_t recv_minute;
uint32_t recv_second;
uint32_t file_recv;
uint32_t file_send;
};
class ConnectionStatistics {
public:
explicit ConnectionStatistics(const std::shared_ptr<ConnectionStatistics>& /* root */, bool /* spawn properties */);
~ConnectionStatistics();
std::shared_ptr<Properties> statistics();
void logIncomingPacket(const protocol::ClientPacket&);
void logOutgoingPacket(const protocol::ServerPacket&);
void logFileTransfareIn(uint64_t);
void logFileTransfareOut(uint64_t);
void tick();
DataSummery dataReport();
std::pair<uint64_t, uint64_t> mark_file_bytes();
inline bool measure_bandwidths() { return this->_measure_bandwidths; }
void measure_bandwidths(bool flag) { this->_measure_bandwidths = flag; }
inline bool has_properties() { return !!this->properties; }
private:
class spin_lock {
std::atomic_flag locked = ATOMIC_FLAG_INIT;
public:
void lock() {
uint8_t round = 0;
while (locked.test_and_set(std::memory_order_acquire)) {
//Yield when we're using this lock for a longer time, which we usually not doing
if(round++ % 8 == 0)
std::this_thread::yield();
}
}
inline bool try_lock() {
return !locked.test_and_set(std::memory_order_acquire);
}
void unlock() {
locked.clear(std::memory_order_release);
}
};
typedef spin_lock fast_lock_t;
bool _measure_bandwidths = true;
std::shared_ptr<ConnectionStatistics> handle;
std::shared_ptr<Properties> properties;
std::atomic<uint64_t> connection_packets_sent[4]{0, 0, 0, 0};
std::atomic<uint64_t> connection_bytes_sent[4]{0, 0, 0, 0};
std::atomic<uint64_t> connection_packets_received[4]{0, 0, 0, 0};
std::atomic<uint64_t> connection_bytes_received[4]{0, 0, 0, 0};
std::atomic<uint64_t> file_bytes_sent = 0;
std::atomic<uint64_t> file_bytes_received = 0;
std::atomic<uint64_t> mark_file_bytes_sent = 0;
std::atomic<uint64_t> mark_file_bytes_received = 0;
fast_lock_t history_lock_outgoing;
fast_lock_t history_lock_incoming;
std::deque<StatisticEntry*> history_file_incoming{};
std::deque<StatisticEntry*> history_file_outgoing{};
std::deque<StatisticEntry*> history_incoming{};
std::deque<StatisticEntry*> history_outgoing{};
void _log_incoming_packet(StatisticEntry */* statistics */, int8_t /* type index */);
void _log_outgoing_packet(StatisticEntry* /* statistics */, int8_t /* type index */);
void _log_incoming_file_packet(StatisticEntry */* statistics */);
void _log_outgoing_file_packet(StatisticEntry* /* statistics */);
};
}
}