diff options
-rw-r--r-- | data/example.conf | 3 | ||||
-rw-r--r-- | data/modules.example.conf | 19 | ||||
-rw-r--r-- | modules/database/db_mysql_live.cpp | 80 | ||||
-rw-r--r-- | modules/extra/async_commands.h | 30 | ||||
-rw-r--r-- | modules/extra/m_async_commands.cpp | 233 |
5 files changed, 10 insertions, 355 deletions
diff --git a/data/example.conf b/data/example.conf index 62ce6b127..d4507d055 100644 --- a/data/example.conf +++ b/data/example.conf @@ -984,9 +984,6 @@ db_plain * This effectively allows you to edit your database and have it be immediately * reflected back in Anope. * - * For information on how to make db_mysql_live use asynchronous queries see - * m_async_commands. - * * At this time db_mysql_live only supports pulling data in real time from the three * main tables: anope_cs_info, anope_ns_alias, and anope_ns_core. */ diff --git a/data/modules.example.conf b/data/modules.example.conf index 8ee15877e..955ab16bb 100644 --- a/data/modules.example.conf +++ b/data/modules.example.conf @@ -17,21 +17,7 @@ module { name = "help" } /* - * m_async_commands - * - * Threads for each command executed by users. You should - * only load this if you are using a module designed to work with this. - * - * If this is loaded with db_mysql_live then Anope will support - * processing multiple commands at once which will negate the "lag" - * issues caused from the overhead of SQL queries by db_mysql_live. - * - * Note that this module is currently EXPERIMENTAL and you should report - * any bugs you find. - */ -#module { name = "m_async_commands" } - -/* m_dnsbl + * m_dnsbl * * Allows configurable DNS blacklists to check connecting users against. If a user * is found on the blacklist they will be immediately banned. This is a crucial module @@ -94,7 +80,8 @@ blacklist reason = "You have a host listed in the DroneBL. For more information, visit http://dronebl.org/lookup_branded.do?ip=%i&network=%N" } -/* m_helpchan +/* + * m_helpchan * * Gives users who are op in the specified help channel usermode +h (helpop). */ diff --git a/modules/database/db_mysql_live.cpp b/modules/database/db_mysql_live.cpp index 07b9b037c..d320b5001 100644 --- a/modules/database/db_mysql_live.cpp +++ b/modules/database/db_mysql_live.cpp @@ -1,5 +1,4 @@ #include "module.h" -#include "../extra/async_commands.h" #include "../extra/sql.h" class SQLCache : public Timer @@ -136,7 +135,6 @@ static void NickCoreUpdate(const SQLResult &res) class MySQLLiveModule : public Module { service_reference<SQLProvider> SQL; - service_reference<AsynchCommandsService> ACS; SQLCache chan_cache, nick_cache, core_cache; @@ -151,16 +149,9 @@ class MySQLLiveModule : public Module return res; } - CommandMutex *CurrentCommand() - { - if (this->ACS) - return this->ACS->CurrentCommand(); - return NULL; - } - public: MySQLLiveModule(const Anope::string &modname, const Anope::string &creator) : - Module(modname, creator, DATABASE), SQL("mysql/main"), ACS("asynch_commands") + Module(modname, creator, DATABASE), SQL("mysql/main") { Implementation i[] = { I_OnFindChan, I_OnFindNick, I_OnFindCore, I_OnShutdown }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); @@ -182,27 +173,8 @@ class MySQLLiveModule : public Module { SQLQuery query("SELECT * FROM `anope_cs_info` WHERE `name` = @name"); query.setValue("name", chname); - CommandMutex *current_command = this->CurrentCommand(); - if (current_command) - { - current_command->Unlock(); - try - { - SQLResult res = this->RunQuery(query); - current_command->Lock(); - ChanInfoUpdate(res); - } - catch (const SQLException &) - { - current_command->Lock(); - throw; - } - } - else - { - SQLResult res = this->RunQuery(query); - ChanInfoUpdate(res); - } + SQLResult res = this->RunQuery(query); + ChanInfoUpdate(res); } catch (const SQLException &ex) { @@ -219,27 +191,8 @@ class MySQLLiveModule : public Module { SQLQuery query("SELECT * FROM `anope_ns_alias` WHERE `nick` = @nick"); query.setValue("nick", nick); - CommandMutex *current_command = this->CurrentCommand(); - if (current_command) - { - current_command->Unlock(); - try - { - SQLResult res = this->RunQuery(query); - current_command->Lock(); - NickInfoUpdate(res); - } - catch (const SQLException &) - { - current_command->Lock(); - throw; - } - } - else - { - SQLResult res = this->RunQuery(query); - NickInfoUpdate(res); - } + SQLResult res = this->RunQuery(query); + NickInfoUpdate(res); } catch (const SQLException &ex) { @@ -256,27 +209,8 @@ class MySQLLiveModule : public Module { SQLQuery query("SELECT * FROM `anope_ns_core` WHERE `display` = @display"); query.setValue("display", nick); - CommandMutex *current_command = this->CurrentCommand(); - if (current_command) - { - current_command->Unlock(); - try - { - SQLResult res = this->RunQuery(query); - current_command->Lock(); - NickCoreUpdate(res); - } - catch (const SQLException &) - { - current_command->Lock(); - throw; - } - } - else - { - SQLResult res = this->RunQuery(query); - NickCoreUpdate(res); - } + SQLResult res = this->RunQuery(query); + NickCoreUpdate(res); } catch (const SQLException &ex) { diff --git a/modules/extra/async_commands.h b/modules/extra/async_commands.h deleted file mode 100644 index a2f650bae..000000000 --- a/modules/extra/async_commands.h +++ /dev/null @@ -1,30 +0,0 @@ - -class CommandMutex : public Thread -{ - public: - // Mutex used by this command to allow the core to drop and pick up processing of it at will - Mutex mutex; - // Set to true when this thread is processing data that is not thread safe (eg, the command) - bool processing; - CommandSource source; - Command *command; - std::vector<Anope::string> params; - - CommandMutex(CommandSource &s, Command *c, const std::vector<Anope::string> &p) : Thread(), processing(true), source(s), command(c), params(p) { } - - ~CommandMutex() { } - - virtual void Run() = 0; - - virtual void Lock() = 0; - - virtual void Unlock() = 0; -}; - -class AsynchCommandsService : public Service -{ - public: - AsynchCommandsService(Module *o, const Anope::string &n) : Service(o, n) { } - virtual CommandMutex *CurrentCommand() = 0; -}; - diff --git a/modules/extra/m_async_commands.cpp b/modules/extra/m_async_commands.cpp deleted file mode 100644 index 814c86c92..000000000 --- a/modules/extra/m_async_commands.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include "module.h" -#include "async_commands.h" - -static bool ignore_pre_command = false; -static Pipe *me; -static CommandMutex *current_command = NULL; -static std::list<CommandMutex *> commands; -/* Mutex held by the core when it is processing. Used by threads to halt the core */ -static Mutex main_mutex; - -class AsynchCommandMutex : public CommandMutex -{ - public: - bool destroy; - bool started; - - AsynchCommandMutex(CommandSource &s, Command *c, const std::vector<Anope::string> &p) : CommandMutex(s, c, p), destroy(false), started(false) - { - commands.push_back(this); - - this->mutex.Lock(); - } - - ~AsynchCommandMutex() - { - std::list<CommandMutex *>::iterator it = std::find(commands.begin(), commands.end(), this); - if (it != commands.end()) - commands.erase(it); - if (this == current_command) - current_command = NULL; - } - - void Run() - { - this->started = true; - - User *u = this->source.u; - BotInfo *bi = this->source.owner; - - ignore_pre_command = true; - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreCommand, OnPreCommand(source, command, params)); - if (MOD_RESULT == EVENT_STOP) - { - source.DoReply(); - return; - } - - if (!this->source.permission.empty() && !u->HasCommand(this->source.permission)) - { - u->SendMessage(bi, ACCESS_DENIED); - Log(LOG_COMMAND, "denied", bi) << "Access denied for user " << u->GetMask() << " with command " << command; - } - else - { - command->Execute(source, params); - FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, command, params)); - source.DoReply(); - } - - main_mutex.Unlock(); - } - - void Lock() - { - if (this->destroy) - this->Exit(); - - this->processing = true; - me->Notify(); - this->mutex.Lock(); - - if (this->destroy) - { - this->Unlock(); - this->Exit(); - } - } - - void Unlock() - { - this->processing = false; - main_mutex.Unlock(); - } - - void Destroy() - { - this->destroy = true; - } -}; - - -class ModuleAsynchCommands : public Module, public Pipe, public AsynchCommandsService -{ - bool reset; - - void Reset() - { - this->reset = false; - - unsigned count = 0, size = commands.size(); - for (std::list<CommandMutex *>::iterator it = commands.begin(); count < size; ++count, ++it) - { - AsynchCommandMutex *cm = debug_cast<AsynchCommandMutex *>(*it); - cm->Destroy(); - - new AsynchCommandMutex(cm->source, cm->command, cm->params); - } - } - - public: - ModuleAsynchCommands(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), Pipe(), AsynchCommandsService(this, "asynch_commands"), reset(false) - { - me = this; - - this->SetPermanent(true); - - main_mutex.Lock(); - - Implementation i[] = { I_OnDeleteObject, I_OnPreCommand }; - ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - - ModuleManager::SetPriority(this, PRIORITY_FIRST); - - ModuleManager::RegisterService(this); - } - - void OnDeleteObject(Base *b) - { - for (std::list<CommandMutex *>::iterator it = commands.begin(), it_end = commands.end(); it != it_end; ++it) - { - AsynchCommandMutex *cm = debug_cast<AsynchCommandMutex *>(*it); - - if (cm->started && (cm->command == b || cm->source.u == b || cm->source.owner == b || cm->source.service == b)) - cm->Destroy(); - } - - this->reset = true; - } - - EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) - { - if (ignore_pre_command) - { - ignore_pre_command = false; - return EVENT_CONTINUE; - } - else if (current_command) - return EVENT_CONTINUE; - else if (command->name == "RESTART") - return EVENT_CONTINUE; - - CommandSource source_copy = source; - AsynchCommandMutex *cm = new AsynchCommandMutex(source_copy, command, params); - - try - { - // Give processing to the command thread - Log(LOG_DEBUG_2) << "Waiting for command thread " << cm->command->name << " from " << source_copy.u->nick; - current_command = cm; - threadEngine.Start(cm); - main_mutex.Lock(); - current_command = NULL; - - return EVENT_STOP; - } - catch (const CoreException &ex) - { - delete cm; - Log() << "Unable to thread for command: " << ex.GetReason(); - } - - return EVENT_CONTINUE; - } - - void OnNotify() - { - for (std::list<CommandMutex *>::iterator it = commands.begin(), it_end = commands.end(); it != it_end;) - { - AsynchCommandMutex *cm = debug_cast<AsynchCommandMutex *>(*it++); - - // Thread engine will pick this up later - if (cm->GetExitState() || !cm->processing) - continue; - else if (cm->destroy) - { - if (cm->started) - { - cm->mutex.Unlock(); - continue; - } - else - delete cm; - } - - if (this->reset) - { - this->Reset(); - return this->OnNotify(); - } - - Log(LOG_DEBUG_2) << "Waiting for command thread " << cm->command->name << " from " << cm->source.u->nick; - current_command = cm; - - // Unlock to give processing back to the command thread - if (!cm->started) - { - try - { - threadEngine.Start(cm); - } - catch (const CoreException &) - { - delete cm; - continue; - } - } - else - cm->mutex.Unlock(); - // Relock to regain processing once the command thread hangs for any reason - main_mutex.Lock(); - - current_command = NULL; - } - } - - CommandMutex *CurrentCommand() - { - return current_command; - } -}; - -MODULE_INIT(ModuleAsynchCommands) |