106 lines
3.9 KiB
C
106 lines
3.9 KiB
C
|
#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 */);
|
||
|
};
|
||
|
}
|
||
|
}
|