Added profiler to loginserver as initial work cause it's the smallest service or one of the smallest

This commit is contained in:
KimLS 2015-01-31 14:52:27 -08:00
parent 0bdbc5f5c9
commit e135f46711
28 changed files with 629 additions and 130 deletions

View File

@ -31,6 +31,7 @@
#EQEMU_SANITIZE_LUA_LIBS
#EQEMU_BUILD_CLIENT_FILES
#EQEMU_MAP_DIR
#EQEMU_ENABLE_PROFILING
#We set a fairly new version (as of 2013) because I found finding perl was a bit... buggy on older ones
#Can change this if you really want but you should upgrade!
@ -257,6 +258,7 @@ OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON)
OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON)
OPTION(EQEMU_ENABLE_PROFILING "Enable CPU profiler. Note: will slow down execution time." OFF)
#C++11 stuff
IF(NOT MSVC)
@ -331,6 +333,15 @@ IF(EQEMU_BUILD_LUA)
ADD_SUBDIRECTORY(luabind)
ENDIF(EQEMU_BUILD_LUA)
IF(EQEMU_ENABLE_PROFILING)
ADD_DEFINITIONS(-DEQPERF_ENABLED)
INCLUDE_DIRECTORIES("eqperf")
ADD_SUBDIRECTORY(eqperf)
SET(PERF_LIBS eqperf)
ELSE(EQEMU_ENABLE_PROFILING)
SET(PERF_LIBS "")
ENDIF(EQEMU_ENABLE_PROFILING)
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
ADD_SUBDIRECTORY(common)
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)

View File

@ -158,7 +158,6 @@ SET(common_headers
packet_functions.h
platform.h
proc_launcher.h
profiler.h
ptimer.h
queue.h
races.h

View File

@ -1,92 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PROFILER_H
#define PROFILER_H
#ifdef EQPROFILE
#include "../common/rdtsc.h"
#include "../common/types.h"
class ScopedProfiler;
class GeneralProfiler {
friend class ScopedProfiler;
public:
inline GeneralProfiler(unsigned int _count) {
count = _count;
timers = new RDTSC_Collector[count];
}
inline virtual ~GeneralProfiler() {
safe_delete_array(timers);
}
inline double getTotalDuration(unsigned int id) {
return(id<count? timers[id].getTotalDuration() : 0);
}
inline double getAverage(unsigned int id) {
return(id<count? timers[id].getAverage() : 0);
}
inline unsigned long long getTicks(unsigned int id) {
return(id<count? timers[id].getTicks() : 0);
}
inline unsigned long long getTotalTicks(unsigned int id) {
return(id<count? timers[id].getTotalTicks() : 0);
}
inline unsigned long long getCount(unsigned int id) {
return(id<count? timers[id].getCount() : 0);
}
inline void reset() {
unsigned int r;
RDTSC_Collector *cur = timers;
for(r = 0; r < count; r++, cur++)
cur->reset();
}
RDTSC_Collector *timers;
unsigned int count;
};
class ScopedProfiler {
public:
inline ScopedProfiler(RDTSC_Collector *c) {
_it = c;
c->start();
}
inline ~ScopedProfiler() {
_it->stop();
}
protected:
RDTSC_Collector *_it;
};
#define _GP(obj, pkg, name) ScopedProfiler __eqemu_profiler(&obj.timers[pkg::name])
#else // else !EQPROFILE
//no profiling, dummy functions
#define _GP(obj, pkg, name) ;
#endif
#endif

View File

@ -18,6 +18,7 @@
#ifndef TYPES_H
#define TYPES_H
#include <eqp_profiler.h>
#include <stdint.h>
typedef uint8_t byte;
typedef uint8_t uint8;

22
eqperf/CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(eqperf_sources
eqp_profile_event.cpp
eqp_profile_timer.cpp
eqp_profiler.cpp
eqp_profiler_node.cpp
)
SET(eqperf_headers
eqp_profile_event.h
eqp_profile_function.h
eqp_profile_timer.h
eqp_profiler.h
eqp_profiler_node.h
)
ADD_LIBRARY(eqperf SHARED ${eqperf_sources} ${eqperf_headers})
INSTALL(TARGETS eqperf RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

View File

@ -0,0 +1,47 @@
#include "eqp_profile_event.h"
#include "eqp_profile_timer.h"
#include "eqp_profiler.h"
EQP::CPU::ST::Event::Event(const char *function_name) {
function_name_ = function_name;
name_ = nullptr;
start_ = GetCurrentTimer();
EQP::CPU::ST::GetProfiler().EventStarted(function_name_, name_);
}
EQP::CPU::ST::Event::Event(const char *function_name, const char *name) {
function_name_ = function_name;
name_ = name;
start_ = GetCurrentTimer();
EQP::CPU::ST::GetProfiler().EventStarted(function_name_, name_);
}
EQP::CPU::ST::Event::~Event() {
uint64_t end = GetCurrentTimer();
EQP::CPU::ST::GetProfiler().EventFinished(end - start_);
}
EQP::CPU::MT::Event::Event(const char *function_name) {
function_name_ = function_name;
name_ = nullptr;
start_ = GetCurrentTimer();
EQP::CPU::MT::GetProfiler().EventStarted(function_name_, name_);
}
EQP::CPU::MT::Event::Event(const char *function_name, const char *name) {
function_name_ = function_name;
name_ = name;
start_ = GetCurrentTimer();
EQP::CPU::MT::GetProfiler().EventStarted(function_name_, name_);
}
EQP::CPU::MT::Event::~Event() {
uint64_t end = GetCurrentTimer();
EQP::CPU::MT::GetProfiler().EventFinished(end - start_);
}

View File

@ -0,0 +1,41 @@
#pragma once
#include <stdint.h>
#include "eqp_profile_function.h"
namespace EQP
{
namespace CPU
{
namespace ST
{
class EQP_EXPORT Event
{
public:
Event(const char *function_name);
Event(const char *function_name, const char *name);
~Event();
private:
const char *function_name_;
const char *name_;
uint64_t start_;
};
}
namespace MT
{
class EQP_EXPORT Event
{
public:
Event(const char *function_name);
Event(const char *function_name, const char *name);
~Event();
private:
const char *function_name_;
const char *name_;
uint64_t start_;
};
}
}
} // Profile

View File

@ -0,0 +1,15 @@
#pragma once
#ifndef __PRETTY_FUNCTION__
#ifdef _MSC_VER
#define __PRETTY_FUNCTION__ __FUNCSIG__
#else
#define __PRETTY_FUNCTION__ __FUNCTION__
#endif
#endif
#ifdef _MSC_VER
#define EQP_EXPORT __declspec(dllexport)
#else
#define EQP_EXPORT
#endif

View File

@ -0,0 +1,24 @@
#include "eqp_profile_timer.h"
#ifdef _MSC_VER
#include <Windows.h>
#else
#include <time.h>
#endif
uint64_t EQP::GetCurrentTimer()
{
#ifdef _MSC_VER
LARGE_INTEGER qpt_i;
QueryPerformanceCounter(&qpt_i);
return qpt_i.QuadPart;
#else
timespec tp;
if(clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
uint64_t res = tp.tv_sec * 1000000000;
res += tp.tv_nsec;
return res;
}
return 0;
#endif
}

View File

@ -0,0 +1,9 @@
#pragma once
#include <stdint.h>
namespace EQP
{
uint64_t GetCurrentTimer();
} // EQP

194
eqperf/eqp_profiler.cpp Normal file
View File

@ -0,0 +1,194 @@
#include "eqp_profiler.h"
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <algorithm>
EQP::CPU::ST::Profiler st_profiler;
EQP::CPU::MT::Profiler mt_profiler;
struct EQP::CPU::MT::Profiler::impl
{
std::mutex lock_;
std::unordered_map<std::thread::id, ThreadInfo*> nodes_;
};
EQP::CPU::ST::Profiler &EQP::CPU::ST::GetProfiler() {
return st_profiler;
}
EQP::CPU::MT::Profiler &EQP::CPU::MT::GetProfiler() {
return mt_profiler;
}
EQP::CPU::ST::Profiler::Profiler() {
root_ = new ProfilerNode;
root_->SetParent(root_);
current_ = root_;
}
EQP::CPU::ST::Profiler::~Profiler() {
delete root_;
}
void EQP::CPU::ST::Profiler::EventStarted(const char *func, const char *name) {
std::string cur_name = func;
if(name) {
cur_name += " - ";
cur_name += name;
}
auto search = current_->GetNodes().find(cur_name);
if(search != current_->GetNodes().end()) {
current_ = search->second;
} else {
ProfilerNode *t = new ProfilerNode;
t->SetParent(current_);
current_->GetNodes()[cur_name] = t;
current_ = t;
}
}
void EQP::CPU::ST::Profiler::EventFinished(uint64_t time) {
current_->GetTime() += time;
current_->GetCount()++;
current_ = current_->GetParent();
}
void EQP::CPU::ST::Profiler::Clear() {
for(auto &iter : root_->GetNodes()) {
delete iter.second;
}
root_->GetNodes().clear();
root_->SetTime(0);
root_->SetCount(0);
current_ = root_;
}
void EQP::CPU::ST::Profiler::Dump(std::ostream &stream) {
uint64_t total = 0;
std::vector<ProfilerNodeDump> sorted_vec;
sorted_vec.reserve(root_->GetNodes().size() + 1);
for(auto &iter : root_->GetNodes()) {
ProfilerNodeDump n;
n.name = iter.first;
n.node = iter.second;
sorted_vec.push_back(n);
total += iter.second->GetTime();
}
std::sort(sorted_vec.begin(), sorted_vec.end(),
[](const ProfilerNodeDump& a, const ProfilerNodeDump& b) { return a.node->GetTime() > b.node->GetTime(); });
for(auto &iter : sorted_vec) {
iter.node->Dump(stream, iter.name, total, 0);
}
}
EQP::CPU::MT::Profiler::ThreadInfo::ThreadInfo() {
root_ = new ProfilerNode;
root_->SetParent(root_);
current_ = root_;
}
EQP::CPU::MT::Profiler::ThreadInfo::~ThreadInfo() {
delete root_;
}
EQP::CPU::MT::Profiler::Profiler() {
imp_ = new impl;
}
EQP::CPU::MT::Profiler::~Profiler() {
delete imp_;
}
void EQP::CPU::MT::Profiler::EventStarted(const char *func, const char *name) {
std::string cur_name = func;
if(name) {
cur_name += " - ";
cur_name += name;
}
ThreadInfo *ti = nullptr;
imp_->lock_.lock();
auto ti_search = imp_->nodes_.find(std::this_thread::get_id());
if(ti_search == imp_->nodes_.end()) {
ti = new ThreadInfo;
imp_->nodes_[std::this_thread::get_id()] = ti;
} else {
ti = ti_search->second;
}
imp_->lock_.unlock();
auto search = ti->current_->GetNodes().find(cur_name);
if(search != ti->current_->GetNodes().end()) {
ti->current_ = search->second;
}
else {
ProfilerNode *t = new ProfilerNode;
t->SetParent(ti->current_);
ti->current_->GetNodes()[cur_name] = t;
ti->current_ = t;
}
}
void EQP::CPU::MT::Profiler::EventFinished(uint64_t time) {
ThreadInfo *ti = nullptr;
imp_->lock_.lock();
auto ti_search = imp_->nodes_.find(std::this_thread::get_id());
if(ti_search == imp_->nodes_.end()) {
imp_->lock_.unlock();
return;
}
else {
ti = ti_search->second;
}
imp_->lock_.unlock();
ti->current_->GetTime() += time;
ti->current_->GetCount()++;
ti->current_ = ti->current_->GetParent();
}
void EQP::CPU::MT::Profiler::Clear() {
imp_->lock_.lock();
for(auto &iter : imp_->nodes_) {
delete iter.second;
}
imp_->nodes_.clear();
imp_->lock_.unlock();
}
void EQP::CPU::MT::Profiler::Dump(std::ostream &stream) {
imp_->lock_.lock();
for(auto &iter : imp_->nodes_) {
stream << "Thread: " << iter.first << std::endl;
uint64_t total = 0;
std::vector<ProfilerNodeDump> sorted_vec;
sorted_vec.reserve(iter.second->root_->GetNodes().size() + 1);
for(auto &t_iter : iter.second->root_->GetNodes()) {
ProfilerNodeDump n;
n.name = t_iter.first;
n.node = t_iter.second;
sorted_vec.push_back(n);
total += t_iter.second->GetTime();
}
std::sort(sorted_vec.begin(), sorted_vec.end(),
[](const ProfilerNodeDump& a, const ProfilerNodeDump& b) { return a.node->GetTime() > b.node->GetTime(); });
for(auto &t_iter : sorted_vec) {
t_iter.node->Dump(stream, t_iter.name, total, 1);
}
stream << std::endl;
}
imp_->lock_.unlock();
}

78
eqperf/eqp_profiler.h Normal file
View File

@ -0,0 +1,78 @@
#pragma once
#ifdef EQPERF_ENABLED
#include <string>
#include "eqp_profile_event.h"
#include "eqp_profiler_node.h"
#define eqp_comb_fin(x, y) x##y
#define eqp_comb(x, y) eqp_comb_fin(x, y)
#define _eqp EQP::CPU::ST::Event eqp_comb(eq_perf_event_, __LINE__) (__PRETTY_FUNCTION__);
#define _eqpn(x) EQP::CPU::ST::Event eqp_comb(eq_perf_event_, __LINE__) (__PRETTY_FUNCTION__, x);
#define _eqp_mt EQP::CPU::MT::Event eqp_comb(eq_perf_event_, __LINE__) (__PRETTY_FUNCTION__);
#define _eqpn_mt(x) EQP::CPU::MT::Event eqp_comb(eq_perf_event_, __LINE__) (__PRETTY_FUNCTION__, x);
namespace EQP
{
namespace CPU
{
namespace ST
{
class EQP_EXPORT Profiler
{
typedef EQP::CPU::ProfilerNode Node;
public:
Profiler();
~Profiler();
void EventStarted(const char *func, const char *name);
void EventFinished(uint64_t time);
void Clear();
void Dump(std::ostream &stream);
private:
Node *root_;
Node *current_;
};
EQP_EXPORT Profiler &GetProfiler();
}
namespace MT
{
class EQP_EXPORT Profiler
{
typedef EQP::CPU::ProfilerNode Node;
class ThreadInfo {
public:
ThreadInfo();
~ThreadInfo();
Node *root_;
Node *current_;
};
public:
Profiler();
~Profiler();
void EventStarted(const char *func, const char *name);
void EventFinished(uint64_t time);
void Clear();
void Dump(std::ostream &stream);
private:
struct impl;
impl *imp_;
};
EQP_EXPORT Profiler &GetProfiler();
}
} // CPU
} // EQP
#else
#define _eqp
#define _eqpn(x)
#define _eqp_mt
#define _eqpn_mt(x)
#endif

View File

@ -0,0 +1,54 @@
#include "eqp_profiler_node.h"
#include <iostream>
#include <iomanip>
#include <algorithm>
EQP::CPU::ProfilerNode::ProfilerNode() {
count_ = 0;
time_ = 0;
parent_ = nullptr;;
}
EQP::CPU::ProfilerNode::~ProfilerNode() {
for(auto &iter : nodes_) {
delete iter.second;
}
}
void EQP::CPU::ProfilerNode::Dump(std::ostream &stream, const std::string &func, uint64_t total_time, int node_level) {
if(node_level >= 1) {
stream << std::setw(node_level * 2) << " ";
}
double m_cycles = time_ / 1000000.0;
double m_avg_cycles = m_cycles / count_;
double percentage = time_ * 100 / static_cast<double>(total_time);
std::streamsize p = stream.precision();
stream << std::fixed;
stream.precision(2);
stream << m_cycles << "M cycles, " << count_ << " calls, " << m_avg_cycles << "M cycles avg, ";
stream << func.c_str() << " ";
stream << percentage << "%";
stream << std::endl;
stream.precision(p);
std::vector<ProfilerNodeDump> sorted_vec;
sorted_vec.reserve(nodes_.size() + 1);
for(auto &iter : nodes_) {
ProfilerNodeDump n;
n.name = iter.first;
n.node = iter.second;
sorted_vec.push_back(n);
}
std::sort(sorted_vec.begin(), sorted_vec.end(),
[](const ProfilerNodeDump& a, const ProfilerNodeDump& b) { return a.node->GetTime() > b.node->GetTime(); });
for(auto &iter : sorted_vec) {
iter.node->Dump(stream, iter.name, total_time, node_level + 1);
}
}

View File

@ -0,0 +1,43 @@
#pragma once
#include <unordered_map>
#include <string>
#include <stdint.h>
namespace EQP
{
namespace CPU
{
class ProfilerNode
{
public:
ProfilerNode();
~ProfilerNode();
inline void SetCount(uint64_t c) { count_ = c; }
inline uint64_t& GetCount() { return count_; }
inline void SetTime(uint64_t t) { time_ = t; }
inline uint64_t& GetTime() { return time_; }
inline void SetParent(ProfilerNode *p) { parent_ = p; }
inline ProfilerNode* GetParent() { return parent_; }
inline std::unordered_map<std::string, ProfilerNode*>& GetNodes() { return nodes_; }
void Dump(std::ostream &stream, const std::string &func, uint64_t total_time, int node_level);
private:
uint64_t count_;
uint64_t time_;
ProfilerNode *parent_;
std::unordered_map<std::string, ProfilerNode*> nodes_;
};
struct ProfilerNodeDump
{
std::string name;
ProfilerNode *node;
};
} // CPU
} // EQP

View File

@ -43,7 +43,7 @@ ADD_EXECUTABLE(loginserver ${eqlogin_sources} ${eqlogin_headers})
INSTALL(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
TARGET_LINK_LIBRARIES(loginserver common ${PERF_LIBS} debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
IF(MSVC)
SET_TARGET_PROPERTIES(loginserver PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")

View File

@ -26,6 +26,7 @@ extern LoginServer server;
Client::Client(std::shared_ptr<EQStream> c, LSClientVersion v)
{
_eqp
connection = c;
version = v;
status = cs_not_sent_session_ready;
@ -36,6 +37,7 @@ Client::Client(std::shared_ptr<EQStream> c, LSClientVersion v)
bool Client::Process()
{
_eqp
EQApplicationPacket *app = connection->PopPacket();
while(app)
{
@ -114,6 +116,7 @@ bool Client::Process()
void Client::Handle_SessionReady(const char* data, unsigned int size)
{
_eqp
if(status != cs_not_sent_session_ready)
{
server_log->Log(log_network_error, "Session ready received again after already being received.");
@ -175,6 +178,7 @@ void Client::Handle_SessionReady(const char* data, unsigned int size)
void Client::Handle_Login(const char* data, unsigned int size)
{
_eqp
if(status != cs_waiting_for_login)
{
server_log->Log(log_network_error, "Login received after already having logged in.");
@ -329,6 +333,7 @@ void Client::Handle_Login(const char* data, unsigned int size)
void Client::Handle_Play(const char* data)
{
_eqp
if(status != cs_logged_in)
{
server_log->Log(log_client_error, "Client sent a play request when they either were not logged in, discarding.");
@ -352,6 +357,7 @@ void Client::Handle_Play(const char* data)
void Client::SendServerListPacket()
{
_eqp
EQApplicationPacket *outapp = server.SM->CreateServerListPacket(this);
if(server.options.IsDumpOutPacketsOn())
@ -365,6 +371,7 @@ void Client::SendServerListPacket()
void Client::SendPlayResponse(EQApplicationPacket *outapp)
{
_eqp
if(server.options.IsTraceOn())
{
server_log->Log(log_network_trace, "Sending play response for %s.", GetAccountName().c_str());
@ -376,6 +383,7 @@ void Client::SendPlayResponse(EQApplicationPacket *outapp)
void Client::GenerateKey()
{
_eqp
key.clear();
int count = 0;
while(count < 10)

View File

@ -25,6 +25,7 @@ extern bool run_server;
ClientManager::ClientManager()
{
_eqp
int titanium_port = atoi(server.config->GetVariable("Titanium", "port").c_str());
titanium_stream = new EQStreamFactory(LoginStream, titanium_port);
titanium_ops = new RegularOpcodeManager;
@ -68,6 +69,7 @@ ClientManager::ClientManager()
ClientManager::~ClientManager()
{
_eqp
if(titanium_stream)
{
titanium_stream->Close();
@ -93,6 +95,7 @@ ClientManager::~ClientManager()
void ClientManager::Process()
{
_eqp
ProcessDisconnect();
std::shared_ptr<EQStream> cur = titanium_stream->Pop();
while(cur)
@ -138,6 +141,7 @@ void ClientManager::Process()
void ClientManager::ProcessDisconnect()
{
_eqp
list<Client*>::iterator iter = clients.begin();
while(iter != clients.end())
{
@ -157,6 +161,7 @@ void ClientManager::ProcessDisconnect()
void ClientManager::UpdateServerList()
{
_eqp
list<Client*>::iterator iter = clients.begin();
while(iter != clients.end())
{
@ -167,6 +172,7 @@ void ClientManager::UpdateServerList()
void ClientManager::RemoveExistingClient(unsigned int account_id)
{
_eqp
list<Client*>::iterator iter = clients.begin();
while(iter != clients.end())
{
@ -185,6 +191,7 @@ void ClientManager::RemoveExistingClient(unsigned int account_id)
Client *ClientManager::GetClient(unsigned int account_id)
{
_eqp
Client *cur = nullptr;
int count = 0;
list<Client*>::iterator iter = clients.begin();

View File

@ -27,6 +27,7 @@ extern ErrorLog *server_log;
*/
std::string Config::GetVariable(std::string title, std::string parameter)
{
_eqp
std::map<std::string, std::map<std::string, std::string> >::iterator iter = vars.find(title);
if(iter != vars.end())
{
@ -46,6 +47,7 @@ std::string Config::GetVariable(std::string title, std::string parameter)
*/
void Config::Parse(const char *file_name)
{
_eqp
if(file_name == nullptr)
{
server_log->Log(log_error, "Config::Parse(), file_name passed was null.");
@ -144,6 +146,7 @@ void Config::Parse(const char *file_name)
*/
void Config::Tokenize(FILE *input, std::list<std::string> &tokens)
{
_eqp
char c = fgetc(input);
std::string lexeme;

View File

@ -30,6 +30,7 @@ extern LoginServer server;
DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, string name)
{
_eqp
this->user = user;
this->pass = pass;
this->host = host;
@ -55,6 +56,7 @@ DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port,
DatabaseMySQL::~DatabaseMySQL()
{
_eqp
if(db)
{
mysql_close(db);
@ -63,6 +65,7 @@ DatabaseMySQL::~DatabaseMySQL()
bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id)
{
_eqp
if(!db)
{
return false;
@ -101,6 +104,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id,
unsigned int &trusted, string &list_desc, string &account, string &password)
{
_eqp
if(!db)
{
return false;
@ -176,6 +180,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
{
_eqp
if(!db)
{
return;
@ -195,6 +200,7 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string password, string email)
{
_eqp
if(!db)
{
return;
@ -214,6 +220,7 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas
void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, string ip_address)
{
_eqp
if(!db)
{
return;
@ -239,6 +246,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s
bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, unsigned int &id)
{
_eqp
if(!db)
{
return false;

View File

@ -30,6 +30,7 @@ extern LoginServer server;
DatabasePostgreSQL::DatabasePostgreSQL(string user, string pass, string host, string port, string name)
{
_eqp
db = nullptr;
db = PQsetdbLogin(host.c_str(), port.c_str(), nullptr, nullptr, name.c_str(), user.c_str(), pass.c_str());
if(!db)
@ -47,6 +48,7 @@ DatabasePostgreSQL::DatabasePostgreSQL(string user, string pass, string host, st
DatabasePostgreSQL::~DatabasePostgreSQL()
{
_eqp
if(db)
{
PQfinish(db);
@ -55,6 +57,7 @@ DatabasePostgreSQL::~DatabasePostgreSQL()
bool DatabasePostgreSQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id)
{
_eqp
if(!db)
{
return false;
@ -103,6 +106,7 @@ bool DatabasePostgreSQL::GetLoginDataFromAccountName(string name, string &passwo
bool DatabasePostgreSQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id,
unsigned int &trusted, string &list_desc, string &account, string &password)
{
_eqp
if(!db)
{
return false;
@ -160,6 +164,7 @@ bool DatabasePostgreSQL::GetWorldRegistration(string long_name, string short_nam
void DatabasePostgreSQL::UpdateLSAccountData(unsigned int id, string ip_address)
{
_eqp
if(!db)
{
return;
@ -195,6 +200,7 @@ void DatabasePostgreSQL::UpdateLSAccountData(unsigned int id, string ip_address)
void DatabasePostgreSQL::UpdateWorldRegistration(unsigned int id, string long_name, string ip_address)
{
_eqp
if(!db)
{
return;

View File

@ -24,6 +24,7 @@ extern ErrorLog *server_log;
bool Encryption::LoadCrypto(std::string name)
{
_eqp
if(!Load(name.c_str()))
{
server_log->Log(log_error, "Failed to load %s from the operating system.", name.c_str());
@ -58,6 +59,7 @@ bool Encryption::LoadCrypto(std::string name)
char *Encryption::DecryptUsernamePassword(const char* encrypted_buffer, unsigned int buffer_size, int mode)
{
_eqp
if(decrypt_func)
{
return decrypt_func(encrypted_buffer, buffer_size, mode);
@ -67,6 +69,7 @@ char *Encryption::DecryptUsernamePassword(const char* encrypted_buffer, unsigned
char *Encryption::Encrypt(const char* buffer, unsigned int buffer_size, unsigned int &out_size)
{
_eqp
if(encrypt_func)
{
return encrypt_func(buffer, buffer_size, out_size);
@ -76,6 +79,7 @@ char *Encryption::Encrypt(const char* buffer, unsigned int buffer_size, unsigned
void Encryption::DeleteHeap(char *buffer)
{
_eqp
if(delete_func)
{
delete_func(buffer);
@ -84,6 +88,7 @@ void Encryption::DeleteHeap(char *buffer)
bool Encryption::Load(const char *name)
{
_eqp
SetLastError(0);
#ifdef UNICODE
int name_length = strlen(name);
@ -111,6 +116,7 @@ bool Encryption::Load(const char *name)
void Encryption::Unload()
{
_eqp
if(h_dll)
{
FreeLibrary(h_dll);
@ -120,6 +126,7 @@ void Encryption::Unload()
bool Encryption::GetSym(const char *name, void **sym)
{
_eqp
if(Loaded())
{
*sym = GetProcAddress(h_dll, name);
@ -133,6 +140,7 @@ bool Encryption::GetSym(const char *name, void **sym)
void *Encryption::GetSym(const char *name)
{
_eqp
if(Loaded())
{
return GetProcAddress(h_dll, name);

View File

@ -34,12 +34,14 @@ const char *eqLogTypes[_log_largest_type] =
ErrorLog::ErrorLog(const char* file_name)
{
_eqp
log_mutex = new Mutex();
error_log = fopen(file_name, "w");
}
ErrorLog::~ErrorLog()
{
_eqp
log_mutex->lock();
if(error_log)
{
@ -51,6 +53,7 @@ ErrorLog::~ErrorLog()
void ErrorLog::Log(eqLogType type, const char *message, ...)
{
_eqp
if(type >= _log_largest_type)
{
return;
@ -98,6 +101,7 @@ void ErrorLog::Log(eqLogType type, const char *message, ...)
void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size)
{
_eqp
if(type >= _log_largest_type)
{
return;

View File

@ -26,8 +26,10 @@
#include "login_server.h"
#include <time.h>
#include <stdlib.h>
#include <signal.h>
#include <string>
#include <sstream>
#include <fstream>
TimeoutManager timeout_manager;
LoginServer server;
@ -37,6 +39,20 @@ bool run_server = true;
void CatchSignal(int sig_num)
{
#ifdef EQPERF_ENABLED
char time_str[128];
time_t result = time(nullptr);
strftime(time_str, sizeof(time_str), "%Y_%m_%d__%H_%M_%S", localtime(&result));
std::string prof_name = "./profile/login_";
prof_name += time_str;
prof_name += ".log";
std::ofstream profile_out(prof_name, std::ofstream::out);
if(profile_out.good()) {
EQP::CPU::ST::GetProfiler().Dump(profile_out);
}
#endif
}
int main()
@ -47,14 +63,23 @@ int main()
//Create our error log, is of format login_<number>.log
time_t current_time = time(nullptr);
std::stringstream log_name(std::stringstream::in | std::stringstream::out);
#ifdef WIN32
log_name << ".\\logs\\login_" << (unsigned int)current_time << ".log";
#else
log_name << "./logs/login_" << (unsigned int)current_time << ".log";
#endif
server_log = new ErrorLog(log_name.str().c_str());
server_log->Log(log_debug, "Logging System Init.");
if(signal(SIGINT, CatchSignal) == SIG_ERR) {
server_log->Log(log_error, "Could not set signal handler");
return 1;
}
if(signal(SIGTERM, CatchSignal) == SIG_ERR) {
server_log->Log(log_error, "Could not set signal handler");
return 1;
}
if(signal(SIGBREAK, CatchSignal) == SIG_ERR) {
server_log->Log(log_error, "Could not set signal handler");
return 1;
}
//Create our subsystem and parse the ini file.
server.config = new Config();
server_log->Log(log_debug, "Config System Init.");

View File

@ -27,6 +27,7 @@ extern bool run_server;
ServerManager::ServerManager()
{
_eqp
char error_buffer[TCPConnection_ErrorBufferSize];
int listen_port = atoi(server.config->GetVariable("options", "listen_port").c_str());
@ -44,6 +45,7 @@ ServerManager::ServerManager()
ServerManager::~ServerManager()
{
_eqp
if(tcps)
{
tcps->Close();
@ -53,6 +55,7 @@ ServerManager::~ServerManager()
void ServerManager::Process()
{
_eqp
ProcessDisconnect();
EmuTCPConnection *tcp_c = nullptr;
while(tcp_c = tcps->NewQueuePop())
@ -94,6 +97,7 @@ void ServerManager::Process()
void ServerManager::ProcessDisconnect()
{
_eqp
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{
@ -116,6 +120,7 @@ void ServerManager::ProcessDisconnect()
WorldServer* ServerManager::GetServerByAddress(unsigned int address)
{
_eqp
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{
@ -131,6 +136,7 @@ WorldServer* ServerManager::GetServerByAddress(unsigned int address)
EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
{
_eqp
unsigned int packet_size = sizeof(ServerListHeader_Struct);
unsigned int server_count = 0;
in_addr in;
@ -268,6 +274,7 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int client_account_id)
{
_eqp
list<WorldServer*>::iterator iter = world_servers.begin();
bool found = false;
while(iter != world_servers.end())
@ -298,6 +305,7 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *ignore)
{
_eqp
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{
@ -319,6 +327,7 @@ bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *igno
void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServer *ignore)
{
_eqp
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{

View File

@ -25,6 +25,7 @@ extern LoginServer server;
WorldServer::WorldServer(EmuTCPConnection *c)
{
_eqp
connection = c;
zones_booted = 0;
players_online = 0;
@ -39,6 +40,7 @@ WorldServer::WorldServer(EmuTCPConnection *c)
WorldServer::~WorldServer()
{
_eqp
if(connection)
{
connection->Free();
@ -47,6 +49,7 @@ WorldServer::~WorldServer()
void WorldServer::Reset()
{
_eqp
zones_booted = 0;
players_online = 0;
status = 0;
@ -59,6 +62,7 @@ void WorldServer::Reset()
bool WorldServer::Process()
{
_eqp
ServerPacket *app = nullptr;
while(app = connection->PopPacket())
{
@ -237,6 +241,7 @@ bool WorldServer::Process()
void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
{
_eqp
if(logged_in)
{
server_log->Log(log_network_error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting.");
@ -501,6 +506,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s)
{
_eqp
players_online = s->num_players;
zones_booted = s->num_zones;
status = s->status;
@ -508,6 +514,7 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s)
void WorldServer::SendClientAuth(unsigned int ip, string account, string key, unsigned int account_id)
{
_eqp
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ServerLSClientAuth));
ServerLSClientAuth* slsca = (ServerLSClientAuth*)outapp->pBuffer;

View File

@ -153,10 +153,6 @@ int command_init(void) {
#ifdef PACKET_PROFILER
command_add("packetprofile", "- Dump packet profile for target or self.", 250, command_packetprofile) ||
#endif
#ifdef EQPROFILE
command_add("profiledump", "- Dump profiling info to logs", 250, command_profiledump) ||
command_add("profilereset", "- Reset profiling info", 250, command_profilereset) ||
#endif
#ifdef BOTS
command_add("bot", "- Type \"#bot help\" to the see the list of available commands for bots.", 0, command_bot) ||
#endif
@ -6611,16 +6607,6 @@ void command_packetprofile(Client *c, const Seperator *sep) {
}
#endif
#ifdef EQPROFILE
void command_profiledump(Client *c, const Seperator *sep) {
DumpZoneProfile();
}
void command_profilereset(Client *c, const Seperator *sep) {
ResetZoneProfile();
}
#endif
void command_opcode(Client *c, const Seperator *sep) {
if(!strcasecmp(sep->arg[1], "reload" )) {
ReloadAllPatches();

View File

@ -325,11 +325,6 @@ void command_tune(Client *c, const Seperator *sep);
void command_logtest(Client *c, const Seperator *sep);
void command_mysqltest(Client *c, const Seperator *sep);
void command_logs(Client *c, const Seperator *sep);
#ifdef EQPROFILE
void command_profiledump(Client *c, const Seperator *sep);
void command_profilereset(Client *c, const Seperator *sep);
#endif
#ifdef PACKET_PROFILER
void command_packetprofile(Client *c, const Seperator *sep);

View File

@ -308,12 +308,6 @@ int main(int argc, char** argv) {
}
Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect
#ifdef EQPROFILE
#ifdef PROFILE_DUMP_TIME
Timer profile_dump_timer(PROFILE_DUMP_TIME*1000);
profile_dump_timer.Start();
#endif
#endif
if (!strlen(zone_name) || !strcmp(zone_name,".")) {
Log.Out(Logs::General, Logs::Zone_Server, "Entering sleep mode");
} else if (!Zone::Bootup(database.GetZoneID(zone_name), 0, true)) { //todo: go above and fix this to allow cmd line instance
@ -444,13 +438,6 @@ int main(int argc, char** argv) {
worldserver.AsyncConnect();
}
#ifdef EQPROFILE
#ifdef PROFILE_DUMP_TIME
if(profile_dump_timer.Check()) {
DumpZoneProfile();
}
#endif
#endif
} //end extra profiler block
Sleep(ZoneTimerResolution);
}