#include #include #include #include "ConnectionHistory.hpp" #include "../../server/tracy_pdqsort.h" #include "../../server/TracyStorage.hpp" ConnectionHistory::ConnectionHistory() : m_fn( tracy::GetSavePath( "connection.history" ) ) { FILE* f = fopen( m_fn.c_str(), "rb" ); if( !f ) return; uint64_t sz; if( fread( &sz, 1, sizeof( sz ), f ) != sizeof( sz ) ) goto err; for( uint64_t i=0; i= 1024 ) goto err; char tmp[1024]; if( fread( tmp, 1, ssz, f ) != ssz ) goto err; if( fread( &cnt, 1, sizeof( cnt ), f ) != sizeof( cnt ) ) goto err; m_connHistMap.emplace( std::string( tmp, tmp+ssz ), cnt ); } fclose( f ); Rebuild(); return; err: fclose( f ); m_connHistMap.clear(); } ConnectionHistory::~ConnectionHistory() { FILE* f = fopen( m_fn.c_str(), "wb" ); if( !f ) return; uint64_t sz = uint64_t( m_connHistMap.size() ); fwrite( &sz, 1, sizeof( uint64_t ), f ); for( auto& v : m_connHistMap ) { sz = uint64_t( v.first.size() ); fwrite( &sz, 1, sizeof( uint64_t ), f ); fwrite( v.first.c_str(), 1, sz, f ); fwrite( &v.second, 1, sizeof( v.second ), f ); } fclose( f ); } void ConnectionHistory::Rebuild() { std::vector::const_iterator> vec; vec.reserve( m_connHistMap.size() ); for( auto it = m_connHistMap.begin(); it != m_connHistMap.end(); ++it ) { vec.emplace_back( it ); } tracy::pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second > rhs->second; } ); std::swap( m_connHistVec, vec ); } void ConnectionHistory::Count( const char* name ) { std::string addr( name ); auto it = m_connHistMap.find( addr ); if( it != m_connHistMap.end() ) { it->second++; } else { m_connHistMap.emplace( std::move( addr ), 1 ); } Rebuild(); } void ConnectionHistory::Erase( size_t idx ) { assert( idx < m_connHistVec.size() ); m_connHistMap.erase( m_connHistVec[idx] ); Rebuild(); }