summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/CMakeLists.txt5
-rw-r--r--include/bots.h2
-rw-r--r--include/commands.h6
-rw-r--r--include/modules.h7
-rw-r--r--modules/extra/async_commands.h4
-rw-r--r--modules/extra/db_mysql_live.cpp355
-rw-r--r--modules/extra/m_async_commands.cpp95
-rw-r--r--modules/extra/m_mysql.cpp17
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/base.cpp3
-rw-r--r--src/bots.cpp4
-rw-r--r--src/command.cpp40
-rw-r--r--src/commands.cpp2
-rw-r--r--src/modulemanager.cpp2
-rw-r--r--src/threadengines/threadengine_pthread.cpp1
-rw-r--r--src/threadengines/threadengine_win32.cpp1
16 files changed, 406 insertions, 141 deletions
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 8b292aea2..a2f8c42d7 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -19,6 +19,8 @@ endif(NOT WIN32)
set(PCH_SOURCES_GCH "")
if(CMAKE_COMPILER_IS_GNUCXX)
string(REPLACE " " ";" PCH_CXXFLAGS ${CXXFLAGS})
+ file(GLOB INCLUDE_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h")
+ remove_item_from_list(INCLUDE_SRCS "version.h")
set(PCH_SOURCES "module.h;modules.h;services.h")
foreach(PCH_SOURCE ${PCH_SOURCES})
@@ -32,7 +34,8 @@ if(CMAKE_COMPILER_IS_GNUCXX)
set(PCH_SOURCES_GCH "${PCH_SOURCES_GCH};${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch")
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch
- COMMAND ${CMAKE_CXX_COMPILER} ARGS ${PCH_CXXFLAGS} ${PCH_EXTRAFLAGS} -I${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${PCH_SOURCE} -o ${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch VERBATIM
+ COMMAND ${CMAKE_CXX_COMPILER} ARGS ${PCH_CXXFLAGS} ${PCH_EXTRAFLAGS} -I${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${PCH_SOURCE} -o ${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch
+ DEPENDS ${INCLUDE_SRCS} VERBATIM
)
endforeach(PCH_SOURCE ${PCH_SOURCES})
endif(CMAKE_COMPILER_IS_GNUCXX)
diff --git a/include/bots.h b/include/bots.h
index 84c4fa2ec..7cdf417f1 100644
--- a/include/bots.h
+++ b/include/bots.h
@@ -51,6 +51,8 @@ class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END>
*/
virtual ~BotInfo();
+ void SetIdent(const Anope::string &sident);
+
/** Change the nickname for the bot.
* @param newnick The nick to change to
*/
diff --git a/include/commands.h b/include/commands.h
index a2d6643fe..8320c531a 100644
--- a/include/commands.h
+++ b/include/commands.h
@@ -69,15 +69,15 @@ struct CoreExport CommandSource
std::list<Anope::string> reply;
- ~CommandSource();
-
void Reply(const char *message, ...);
void Reply(const Anope::string &message);
+
+ void DoReply();
};
/** Every services command is a class, inheriting from Command.
*/
-class CoreExport Command : public Flags<CommandFlag>
+class CoreExport Command : public Flags<CommandFlag>, public Base
{
Anope::string desc;
diff --git a/include/modules.h b/include/modules.h
index 4532549f1..c407e2c21 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -1066,6 +1066,11 @@ class CoreExport Module : public Extensible
* @return MOD_STOP to stop processing completely
*/
virtual EventReturn OnPrivmsg(User *u, ChannelInfo *ci, Anope::string &msg, bool &Allow) { return EVENT_CONTINUE; }
+
+ /** Called when any object is destroyed
+ * @param b The object
+ */
+ virtual void OnObjectDestroy(Base *b) { }
};
/** Implementation-specific flags which may be set in ModuleManager::Attach()
@@ -1118,7 +1123,7 @@ enum Implementation
I_OnServerQuit, I_OnTopicUpdated,
I_OnEncrypt, I_OnEncryptCheckLen, I_OnDecrypt, I_OnCheckPassword,
I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd,
- I_OnMLock, I_OnUnMLock, I_OnServerSync, I_OnUplinkSync, I_OnBotPrivmsg, I_OnPrivmsg,
+ I_OnMLock, I_OnUnMLock, I_OnServerSync, I_OnUplinkSync, I_OnBotPrivmsg, I_OnPrivmsg, I_OnObjectDestroy,
I_END
};
diff --git a/modules/extra/async_commands.h b/modules/extra/async_commands.h
index b6b9e7c2b..a2f650bae 100644
--- a/modules/extra/async_commands.h
+++ b/modules/extra/async_commands.h
@@ -6,11 +6,11 @@ class CommandMutex : public Thread
Mutex mutex;
// Set to true when this thread is processing data that is not thread safe (eg, the command)
bool processing;
- Command *command;
CommandSource source;
+ Command *command;
std::vector<Anope::string> params;
- CommandMutex() : Thread(), processing(true) { }
+ CommandMutex(CommandSource &s, Command *c, const std::vector<Anope::string> &p) : Thread(), processing(true), source(s), command(c), params(p) { }
~CommandMutex() { }
diff --git a/modules/extra/db_mysql_live.cpp b/modules/extra/db_mysql_live.cpp
index 8f14f3998..c5e645be6 100644
--- a/modules/extra/db_mysql_live.cpp
+++ b/modules/extra/db_mysql_live.cpp
@@ -2,59 +2,51 @@
#include "async_commands.h"
#include "sql.h"
-class MySQLLiveModule : public Module
+class SQLCache : public Timer
{
- service_reference<SQLProvider> SQL;
- service_reference<AsynchCommandsService> ACS;
+ typedef std::map<Anope::string, time_t, std::less<ci::string> > cache_map;
+ cache_map cache;
+ public:
- SQLResult RunQuery(const Anope::string &query)
+ SQLCache() : Timer(300, Anope::CurTime, true) { }
+
+ bool Check(const Anope::string &item)
{
- if (!this->SQL)
- throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
+ cache_map::iterator it = this->cache.find(item);
+ if (it != this->cache.end() && Anope::CurTime - it->second < 5)
+ return true;
- return SQL->RunQuery(query);
+ this->cache[item] = Anope::CurTime;
+ return false;
}
- const Anope::string Escape(const Anope::string &query)
+ void Tick(time_t)
{
- return SQL ? SQL->Escape(query) : query;
- }
+ for (cache_map::iterator it = this->cache.begin(), next_it; it != this->cache.end(); it = next_it)
+ {
+ next_it = it;
+ ++next_it;
- CommandMutex *CurrentCommand()
- {
- if (this->ACS)
- return this->ACS->CurrentCommand();
- return NULL;
+ if (Anope::CurTime - it->second > 5)
+ this->cache.erase(it);
+ }
}
+};
+class BotInfoUpdater : public SQLInterface, public SQLCache
+{
public:
- MySQLLiveModule(const Anope::string &modname, const Anope::string &creator) :
- Module(modname, creator), SQL("mysql/main"), ACS("asynch_commands")
+ BotInfoUpdater(Module *m) : SQLInterface(m) { }
+
+ void OnResult(const SQLResult &r)
{
- Implementation i[] = { I_OnFindBot, I_OnFindChan, I_OnFindNick, I_OnFindCore };
- ModuleManager::Attach(i, this, 4);
+ BotInfoUpdater::Process(r);
}
- void OnFindBot(const Anope::string &nick)
+ static void Process(const SQLResult &res)
{
- static bool lookup = true;
- if (lookup == false)
- {
- lookup = true;
- return;
- }
-
try
{
- CommandMutex *current_command = this->CurrentCommand();
-
- if (current_command)
- current_command->Unlock();
- SQLResult res = this->RunQuery("SELECT * FROM `anope_bs_core` WHERE `nick` = '" + this->Escape(nick) + "'");
- if (current_command)
- current_command->Lock();
-
- lookup = false;
BotInfo *bi = findbot(res.Get(0, "nick"));
if (!bi)
bi = new BotInfo(res.Get(0, "nick"), res.Get(0, "user"), res.Get(0, "host"), res.Get(0, "rname"));
@@ -70,30 +62,28 @@ class MySQLLiveModule : public Module
bi->created = convertTo<time_t>(res.Get(0, "created"));
bi->chancount = convertTo<uint32>(res.Get(0, "chancount"));
}
- catch (const SQLException &) { }
+ catch (const SQLException &ex)
+ {
+ Log(LOG_DEBUG) << ex.GetReason();
+ }
catch (const ConvertException &) { }
}
+};
- void OnFindChan(const Anope::string &chname)
+class ChanInfoUpdater : public SQLInterface, public SQLCache
+{
+ public:
+ ChanInfoUpdater(Module *m) : SQLInterface(m) { }
+
+ void OnResult(const SQLResult &r)
{
- static bool lookup = true;
- if (lookup == false)
- {
- lookup = true;
- return;
- }
+ ChanInfoUpdater::Process(r);
+ }
+ static void Process(const SQLResult &res)
+ {
try
{
- CommandMutex *current_command = this->CurrentCommand();
-
- if (current_command)
- current_command->Unlock();
- SQLResult res = this->RunQuery("SELECT * FROM `anope_cs_info` WHERE `name` = '" + this->Escape(chname) + "'");
- if (current_command)
- current_command->Lock();
-
- lookup = false;
ChannelInfo *ci = cs_findchan(res.Get(0, "name"));
if (!ci)
ci = new ChannelInfo(res.Get(0, "name"));
@@ -159,33 +149,31 @@ class MySQLLiveModule : public Module
if (ci->c)
check_modes(ci->c);
}
- catch (const SQLException &) { }
+ catch (const SQLException &ex)
+ {
+ Log(LOG_DEBUG) << ex.GetReason();
+ }
catch (const ConvertException &) { }
}
+};
- void OnFindNick(const Anope::string &nick)
+class NickInfoUpdater : public SQLInterface, public SQLCache
+{
+ public:
+ NickInfoUpdater(Module *m) : SQLInterface(m) { }
+
+ void OnResult(const SQLResult &r)
{
- static bool lookup = true;
- if (lookup == false)
- {
- lookup = true;
- return;
- }
+ NickInfoUpdater::Process(r);
+ }
+ static void Process(const SQLResult &res)
+ {
try
{
- CommandMutex *current_command = this->CurrentCommand();
-
- if (current_command)
- current_command->Unlock();
- SQLResult res = this->RunQuery("SELECT * FROM `anope_ns_alias` WHERE `nick` = '" + this->Escape(nick) + "'");
- if (current_command)
- current_command->Lock();
-
NickCore *nc = findcore(res.Get(0, "display"));
if (!nc)
return;
- lookup = false;
NickAlias *na = findnick(res.Get(0, "nick"));
if (!na)
na = new NickAlias(res.Get(0, "nick"), nc);
@@ -208,30 +196,28 @@ class MySQLLiveModule : public Module
na->nc->aliases.push_back(na);
}
}
- catch (const SQLException &) { }
+ catch (const SQLException &ex)
+ {
+ Log(LOG_DEBUG) << ex.GetReason();
+ }
catch (const ConvertException &) { }
}
+};
- void OnFindCore(const Anope::string &nick)
+class NickCoreUpdater : public SQLInterface, public SQLCache
+{
+ public:
+ NickCoreUpdater(Module *m) : SQLInterface(m) { }
+
+ void OnResult(const SQLResult &r)
{
- static bool lookup = true;
- if (lookup == false)
- {
- lookup = true;
- return;
- }
+ NickCoreUpdater::Process(r);
+ }
+ static void Process(const SQLResult &res)
+ {
try
{
- CommandMutex *current_command = this->CurrentCommand();
-
- if (current_command)
- current_command->Unlock();
- SQLResult res = this->RunQuery("SELECT * FROM `anope_ns_core` WHERE `name` = '" + this->Escape(nick) + "'");
- if (current_command)
- current_command->Lock();
-
- lookup = false;
NickCore *nc = findcore(res.Get(0, "display"));
if (!nc)
nc = new NickCore(res.Get(0, "display"));
@@ -243,9 +229,202 @@ class MySQLLiveModule : public Module
nc->FromString(BuildStringVector(res.Get(0, "flags")));
nc->language = res.Get(0, "language");
}
- catch (const SQLException &) { }
+ catch (const SQLException &ex)
+ {
+ Log(LOG_DEBUG) << ex.GetReason();
+ }
catch (const ConvertException &) { }
}
};
+class MySQLLiveModule : public Module
+{
+ service_reference<SQLProvider> SQL;
+ service_reference<AsynchCommandsService> ACS;
+
+ BotInfoUpdater botinfoupdater;
+ ChanInfoUpdater chaninfoupdater;
+ NickInfoUpdater nickinfoupdater;
+ NickCoreUpdater nickcoreupdater;
+
+ SQLResult RunQuery(const Anope::string &query)
+ {
+ if (!this->SQL)
+ throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
+
+ SQLResult res = SQL->RunQuery(query);
+ if (!res.GetError().empty())
+ throw SQLException(res.GetError());
+ return res;
+ }
+
+ void RunQuery(SQLInterface *i, const Anope::string &query)
+ {
+ if (!this->SQL)
+ throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
+
+ return SQL->Run(i, query);
+ }
+
+ const Anope::string Escape(const Anope::string &query)
+ {
+ return SQL ? SQL->Escape(query) : query;
+ }
+
+ CommandMutex *CurrentCommand()
+ {
+ if (this->ACS)
+ return this->ACS->CurrentCommand();
+ return NULL;
+ }
+
+ public:
+ MySQLLiveModule(const Anope::string &modname, const Anope::string &creator) :
+ Module(modname, creator), SQL("mysql/main"), ACS("asynch_commands"), botinfoupdater(this),
+ chaninfoupdater(this), nickinfoupdater(this), nickcoreupdater(this)
+ {
+ Implementation i[] = { I_OnFindBot, I_OnFindChan, I_OnFindNick, I_OnFindCore, I_OnPreShutdown };
+ ModuleManager::Attach(i, this, 5);
+ }
+
+ void OnPreShutdown()
+ {
+ Implementation i[] = { I_OnFindBot, I_OnFindChan, I_OnFindNick, I_OnFindCore };
+ for (size_t j = 0; j < 4; ++j)
+ ModuleManager::Detach(i[j], this);
+ }
+
+ void OnFindBot(const Anope::string &nick)
+ {
+ if (botinfoupdater.Check(nick))
+ return;
+
+ try
+ {
+ Anope::string query = "SELECT * FROM `anope_bs_core` WHERE `nick` = '" + this->Escape(nick) + "'";
+ CommandMutex *current_command = this->CurrentCommand();
+ if (current_command)
+ {
+ current_command->Unlock();
+ try
+ {
+ SQLResult res = this->RunQuery(query);
+ current_command->Lock();
+ BotInfoUpdater::Process(res);
+ }
+ catch (const SQLException &ex)
+ {
+ current_command->Lock();
+ throw;
+ }
+ }
+ else
+ this->RunQuery(&botinfoupdater, query);
+ }
+ catch (const SQLException &ex)
+ {
+ Log(LOG_DEBUG) << "OnBotChan: " << ex.GetReason();
+ }
+ }
+
+ void OnFindChan(const Anope::string &chname)
+ {
+ if (chaninfoupdater.Check(chname))
+ return;
+
+ try
+ {
+ Anope::string query = "SELECT * FROM `anope_cs_info` WHERE `name` = '" + this->Escape(chname) + "'";
+ CommandMutex *current_command = this->CurrentCommand();
+ if (current_command)
+ {
+ current_command->Unlock();
+ try
+ {
+ SQLResult res = this->RunQuery(query);
+ current_command->Lock();
+ ChanInfoUpdater::Process(res);
+ }
+ catch (const SQLException &)
+ {
+ current_command->Lock();
+ throw;
+ }
+ }
+ else
+ this->RunQuery(&chaninfoupdater, query);
+ }
+ catch (const SQLException &ex)
+ {
+ Log(LOG_DEBUG) << "OnFindChan: " << ex.GetReason();
+ }
+ }
+
+ void OnFindNick(const Anope::string &nick)
+ {
+ if (nickinfoupdater.Check(nick))
+ return;
+
+ try
+ {
+ Anope::string query = "SELECT * FROM `anope_ns_alias` WHERE `nick` = '" + this->Escape(nick) + "'";
+ CommandMutex *current_command = this->CurrentCommand();
+ if (current_command)
+ {
+ current_command->Unlock();
+ try
+ {
+ SQLResult res = this->RunQuery(query);
+ current_command->Lock();
+ NickInfoUpdater::Process(res);
+ }
+ catch (const SQLException &)
+ {
+ current_command->Lock();
+ throw;
+ }
+ }
+ else
+ this->RunQuery(&nickinfoupdater, query);
+ }
+ catch (const SQLException &ex)
+ {
+ Log(LOG_DEBUG) << "OnFindNick: " << ex.GetReason();
+ }
+ }
+
+ void OnFindCore(const Anope::string &nick)
+ {
+ if (nickcoreupdater.Check(nick))
+ return;
+
+ try
+ {
+ Anope::string query = "SELECT * FROM `anope_ns_core` WHERE `display` = '" + this->Escape(nick) + "'";
+ CommandMutex *current_command = this->CurrentCommand();
+ if (current_command)
+ {
+ current_command->Unlock();
+ try
+ {
+ SQLResult res = this->RunQuery(query);
+ current_command->Lock();
+ NickCoreUpdater::Process(res);
+ }
+ catch (const SQLException &)
+ {
+ current_command->Lock();
+ throw;
+ }
+ }
+ else
+ this->RunQuery(&nickcoreupdater, query);
+ }
+ catch (const SQLException &ex)
+ {
+ Log(LOG_DEBUG) << "OnFindCore: " << ex.GetReason();
+ }
+ }
+};
+
MODULE_INIT(MySQLLiveModule)
diff --git a/modules/extra/m_async_commands.cpp b/modules/extra/m_async_commands.cpp
index ddc660ea8..4f251431c 100644
--- a/modules/extra/m_async_commands.cpp
+++ b/modules/extra/m_async_commands.cpp
@@ -9,11 +9,15 @@ static Mutex main_mutex;
class AsynchCommandMutex : public CommandMutex
{
+ bool destroy;
public:
- AsynchCommandMutex() : CommandMutex()
+ 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);
- current_command = this;
+
+ this->mutex.Lock();
}
~AsynchCommandMutex()
@@ -27,6 +31,8 @@ class AsynchCommandMutex : public CommandMutex
void Run()
{
+ this->started = true;
+
User *u = this->source.u;
BotInfo *bi = this->source.owner;
@@ -43,6 +49,8 @@ class AsynchCommandMutex : public CommandMutex
{
FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, command, params));
}
+
+ source.DoReply();
}
main_mutex.Unlock();
@@ -50,6 +58,11 @@ class AsynchCommandMutex : public CommandMutex
void Lock()
{
+ if (this->destroy)
+ {
+ this->Exit();
+ }
+
this->processing = true;
me->Notify();
this->mutex.Lock();
@@ -60,13 +73,34 @@ class AsynchCommandMutex : public CommandMutex
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), Pipe(), AsynchCommandsService(this, "asynch_commands")
+ ModuleAsynchCommands(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), Pipe(), AsynchCommandsService(this, "asynch_commands"), reset(false)
{
me = this;
@@ -74,26 +108,40 @@ class ModuleAsynchCommands : public Module, public Pipe, public AsynchCommandsSe
main_mutex.Lock();
- Implementation i[] = { I_OnPreCommand };
- ModuleManager::Attach(i, this, 1);
+ Implementation i[] = { I_OnObjectDestroy, I_OnPreCommand };
+ ModuleManager::Attach(i, this, 2);
ModuleManager::RegisterService(this);
}
+
+ void OnObjectDestroy(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->source.ci == b))
+ cm->Destroy();
+ }
+
+ if (current_command == NULL)
+ this->Reset();
+ else
+ this->reset = true;
+ }
EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> &params)
{
- AsynchCommandMutex *cm = new AsynchCommandMutex();
+ AsynchCommandMutex *cm = new AsynchCommandMutex(source, command, params);
+
try
{
- cm->mutex.Lock();
- cm->command = command;
- cm->source = source;
- cm->params = params;
-
// Give processing to the command thread
Log(LOG_DEBUG_2) << "Waiting for command thread " << cm->command->name << " from " << source.u->nick;
+ current_command = cm;
threadEngine.Start(cm);
main_mutex.Lock();
+ current_command = NULL;
return EVENT_STOP;
}
@@ -108,9 +156,9 @@ class ModuleAsynchCommands : public Module, public Pipe, public AsynchCommandsSe
void OnNotify()
{
- for (std::list<CommandMutex *>::iterator it = commands.begin(), it_end = commands.end(); it != it_end; ++it)
+ for (std::list<CommandMutex *>::iterator it = commands.begin(), it_end = commands.end(); it != it_end;)
{
- CommandMutex *cm = *it;
+ AsynchCommandMutex *cm = debug_cast<AsynchCommandMutex *>(*it++);
// Thread engine will pick this up later
if (cm->GetExitState() || !cm->processing)
@@ -120,11 +168,30 @@ class ModuleAsynchCommands : public Module, public Pipe, public AsynchCommandsSe
current_command = cm;
// Unlock to give processing back to the command thread
- cm->mutex.Unlock();
+ 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;
+
+ if (this->reset)
+ {
+ this->Reset();
+ return this->OnNotify();
+ }
}
}
diff --git a/modules/extra/m_mysql.cpp b/modules/extra/m_mysql.cpp
index 12b4dbcc5..7ef4243e6 100644
--- a/modules/extra/m_mysql.cpp
+++ b/modules/extra/m_mysql.cpp
@@ -50,16 +50,13 @@ class MySQLResult : public SQLResult
public:
MySQLResult(const Anope::string &q, MYSQL_RES *r) : SQLResult(q), res(r)
{
- if (!res)
- return;
+ unsigned num_fields = res ? mysql_num_fields(res) : 0;
- unsigned num_fields = mysql_num_fields(res);
+ Log(LOG_DEBUG) << "SQL query " << q << " returned " << num_fields << " fields";
if (!num_fields)
return;
- Log(LOG_DEBUG) << "SQL query returned " << num_fields << " fields";
-
for (MYSQL_ROW row; (row = mysql_fetch_row(res));)
{
MYSQL_FIELD *fields = mysql_fetch_fields(res);
@@ -268,6 +265,8 @@ class ModuleSQL : public Module
}
this->DThread->Unlock();
+
+ this->SQLPipe->OnNotify();
}
};
@@ -398,8 +397,11 @@ void DispatcherThread::Run()
void MySQLPipe::OnNotify()
{
me->DThread->Lock();
+ std::deque<QueryResult> finishedRequests = me->FinishedRequests;
+ me->FinishedRequests.clear();
+ me->DThread->Unlock();
- for (std::deque<QueryResult>::const_iterator it = me->FinishedRequests.begin(), it_end = me->FinishedRequests.end(); it != it_end; ++it)
+ for (std::deque<QueryResult>::const_iterator it = finishedRequests.begin(), it_end = finishedRequests.end(); it != it_end; ++it)
{
const QueryResult &qr = *it;
@@ -411,9 +413,6 @@ void MySQLPipe::OnNotify()
else
qr.sqlinterface->OnError(qr.result);
}
- me->FinishedRequests.clear();
-
- me->DThread->Unlock();
}
MODULE_INIT(ModuleSQL)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 617029a9b..f606beff6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,5 @@
# Find all the *.cpp files within the current source directory, and sort the list
-file(GLOB SRC_SRCS_CPP RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
-set(SRC_SRCS ${SRC_SRCS_C} ${SRC_SRCS_CPP})
+file(GLOB SRC_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
# If using Windows, add the windows.cpp, the win32 threading engine, and the socket engine to the list
if(WIN32)
diff --git a/src/base.cpp b/src/base.cpp
index d0eff0beb..537770bcd 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -1,4 +1,5 @@
#include "services.h"
+#include "modules.h"
Base::Base()
{
@@ -10,6 +11,8 @@ Base::~Base()
{
(*it)->Invalidate();
}
+
+ FOREACH_MOD(I_OnObjectDestroy, OnObjectDestroy(this));
}
void Base::AddReference(dynamic_reference_base *r)
diff --git a/src/bots.cpp b/src/bots.cpp
index 4f3ed76c9..254e987a1 100644
--- a/src/bots.cpp
+++ b/src/bots.cpp
@@ -111,6 +111,10 @@ BotInfo::~BotInfo()
}
}
+void BotInfo::SetIdent(const Anope::string &sident)
+{
+ this->ident = sident;
+}
void BotInfo::SetNewNick(const Anope::string &newnick)
{
diff --git a/src/command.cpp b/src/command.cpp
index ddf9a6622..cc23a72a5 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -8,26 +8,6 @@
#include "services.h"
#include "modules.h"
-CommandSource::~CommandSource()
-{
- for (std::list<Anope::string>::iterator it = this->reply.begin(), it_end = this->reply.end(); it != it_end; ++it)
- {
- const Anope::string &message = *it;
-
- // Send to the user if the reply is more than one line
- if (!this->fantasy || !this->ci || this->reply.size() > 1)
- u->SendMessage(this->service, message);
- else if (this->ci->botflags.HasFlag(BS_MSG_PRIVMSG))
- ircdproto->SendPrivmsg(this->service, this->ci->name, message.c_str());
- else if (this->ci->botflags.HasFlag(BS_MSG_NOTICE))
- ircdproto->SendNotice(this->service, this->ci->name, message.c_str());
- else if (this->ci->botflags.HasFlag(BS_MSG_NOTICEOPS))
- ircdproto->SendNoticeChanops(this->service, this->ci->c, message.c_str());
- else
- u->SendMessage(this->service, message);
- }
-}
-
void CommandSource::Reply(const char *message, ...)
{
va_list args;
@@ -52,6 +32,26 @@ void CommandSource::Reply(const Anope::string &message)
this->reply.push_back(tok);
}
+void CommandSource::DoReply()
+{
+ for (std::list<Anope::string>::iterator it = this->reply.begin(), it_end = this->reply.end(); it != it_end; ++it)
+ {
+ const Anope::string &message = *it;
+
+ // Send to the user if the reply is more than one line
+ if (!this->fantasy || !this->ci || this->reply.size() > 1)
+ u->SendMessage(this->service, message);
+ else if (this->ci->botflags.HasFlag(BS_MSG_PRIVMSG))
+ ircdproto->SendPrivmsg(this->service, this->ci->name, message.c_str());
+ else if (this->ci->botflags.HasFlag(BS_MSG_NOTICE))
+ ircdproto->SendNotice(this->service, this->ci->name, message.c_str());
+ else if (this->ci->botflags.HasFlag(BS_MSG_NOTICEOPS))
+ ircdproto->SendNoticeChanops(this->service, this->ci->c, message.c_str());
+ else
+ u->SendMessage(this->service, message);
+ }
+}
+
Command::Command(const Anope::string &sname, size_t min_params, size_t max_params, const Anope::string &spermission) : Flags<CommandFlag>(CommandFlagStrings), MaxParams(max_params), MinParams(min_params), name(sname), permission(spermission)
{
this->module = NULL;
diff --git a/src/commands.cpp b/src/commands.cpp
index e3a52a503..6944ac31e 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -168,6 +168,8 @@ void mod_run_cmd(BotInfo *bi, User *u, Command *c, const Anope::string &command,
{
FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, c, params));
}
+
+ source.DoReply();
}
/**
diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp
index 2c716acf6..d530b6e46 100644
--- a/src/modulemanager.cpp
+++ b/src/modulemanager.cpp
@@ -400,7 +400,7 @@ void ModuleManager::UnloadAll()
Module *m = *it++;
if (static_cast<MODType>(i) == m->type)
- DeleteModule(m);
+ UnloadModule(m, NULL);
}
}
}
diff --git a/src/threadengines/threadengine_pthread.cpp b/src/threadengines/threadengine_pthread.cpp
index e8242bb82..f28c43846 100644
--- a/src/threadengines/threadengine_pthread.cpp
+++ b/src/threadengines/threadengine_pthread.cpp
@@ -43,6 +43,7 @@ void Thread::Join()
*/
void Thread::Exit()
{
+ this->SetExitState();
pthread_exit(0);
}
diff --git a/src/threadengines/threadengine_win32.cpp b/src/threadengines/threadengine_win32.cpp
index 218f711c4..adefab800 100644
--- a/src/threadengines/threadengine_win32.cpp
+++ b/src/threadengines/threadengine_win32.cpp
@@ -35,6 +35,7 @@ void Thread::Join()
*/
void Thread::Exit()
{
+ this->SetExitState();
ExitThread(0);
}