#include "StdAfx.h" #include "../../../shared/svn_revision.h" #ifdef WIN32 #pragma pack(push,8) #include "PerfCounters.h" #pragma pack(pop) #include #define SYSTEM_OBJECT_INDEX 2 // 'System' object #define PROCESS_OBJECT_INDEX 230 // 'Process' object #define PROCESSOR_OBJECT_INDEX 238 // 'Processor' object #define TOTAL_PROCESSOR_TIME_COUNTER_INDEX 240 // '% Total processor time' counter (valid in WinNT under 'System' object) #define PROCESSOR_TIME_COUNTER_INDEX 6 // '% processor time' counter (for Win2K/XP) #pragma comment(lib, "advapi32") #pragma comment(lib, "Psapi") #endif extern "C" SCRIPT_DECL uint32 _exp_get_version() { return MAKE_SCRIPT_VERSION(SCRIPTLIB_VERSION_MAJOR, SCRIPTLIB_VERSION_MINOR); } #ifdef WIN32 bool m_bFirstTime = true; LONGLONG m_lnOldValue = 0; LARGE_INTEGER m_OldPerfTime100nSec; uint32 number_of_cpus; #endif #ifdef WIN32 /* This is needed because windows is a piece of shit. ;) */ BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } #endif char Filename[MAX_PATH]; class StatDumper { public: void DumpStats(); }; StatDumper dumper; extern "C" SCRIPT_DECL void _exp_script_register(ScriptMgr* mgr) { //strcpy(Filename, Config.MainConfig.GetStringDefault("StatDumper.Filename", "stats.xml").c_str()); //strcpy(Filename, "stats.xml"); if(!Config.MainConfig.GetString("StatDumper", Filename, "Filename", "stat.xml", MAX_PATH)) strcpy(Filename, "stat.xml"); #ifdef WIN32 memset(&m_OldPerfTime100nSec, 0, sizeof(m_OldPerfTime100nSec)); SYSTEM_INFO si; GetSystemInfo(&si); number_of_cpus = si.dwNumberOfProcessors; #endif dumper.DumpStats(); int t = Config.MainConfig.GetIntDefault("StatDumper", "Interval", 120000); TimedEvent * te = TimedEvent::Allocate(&dumper, new CallbackP0(&dumper, &StatDumper::DumpStats), 1, t, 0); sWorld.event_AddEvent(te); } #ifdef WIN32 /*** GRR ***/ int __cdecl HandleCrash(PEXCEPTION_POINTERS pExceptPtrs) { return 0; } #endif void SetThreadName(const char* format, ...) { } void GenerateUptimeString(char * Dest) { uint32 seconds = sWorld.GetUptime(); uint32 mins=0; uint32 hours=0; uint32 days=0; if(seconds >= 60) { mins = seconds / 60; if(mins) { seconds -= mins*60; if(mins >= 60) { hours = mins / 60; if(hours) { mins -= hours*60; if(hours >= 24) { days = hours/24; if(days) hours -= days*24; } } } } } sprintf(Dest, "%d days, %d hours, %d minutes, %d seconds", days, hours, mins, seconds); } #ifdef WIN32 float GetCPUUsageWin32() { CPerfCounters PerfCounters; DWORD dwObjectIndex = PROCESS_OBJECT_INDEX; DWORD dwCpuUsageIndex = PROCESSOR_TIME_COUNTER_INDEX; int CpuUsage = 0; LONGLONG lnNewValue = 0; PPERF_DATA_BLOCK pPerfData = NULL; LARGE_INTEGER NewPerfTime100nSec = {0}; lnNewValue = PerfCounters.GetCounterValueForProcessID(&pPerfData, dwObjectIndex, dwCpuUsageIndex, GetCurrentProcessId()); NewPerfTime100nSec = pPerfData->PerfTime100nSec; if (m_bFirstTime) { m_bFirstTime = false; m_lnOldValue = lnNewValue; m_OldPerfTime100nSec = NewPerfTime100nSec; return 0; } LONGLONG lnValueDelta = lnNewValue - m_lnOldValue; double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)m_OldPerfTime100nSec.QuadPart; m_lnOldValue = lnNewValue; m_OldPerfTime100nSec = NewPerfTime100nSec; double a = (double)lnValueDelta / DeltaPerfTime100nSec; a /= double(number_of_cpus); return (a * 100); } float GetRAMUsageWin32() { PROCESS_MEMORY_COUNTERS pmc; GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); float ram = pmc.PagefileUsage; ram /= 1024.0f; ram /= 1024.0f; return ram; } #endif float GetCPUUsage() { #ifdef WIN32 return GetCPUUsageWin32(); #else return 0.0f; #endif } float GetRAMUsage() { #ifdef WIN32 return GetRAMUsageWin32(); #else return 0.0f; #endif } void FillOnlineTime(uint32 Time, char * Dest) { uint32 seconds = Time; uint32 mins=0; uint32 hours=0; uint32 days=0; if(seconds >= 60) { mins = seconds / 60; if(mins) { seconds -= mins*60; if(mins >= 60) { hours = mins / 60; if(hours) { mins -= hours*60; if(hours >= 24) { days = hours/24; if(days) hours -= days*24; } } } } } sprintf(Dest, "%d hours, %d minutes, %d seconds", hours, mins, seconds); } void StatDumper::DumpStats() { if (!Filename) return; FILE * f = fopen(Filename, "w"); if (!f) return; // Dump Header fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, " \n"); std::deque gms; { // Dump server information. #ifdef WIN32 fprintf(f, " Antrix/Win32 v2.1.2-%u\n", g_getRevision()); #else fprintf(f, " Antrix/Linux v2.1.2-%u\n", g_getRevision()); #endif char uptime[80]; GenerateUptimeString(uptime); float AvgLat; uint32 GMCount; int gm = 0; int count = 0; int avg = 0; // lock players reader objmgr._playerslock.AcquireReadLock(); HM_NAMESPACE::hash_map::const_iterator itr; for (itr = objmgr._players.begin(); itr != objmgr._players.end(); itr++) { if(itr->second->GetSession() && itr->second->IsInWorld()) { count++; avg += itr->second->GetSession()->GetLatency(); if(itr->second->GetSession()->GetPermissionCount()) { gm++; gms.push_back(itr->second); } } } objmgr._playerslock.ReleaseReadLock(); AvgLat = count ? (float)((float)avg / (float)count) : 0; GMCount = gm; fprintf(f, " d0rk\n", sWorld.AlliancePlayers + sWorld.HordePlayers); fprintf(f, " dUMBURK\n", GetCPUUsage()); fprintf(f, " %s\n", uptime); } fprintf(f, " \n"); Player * player; uint32 t = time(NULL); char otime[100]; { // need a big buffer.. static char buf[500000]; memset(buf, 0, 500000); // Dump Player Information fprintf(f, " \n"); objmgr._playerslock.AcquireReadLock(); HM_NAMESPACE::hash_map::const_iterator itr; for (itr = objmgr._players.begin(); itr != objmgr._players.end(); itr++) { player = itr->second; if(itr->second->GetSession() && itr->second->IsInWorld()) { FillOnlineTime(t - player->OnlineTime, otime); fprintf(f, " \n"); fprintf(f, " %s\n", player->GetName()); fprintf(f, " %u\n", player->getRace()); fprintf(f, " %u\n", player->getClass()); fprintf(f, " %u\n", player->GetUInt32Value(UNIT_FIELD_LEVEL)); fprintf(f, " %u\n", player->GetMapId()); fprintf(f, " %u\n", player->GetAreaID()); fprintf(f, " %s\n", otime); fprintf(f, " %u\n", player->GetSession()->GetLatency()); fprintf(f, " \n"); if(player->GetSession()->GetPermissionCount() > 0) gms.push_back(player); } } objmgr._playerslock.ReleaseReadLock(); fprintf(f, " \n"); } fprintf(f, "\n"); fclose(f); }