1
0
mirror of https://github.com/anope/anope.git synced 2026-06-24 09:36:37 +02:00
Files
anope/modules/database/db_sql_live_write.cpp
T
2011-11-08 17:29:16 -05:00

248 lines
5.6 KiB
C++

#include "module.h"
#include "../extra/sql.h"
class SQLCache : public Timer
{
typedef std::map<Anope::string, time_t, ci::less> 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 Anope::string &name, const SQLResult &res)
{
ChannelInfo *ci = cs_findchan(name);
if (res.Rows() == 0)
{
delete ci;
return;
}
try
{
if (!ci)
ci = new ChannelInfo(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(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_t>(res.Get(0, "capsmin"));
ci->capspercent = convertTo<int16_t>(res.Get(0, "capspercent"));
ci->floodlines = convertTo<int16_t>(res.Get(0, "floodlines"));
ci->floodsecs = convertTo<int16_t>(res.Get(0, "floodsecs"));
ci->repeattimes = convertTo<int16_t>(res.Get(0, "repeattimes"));
if (ci->c)
check_modes(ci->c);
}
catch (const SQLException &ex)
{
Log() << ex.GetReason();
}
catch (const ConvertException &) { }
}
static void NickInfoUpdate(const Anope::string &name, const SQLResult &res)
{
NickAlias *na = findnick(name);
if (res.Rows() == 0)
{
delete na;
return;
}
try
{
NickCore *nc = findcore(res.Get(0, "display"));
if (!nc)
return;
if (!na)
na = new NickAlias(name, 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->last_realhost = res.Get(0, "last_realhost");
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(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() << ex.GetReason();
}
catch (const ConvertException &) { }
}
static void NickCoreUpdate(const Anope::string &name, const SQLResult &res)
{
NickCore *nc = findcore(name);
if (res.Rows() == 0)
{
delete nc;
return;
}
try
{
if (!nc)
nc = new NickCore(name);
nc->pass = res.Get(0, "pass");
nc->email = res.Get(0, "email");
nc->greet = res.Get(0, "greet");
nc->ClearFlags();
nc->FromString(res.Get(0, "flags"));
nc->language = res.Get(0, "language");
}
catch (const SQLException &ex)
{
Log() << ex.GetReason();
}
catch (const ConvertException &) { }
}
class MySQLLiveModule : public Module
{
service_reference<SQLProvider, Base> SQL;
SQLCache chan_cache, nick_cache, core_cache;
SQLResult RunQuery(const SQLQuery &query)
{
if (!this->SQL)
throw SQLException("Unable to locate SQL reference, is db_sql loaded and configured correctly?");
SQLResult res = SQL->RunQuery(query);
if (!res.GetError().empty())
throw SQLException(res.GetError());
return res;
}
public:
MySQLLiveModule(const Anope::string &modname, const Anope::string &creator) :
Module(modname, creator, DATABASE), SQL("")
{
Implementation i[] = { I_OnReload, I_OnFindChan, I_OnFindNick, I_OnFindCore, I_OnShutdown };
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
}
void OnReload()
{
ConfigReader config;
Anope::string engine = config.ReadValue("db_sql", "engine", "", 0);
this->SQL = engine;
}
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 `ChannelInfo` WHERE `name` = @name@");
query.setValue("name", chname);
SQLResult res = this->RunQuery(query);
ChanInfoUpdate(chname, 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 `NickAlias` WHERE `nick` = @nick@");
query.setValue("nick", nick);
SQLResult res = this->RunQuery(query);
NickInfoUpdate(nick, 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 `NickCore` WHERE `display` = @display@");
query.setValue("display", nick);
SQLResult res = this->RunQuery(query);
NickCoreUpdate(nick, res);
}
catch (const SQLException &ex)
{
Log(LOG_DEBUG) << "OnFindCore: " << ex.GetReason();
}
}
};
MODULE_INIT(MySQLLiveModule)