Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
gesior committed Jul 6, 2023
1 parent 3a24a5e commit c06c499
Show file tree
Hide file tree
Showing 31 changed files with 1,249 additions and 862 deletions.
1 change: 1 addition & 0 deletions logs/.gitkeep
@@ -0,0 +1 @@
OTS Stats logs
2 changes: 1 addition & 1 deletion sources/Makefile
Expand Up @@ -40,7 +40,7 @@ DATABASE = databasemysql.cpp
# For OT_ADMIN, add admin.cpp admin.h
EXTRASOURCES =

CXXSOURCES = actions.cpp allocator.cpp baseevents.cpp beds.cpp \
CXXSOURCES = stats.cpp actions.cpp allocator.cpp baseevents.cpp beds.cpp \
chat.cpp combat.cpp condition.cpp configmanager.cpp \
connection.cpp container.cpp creature.cpp creatureevent.cpp\
cylinder.cpp database.cpp databasemanager.cpp $(DATABASE) \
Expand Down
18 changes: 9 additions & 9 deletions sources/admin.cpp
Expand Up @@ -332,7 +332,7 @@ void ProtocolAdmin::parsePacket(NetworkMessage& msg)
flags |= SAVE_PLAYERS_SHALLOW;

addLogLine(LOGTYPE_EVENT, "saving server");
Dispatcher::getInstance().addTask(createTask(boost::bind(&Game::saveGameState, &g_game, flags)));
g_dispatcher.addTask(createTask(boost::bind(&Game::saveGameState, &g_game, flags)));

output->put<char>(AP_MSG_COMMAND_OK);
break;
Expand All @@ -341,7 +341,7 @@ void ProtocolAdmin::parsePacket(NetworkMessage& msg)
case CMD_CLOSE_SERVER:
{
addLogLine(LOGTYPE_EVENT, "closing server");
Dispatcher::getInstance().addTask(createTask(boost::bind(
g_dispatcher.addTask(createTask(boost::bind(
&Game::setGameState, &g_game, GAMESTATE_CLOSED)));

output->put<char>(AP_MSG_COMMAND_OK);
Expand All @@ -360,7 +360,7 @@ void ProtocolAdmin::parsePacket(NetworkMessage& msg)
case CMD_SHUTDOWN_SERVER:
{
addLogLine(LOGTYPE_EVENT, "shutting down server");
Dispatcher::getInstance().addTask(createTask(boost::bind(
g_dispatcher.addTask(createTask(boost::bind(
&Game::setGameState, &g_game, GAMESTATE_SHUTDOWN)));

output->put<char>(AP_MSG_COMMAND_OK);
Expand All @@ -369,31 +369,31 @@ void ProtocolAdmin::parsePacket(NetworkMessage& msg)

case CMD_PAY_HOUSES:
{
Dispatcher::getInstance().addTask(createTask(boost::bind(
g_dispatcher.addTask(createTask(boost::bind(
&ProtocolAdmin::adminCommandPayHouses, this)));
break;
}

case CMD_RELOAD_SCRIPTS:
{
const int8_t reload = msg.get<char>();
Dispatcher::getInstance().addTask(createTask(boost::bind(
g_dispatcher.addTask(createTask(boost::bind(
&ProtocolAdmin::adminCommandReload, this, reload)));
break;
}

case CMD_KICK:
{
const std::string param = msg.getString();
Dispatcher::getInstance().addTask(createTask(boost::bind(
g_dispatcher.addTask(createTask(boost::bind(
&ProtocolAdmin::adminCommandKickPlayer, this, param)));
break;
}

case CMD_SEND_MAIL:
{
const std::string xmlData = msg.getString();
Dispatcher::getInstance().addTask(createTask(boost::bind(
g_dispatcher.addTask(createTask(boost::bind(
&ProtocolAdmin::adminCommandSendMail, this, xmlData)));
break;
}
Expand All @@ -402,7 +402,7 @@ void ProtocolAdmin::parsePacket(NetworkMessage& msg)
{
const std::string param = msg.getString();
addLogLine(LOGTYPE_EVENT, "broadcasting: " + param);
Dispatcher::getInstance().addTask(createTask(boost::bind(
g_dispatcher.addTask(createTask(boost::bind(
&Game::broadcastMessage, &g_game, param, MSG_STATUS_WARNING)));

output->put<char>(AP_MSG_COMMAND_OK);
Expand Down Expand Up @@ -493,7 +493,7 @@ void ProtocolAdmin::adminCommandKickPlayer(const std::string& param)
Player* player = NULL;
if(g_game.getPlayerByNameWildcard(param, player) == RET_NOERROR)
{
Scheduler::getInstance().addEvent(createSchedulerTask(SCHEDULER_MINTICKS, boost::bind(&Game::kickPlayer, &g_game, player->getID(), false)));
g_scheduler.addEvent(createSchedulerTask(SCHEDULER_MINTICKS, boost::bind(&Game::kickPlayer, &g_game, player->getID(), false)));
addLogLine(LOGTYPE_EVENT, "kicking player " + player->getName());
output->put<char>(AP_MSG_COMMAND_OK);
}
Expand Down
2 changes: 1 addition & 1 deletion sources/beds.cpp
Expand Up @@ -128,7 +128,7 @@ void BedItem::sleep(Player* player)

player->getTile()->moveCreature(NULL, player, getTile());
g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_SLEEP);
Scheduler::getInstance().addEvent(createSchedulerTask(SCHEDULER_MINTICKS, boost::bind(&Game::kickPlayer, &g_game, player->getID(), false)));
g_scheduler.addEvent(createSchedulerTask(SCHEDULER_MINTICKS, boost::bind(&Game::kickPlayer, &g_game, player->getID(), false)));
}
else if(Item::items[getID()].transformUseTo)
{
Expand Down
4 changes: 2 additions & 2 deletions sources/connection.cpp
Expand Up @@ -106,7 +106,7 @@ void Connection::close(bool force)
connectionState = CONNECTION_STATE_CLOSED;

if (protocol) {
Dispatcher::getInstance().addTask(
g_dispatcher.addTask(
createTask(std::bind(&Protocol::release, protocol)));
}

Expand Down Expand Up @@ -140,7 +140,7 @@ Connection::~Connection()
void Connection::accept(Protocol_ptr protocol)
{
this->protocol = protocol;
Dispatcher::getInstance().addTask(createTask(std::bind(&Protocol::onConnect, protocol)));
g_dispatcher.addTask(createTask(std::bind(&Protocol::onConnect, protocol)));

accept();
}
Expand Down
8 changes: 4 additions & 4 deletions sources/creature.cpp
Expand Up @@ -352,7 +352,7 @@ void Creature::addEventWalk(bool firstStep/* = false*/)
if(ticks == 1)
g_game.checkCreatureWalk(getID());

eventWalk = Scheduler::getInstance().addEvent(createSchedulerTask(std::max((int64_t)SCHEDULER_MINTICKS, ticks),
eventWalk = g_scheduler.addEvent(createSchedulerTask(std::max((int64_t)SCHEDULER_MINTICKS, ticks),
boost::bind(&Game::checkCreatureWalk, &g_game, id)));
}

Expand All @@ -361,7 +361,7 @@ void Creature::stopEventWalk()
if(!eventWalk)
return;

Scheduler::getInstance().stopEvent(eventWalk);
g_scheduler.stopEvent(eventWalk);
eventWalk = 0;
}

Expand Down Expand Up @@ -673,7 +673,7 @@ void Creature::onCreatureMove(const Creature* creature, const Tile* newTile, con
if(hasFollowPath)
{
isUpdatingPath = true;
Dispatcher::getInstance().addTask(createTask(
g_dispatcher.addTask(createTask(
boost::bind(&Game::updateCreatureWalk, &g_game, getID())));
}

Expand All @@ -686,7 +686,7 @@ void Creature::onCreatureMove(const Creature* creature, const Tile* newTile, con
if(newPos.z == oldPos.z && canSee(attackedCreature->getPosition()))
{
if(hasExtraSwing()) //our target is moving lets see if we can get in hit
Dispatcher::getInstance().addTask(createTask(
g_dispatcher.addTask(createTask(
boost::bind(&Game::checkCreatureAttack, &g_game, getID())));

if(newTile->getZone() != oldTile->getZone())
Expand Down
13 changes: 10 additions & 3 deletions sources/databasemysql.cpp
Expand Up @@ -36,7 +36,7 @@ extern ConfigManager g_config;
DatabaseMySQL::~DatabaseMySQL()
{
if(m_timeoutTask != 0)
Scheduler::getInstance().stopEvent(m_timeoutTask);
g_scheduler.stopEvent(m_timeoutTask);

mysql_close(m_handle);
delete m_handle;
Expand Down Expand Up @@ -80,7 +80,7 @@ bool DatabaseMySQL::connect()

timeout = g_config.getNumber(ConfigManager::SQL_KEEPALIVE) * 1000;
if(timeout)
m_timeoutTask = Scheduler::getInstance().addEvent(createSchedulerTask(timeout,
m_timeoutTask = g_scheduler.addEvent(createSchedulerTask(timeout,
boost::bind(&DatabaseMySQL::keepAlive, this)));

return true;
Expand All @@ -93,7 +93,7 @@ void DatabaseMySQL::keepAlive()
return;

if(!mysql_ping(m_handle))
Scheduler::getInstance().addEvent(createSchedulerTask(timeout,
g_scheduler.addEvent(createSchedulerTask(timeout,
boost::bind(&DatabaseMySQL::keepAlive, this)));
else
m_connected = false;
Expand Down Expand Up @@ -133,6 +133,7 @@ bool DatabaseMySQL::query(std::string query)
return false;

m_lock.lock();
std::chrono::high_resolution_clock::time_point time_point = std::chrono::high_resolution_clock::now();
if(mysql_real_query(m_handle, query.c_str(), query.length()))
{
int32_t error = mysql_errno(m_handle);
Expand All @@ -149,6 +150,9 @@ bool DatabaseMySQL::query(std::string query)
if(tmp)
mysql_free_result(tmp);

uint64_t ns = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - time_point).count();
g_stats.addSqlStats(new Stat(ns, query.substr(0, 100), query.substr(0, 256)));

return true;
}

Expand All @@ -159,6 +163,7 @@ DBResult* DatabaseMySQL::storeQuery(std::string query)

int32_t error = 0;
m_lock.lock();
std::chrono::high_resolution_clock::time_point time_point = std::chrono::high_resolution_clock::now();
if(mysql_real_query(m_handle, query.c_str(), query.length()))
{
error = mysql_errno(m_handle);
Expand All @@ -172,6 +177,8 @@ DBResult* DatabaseMySQL::storeQuery(std::string query)

if(MYSQL_RES* _result = mysql_store_result(m_handle))
{
uint64_t ns = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - time_point).count();
g_stats.addSqlStats(new Stat(ns, query.substr(0, 100), query.substr(0, 256)));
m_lock.unlock();
DBResult* result = (DBResult*)new MySQLResult(_result);
return verifyResult(result);
Expand Down
132 changes: 59 additions & 73 deletions sources/dispatcher.cpp
Expand Up @@ -15,114 +15,100 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
////////////////////////////////////////////////////////////////////////
#include "otpch.h"
#include "dispatcher.h"

#include "outputmessage.h"
#if defined __EXCEPTION_TRACER__
#include "exception.h"
#endif

#include "dispatcher.h"
#include "game.h"
#include "outputmessage.h"

extern Game g_game;

Dispatcher::DispatcherState Dispatcher::m_threadState = Dispatcher::STATE_TERMINATED;
Task* createNewTask(std::function<void(void)> f, const std::string& description, const std::string& extraDescription)
{
return new Task(std::move(f), description, extraDescription);
}

Dispatcher::Dispatcher()
Task* createNewTask(uint32_t expiration, std::function<void(void)> f, const std::string& description, const std::string& extraDescription)
{
Dispatcher::m_threadState = Dispatcher::STATE_RUNNING;
m_thread = boost::thread(boost::bind(&Dispatcher::dispatcherThread, this));
return new Task(expiration, std::move(f), description, extraDescription);
}

void Dispatcher::dispatcherThread()
void Dispatcher::threadMain()
{
#if defined __EXCEPTION_TRACER__
ExceptionHandler dispatcherExceptionHandler;
dispatcherExceptionHandler.InstallHandler();
#endif

boost::unique_lock<boost::mutex> taskLockUnique(m_taskLock, boost::defer_lock);
while(Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED)
{
// NOTE: second argument defer_lock is to prevent from immediate locking
std::unique_lock<std::mutex> taskLockUnique(taskLock, std::defer_lock);
std::chrono::high_resolution_clock::time_point time_point;

while (getState() != THREAD_STATE_TERMINATED) {
// check if there are tasks waiting
taskLockUnique.lock();
if(m_taskList.empty()) //if the list is empty wait for signal
m_taskSignal.wait(taskLockUnique);

if(!m_taskList.empty() && Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED)
{
if (taskList.empty()) {
//if the list is empty wait for signal
time_point = std::chrono::high_resolution_clock::now();
taskSignal.wait(taskLockUnique);
g_stats.dispatcherWaitTime(dispatcherId) += std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - time_point).count();
}

if (!taskList.empty()) {
time_point = std::chrono::high_resolution_clock::now();

// take the first task
Task* task = m_taskList.front();
m_taskList.pop_front();
Task* task = taskList.front();
taskList.pop_front();
taskLockUnique.unlock();

if(!task->hasExpired())
{
if (!task->hasExpired()) {
++dispatcherCycle;
// execute it
(*task)();

g_game.clearSpectatorCache();
}
delete task;

task->executionTime = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - time_point).count();
g_stats.addDispatcherTask(dispatcherId, task);

} else {
taskLockUnique.unlock();
}
}

#if defined __EXCEPTION_TRACER__
dispatcherExceptionHandler.RemoveHandler();
#endif
}

void Dispatcher::addTask(Task* task, bool front/* = false*/)
void Dispatcher::addTask(Task* task, bool push_front /*= false*/)
{
bool signal = false;
m_taskLock.lock();
if(Dispatcher::m_threadState == Dispatcher::STATE_RUNNING)
{
signal = m_taskList.empty();
if(front)
m_taskList.push_front(task);
else
m_taskList.push_back(task);
}
#ifdef __DEBUG_SCHEDULER__
else
std::clog << "[Error - Dispatcher::addTask] Dispatcher thread is terminated." << std::endl;
#endif
bool do_signal = false;

m_taskLock.unlock();
// send a signal if the list was empty
if(signal)
m_taskSignal.notify_one();
}
taskLock.lock();

void Dispatcher::flush()
{
Task* task = NULL;
while(!m_taskList.empty())
{
task = m_taskList.front();
m_taskList.pop_front();
if (getState() == THREAD_STATE_RUNNING) {
do_signal = taskList.empty();

(*task)();
if (push_front) {
taskList.push_front(task);
} else {
taskList.push_back(task);
}
} else {
delete task;

g_game.clearSpectatorCache();
}
}

void Dispatcher::stop()
{
m_taskLock.lock();
m_threadState = Dispatcher::STATE_CLOSING;
m_taskLock.unlock();
taskLock.unlock();

// send a signal if the list was empty
if (do_signal) {
taskSignal.notify_one();
}
}

void Dispatcher::shutdown()
{
m_taskLock.lock();
m_threadState = Dispatcher::STATE_TERMINATED;
Task* task = createTask([this]() {
setState(THREAD_STATE_TERMINATED);
taskSignal.notify_one();
});

std::lock_guard<std::mutex> lockClass(taskLock);
taskList.push_back(task);

flush();
m_taskLock.unlock();
}
taskSignal.notify_one();
}

0 comments on commit c06c499

Please sign in to comment.