diff options
author | Adam <Adam@anope.org> | 2011-08-05 05:35:31 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2011-08-05 05:35:31 -0400 |
commit | e66063e6304538d34c40460ca0aa2be5ddb6bdec (patch) | |
tree | f50fe31097160f8f794669809e4f4ef87f477672 /modules/database/db_mysql_live.cpp | |
parent | 9ec18a3b020932eee6242c878149c484f49b13cb (diff) |
Rewrote the example configurations and split them
up into seperate files for each pseudo client.
Also reorganized how the modules are stored, and
made most of the old "extra" modules "core"
Diffstat (limited to 'modules/database/db_mysql_live.cpp')
-rw-r--r-- | modules/database/db_mysql_live.cpp | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/modules/database/db_mysql_live.cpp b/modules/database/db_mysql_live.cpp new file mode 100644 index 000000000..ecfdc70d1 --- /dev/null +++ b/modules/database/db_mysql_live.cpp @@ -0,0 +1,287 @@ +#include "module.h" +#include "../extra/async_commands.h" +#include "../extra/sql.h" + +class SQLCache : public Timer +{ + typedef std::map<Anope::string, time_t, std::less<ci::string> > cache_map; + cache_map cache; + public: + + SQLCache() : Timer(300, Anope::CurTime, true) { } + + bool Check(const Anope::string &item) + { + cache_map::iterator it = this->cache.find(item); + if (it != this->cache.end() && Anope::CurTime - it->second < 5) + return true; + + this->cache[item] = Anope::CurTime; + return false; + } + + void Tick(time_t) + { + for (cache_map::iterator it = this->cache.begin(), next_it; it != this->cache.end(); it = next_it) + { + next_it = it; + ++next_it; + + if (Anope::CurTime - it->second > 5) + this->cache.erase(it); + } + } +}; + +static void ChanInfoUpdate(const SQLResult &res) +{ + try + { + ChannelInfo *ci = cs_findchan(res.Get(0, "name")); + if (!ci) + ci = new ChannelInfo(res.Get(0, "name")); + ci->SetFounder(findcore(res.Get(0, "founder"))); + ci->successor = findcore(res.Get(0, "successor")); + ci->desc = res.Get(0, "descr"); + ci->time_registered = convertTo<time_t>(res.Get(0, "time_registered")); + ci->ClearFlags(); + ci->FromString(BuildStringVector(res.Get(0, "flags"))); + ci->bantype = convertTo<int>(res.Get(0, "bantype")); + ci->memos.memomax = convertTo<unsigned>(res.Get(0, "memomax")); + + if (res.Get(0, "botnick").equals_cs(ci->bi ? ci->bi->nick : "") == false) + { + if (ci->bi) + ci->bi->UnAssign(NULL, ci); + BotInfo *bi = findbot(res.Get(0, "botnick")); + if (bi) + bi->Assign(NULL, ci); + } + + ci->capsmin = convertTo<int16>(res.Get(0, "capsmin")); + ci->capspercent = convertTo<int16>(res.Get(0, "capspercent")); + ci->floodlines = convertTo<int16>(res.Get(0, "floodlines")); + ci->floodsecs = convertTo<int16>(res.Get(0, "floodsecs")); + ci->repeattimes = convertTo<int16>(res.Get(0, "repeattimes")); + + if (ci->c) + check_modes(ci->c); + } + catch (const SQLException &ex) + { + Log(LOG_DEBUG) << ex.GetReason(); + } + catch (const ConvertException &) { } +} + +static void NickInfoUpdate(const SQLResult &res) +{ + try + { + NickCore *nc = findcore(res.Get(0, "display")); + if (!nc) + return; + NickAlias *na = findnick(res.Get(0, "nick")); + if (!na) + na = new NickAlias(res.Get(0, "nick"), nc); + + na->last_quit = res.Get(0, "last_quit"); + na->last_realname = res.Get(0, "last_realname"); + na->last_usermask = res.Get(0, "last_usermask"); + na->time_registered = convertTo<time_t>(res.Get(0, "time_registered")); + na->last_seen = convertTo<time_t>(res.Get(0, "last_seen")); + na->ClearFlags(); + na->FromString(BuildStringVector(res.Get(0, "flags"))); + + if (na->nc != nc) + { + std::list<NickAlias *>::iterator it = std::find(na->nc->aliases.begin(), na->nc->aliases.end(), na); + if (it != na->nc->aliases.end()) + na->nc->aliases.erase(it); + + na->nc = nc; + na->nc->aliases.push_back(na); + } + } + catch (const SQLException &ex) + { + Log(LOG_DEBUG) << ex.GetReason(); + } + catch (const ConvertException &) { } +} + +static void NickCoreUpdate(const SQLResult &res) +{ + try + { + NickCore *nc = findcore(res.Get(0, "display")); + if (!nc) + nc = new NickCore(res.Get(0, "display")); + + nc->pass = res.Get(0, "pass"); + nc->email = res.Get(0, "email"); + nc->greet = res.Get(0, "greet"); + nc->ClearFlags(); + nc->FromString(BuildStringVector(res.Get(0, "flags"))); + nc->language = res.Get(0, "language"); + } + catch (const SQLException &ex) + { + Log(LOG_DEBUG) << ex.GetReason(); + } + catch (const ConvertException &) { } +} + +class MySQLLiveModule : public Module +{ + service_reference<SQLProvider> SQL; + service_reference<AsynchCommandsService> ACS; + + SQLCache chan_cache, nick_cache, core_cache; + + SQLResult RunQuery(const SQLQuery &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; + } + + 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") + { + Implementation i[] = { I_OnFindChan, I_OnFindNick, I_OnFindCore, I_OnShutdown }; + ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + } + + void OnShutdown() + { + Implementation i[] = { I_OnFindChan, I_OnFindNick, I_OnFindCore }; + for (size_t j = 0; j < 3; ++j) + ModuleManager::Detach(i[j], this); + } + + void OnFindChan(const Anope::string &chname) + { + if (chan_cache.Check(chname)) + return; + + try + { + 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); + } + } + catch (const SQLException &ex) + { + Log(LOG_DEBUG) << "OnFindChan: " << ex.GetReason(); + } + } + + void OnFindNick(const Anope::string &nick) + { + if (nick_cache.Check(nick)) + return; + + try + { + 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); + } + } + catch (const SQLException &ex) + { + Log(LOG_DEBUG) << "OnFindNick: " << ex.GetReason(); + } + } + + void OnFindCore(const Anope::string &nick) + { + if (core_cache.Check(nick)) + return; + + try + { + 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); + } + } + catch (const SQLException &ex) + { + Log(LOG_DEBUG) << "OnFindCore: " << ex.GetReason(); + } + } +}; + +MODULE_INIT(MySQLLiveModule) |