summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2016-10-15 16:25:57 -0400
committerAdam <Adam@anope.org>2016-10-15 16:25:57 -0400
commit1ba242179fee46583098f48421af39ce9a8985a1 (patch)
treea276cd7bd53e7270c86ab3744bd6a568a016501b
parent696239e93391f3dfd6459857fb02a6006048093a (diff)
Various improvements/bugfixes to extdb stuff
-rw-r--r--include/config.h8
-rw-r--r--include/modules/sql.h4
-rw-r--r--include/serialize.h76
-rw-r--r--include/users.h1
-rw-r--r--include/xline.h2
-rw-r--r--modules/botserv/assign.cpp4
-rw-r--r--modules/botserv/bot.cpp26
-rw-r--r--modules/botserv/info.cpp7
-rw-r--r--modules/botserv/set.cpp2
-rw-r--r--modules/chanserv/main/channeltype.cpp8
-rw-r--r--modules/chanserv/main/channeltype.h2
-rw-r--r--modules/chanserv/main/chanserv.cpp16
-rw-r--r--modules/database/old.cpp4
-rw-r--r--modules/database/sql.cpp184
-rw-r--r--modules/extra/mysql.cpp82
-rw-r--r--modules/extra/sqlite.cpp124
-rw-r--r--modules/nickserv/cert.cpp19
-rw-r--r--modules/nickserv/main/accounttype.cpp13
-rw-r--r--modules/nickserv/main/accounttype.h2
-rw-r--r--modules/nickserv/main/nickserv.cpp9
-rw-r--r--modules/nickserv/main/nicktype.cpp9
-rw-r--r--modules/nickserv/main/nicktype.h2
-rw-r--r--src/bots.cpp21
-rw-r--r--src/config.cpp169
-rw-r--r--src/init.cpp3
-rw-r--r--src/service_manager.cpp8
-rw-r--r--src/xline.cpp3
27 files changed, 426 insertions, 382 deletions
diff --git a/include/config.h b/include/config.h
index dccadbe79..b6b36b726 100644
--- a/include/config.h
+++ b/include/config.h
@@ -102,8 +102,9 @@ namespace Configuration
struct Usermode;
struct Channelmode;
- struct CoreExport Conf : Block
+ class CoreExport Conf : public Block
{
+ public:
/* options:readtimeout */
time_t ReadTimeout;
/* options:useprivmsg */
@@ -162,6 +163,11 @@ namespace Configuration
ServiceBot *GetClient(const Anope::string &name);
Block *GetCommand(CommandSource &);
+
+ void LoadBots();
+ void ApplyBots();
+
+ void LoadOpers();
};
struct Uplink
diff --git a/include/modules/sql.h b/include/modules/sql.h
index 2e84db152..6770f407e 100644
--- a/include/modules/sql.h
+++ b/include/modules/sql.h
@@ -202,8 +202,8 @@ namespace SQL
virtual std::vector<Query> InitSchema(const Anope::string &prefix) anope_abstract;
virtual std::vector<Query> Replace(const Anope::string &table, const Query &, const std::set<Anope::string> &) anope_abstract;
- virtual std::vector<Query> CreateTable(const Anope::string &prefix, const Anope::string &table) anope_abstract;
- virtual std::vector<Query> AlterTable(const Anope::string &, const Anope::string &table, const Anope::string &field, bool object) anope_abstract;
+ virtual std::vector<Query> CreateTable(const Anope::string &prefix, Serialize::TypeBase *) anope_abstract;
+ virtual std::vector<Query> AlterTable(const Anope::string &, Serialize::TypeBase *, Serialize::FieldBase *) anope_abstract;
virtual std::vector<Query> CreateIndex(const Anope::string &table, const Anope::string &field) anope_abstract;
virtual Query BeginTransaction() anope_abstract;
diff --git a/include/serialize.h b/include/serialize.h
index 1d0fb9400..8f35e61c6 100644
--- a/include/serialize.h
+++ b/include/serialize.h
@@ -49,6 +49,9 @@ namespace Serialize
inline T GetObject();
template<typename T>
+ inline std::vector<T> GetObjects_(TypeBase *);
+
+ template<typename T>
inline std::vector<T> GetObjects(const Anope::string &name);
template<typename T>
@@ -235,29 +238,6 @@ class CoreExport Serialize::TypeBase : public Service
*/
const Anope::string &GetName() { return this->name; }
- /**
- * Get all objects of the given type
- */
- template<typename T>
- std::vector<T> List()
- {
- std::vector<ID> ids;
- EventReturn result = EventManager::Get()->Dispatch(&Event::SerializeEvents::OnSerializeList, this, ids);
- if (result == EVENT_ALLOW)
- {
- std::vector<T> o;
- for (ID id : ids)
- {
- Object *s = Require(id);
- if (s)
- o.push_back(anope_dynamic_static_cast<T>(s));
- }
- return o;
- }
-
- return GetObjects<T>();
- }
-
/** Create a new object of this type.
*/
virtual Object *Create() anope_abstract;
@@ -306,7 +286,10 @@ class Serialize::Type : public Base
return new T(this, id);
if (s->GetSerializableType() != this)
+ {
+ Log(LOG_DEBUG) << "Mismatch for required id " << id << ", is of type " << s->GetSerializableType()->GetName() << " but wants " << this->GetName();
return nullptr;
+ }
return static_cast<T *>(s);
}
@@ -387,6 +370,8 @@ class Serialize::FieldBase : public Service
*/
bool depends;
+ bool object = false;
+
FieldBase(Module *, const Anope::string &, const Anope::string &, bool);
virtual ~FieldBase();
void Unregister();
@@ -592,7 +577,10 @@ class Serialize::Field : public CommonFieldBase<TypeImpl, T>
// module returned us data, so we unserialize it
T t2 = this->Unserialize(value);
+ // should cache the default value somehow, but can't differentiate not cached from cached and default
+
// Cache
+ OnSet(s, t2);
this->Set_(s, t2);
return t2;
@@ -609,11 +597,18 @@ class Serialize::Field : public CommonFieldBase<TypeImpl, T>
SetField(this->Upcast(s), value);
}
- virtual void SetField(TypeImpl *s, const T &value)
+ /**
+ * Override to hook to changes in the internally
+ * cached value
+ */
+ virtual void OnSet(TypeImpl *s, const T &value) { }
+
+ void SetField(TypeImpl *s, const T &value)
{
Anope::string strvalue = this->Serialize(value);
EventManager::Get()->Dispatch(&Event::SerializeEvents::OnSerializeSet, s, this, strvalue);
+ OnSet(s, value);
this->Set_(s, value);
}
@@ -697,10 +692,12 @@ class Serialize::ObjectField : public CommonFieldBase<TypeImpl, T>
public:
ObjectField(TypeBase *t, const Anope::string &n, bool d = false) : CommonFieldBase<TypeImpl, T>(t, n, d)
{
+ this->object = true;
}
ObjectField(TypeBase *t, const Anope::string &n, T TypeImpl::*field, bool d = false) : CommonFieldBase<TypeImpl, T>(t, n, field, d)
{
+ this->object = true;
}
T GetField(TypeImpl *s)
@@ -723,6 +720,7 @@ class Serialize::ObjectField : public CommonFieldBase<TypeImpl, T>
T t2 = result == EVENT_ALLOW ? static_cast<T>(base->Require(sid)) : nullptr;
+ OnSet(s, t2);
this->Set_(s, t2);
return t2;
@@ -739,7 +737,9 @@ class Serialize::ObjectField : public CommonFieldBase<TypeImpl, T>
SetField(this->Upcast(s), value);
}
- virtual void SetField(TypeImpl *s, T value)
+ virtual void OnSet(TypeImpl *s, T value) { }
+
+ void SetField(TypeImpl *s, T value)
{
EventManager::Get()->Dispatch(&Event::SerializeEvents::OnSerializeSetSerializable, s, this, value);
@@ -747,6 +747,7 @@ class Serialize::ObjectField : public CommonFieldBase<TypeImpl, T>
if (old != nullptr && *old != nullptr)
s->RemoveEdge(*old, this);
+ OnSet(s, value);
this->Set_(s, value);
if (value != nullptr)
@@ -812,13 +813,34 @@ T Serialize::GetObject()
}
template<typename T>
+std::vector<T> Serialize::GetObjects_(TypeBase *type)
+{
+ std::vector<T> o;
+ std::vector<ID> ids;
+ EventReturn result = EventManager::Get()->Dispatch(&Event::SerializeEvents::OnSerializeList, type, ids);
+ if (result == EVENT_ALLOW)
+ {
+ for (ID id : ids)
+ {
+ Object *s = type->Require(id);
+ if (s)
+ o.push_back(anope_dynamic_static_cast<T>(s));
+ }
+ return o;
+ }
+
+ std::transform(type->objects.begin(), type->objects.end(), std::back_inserter(o), [](Object *e) { return anope_dynamic_static_cast<T>(e); });
+ return o;
+}
+
+template<typename T>
std::vector<T> Serialize::GetObjects(const Anope::string &name)
{
std::vector<T> objs;
for (TypeBase *t : GetTypes(name))
- for (Object *s : t->objects)
- objs.push_back(anope_dynamic_static_cast<T>(s));
+ for (T obj : GetObjects_<T>(t))
+ objs.push_back(obj);
return objs;
}
diff --git a/include/users.h b/include/users.h
index dacb7045e..be4ee2a39 100644
--- a/include/users.h
+++ b/include/users.h
@@ -38,7 +38,6 @@ extern CoreExport int OperCount;
enum class UserType
{
USER,
- //LOCAL_USER,
BOT
};
diff --git a/include/xline.h b/include/xline.h
index 87b64d1da..05ddbe2d3 100644
--- a/include/xline.h
+++ b/include/xline.h
@@ -87,7 +87,7 @@ class XLineType : public Serialize::Type<XLine>
{
using Serialize::Field<XLine, Anope::string>::Field;
- void SetField(XLine *s, const Anope::string &value) override;
+ void OnSet(XLine *s, const Anope::string &value) override;
} mask;
Serialize::Field<XLine, Anope::string> by, reason, id;
Serialize::Field<XLine, time_t> created, expires;
diff --git a/modules/botserv/assign.cpp b/modules/botserv/assign.cpp
index eb6b8da10..a26b869fe 100644
--- a/modules/botserv/assign.cpp
+++ b/modules/botserv/assign.cpp
@@ -67,7 +67,7 @@ class CommandBSAssign : public Command
return;
}
- if (bi->bi->GetOperOnly() && !source.HasPriv("botserv/administration"))
+ if (bi->bi && bi->bi->GetOperOnly() && !source.HasPriv("botserv/administration"))
{
source.Reply(_("Access denied. Bot \002{0}\002 is for operators only."), bi->nick);
return;
@@ -265,7 +265,7 @@ class BSAssign : public Module
return;
}
- if (bi->bi->GetOperOnly() && !source->HasPriv("botserv/administration"))
+ if (bi->bi && bi->bi->GetOperOnly() && !source->HasPriv("botserv/administration"))
{
targ->SendMessage(bi, _("Access denied. Bot \002{0}\002 is for operators only."), bi->nick);
return;
diff --git a/modules/botserv/bot.cpp b/modules/botserv/bot.cpp
index c93c4cf50..2e33b7ccb 100644
--- a/modules/botserv/bot.cpp
+++ b/modules/botserv/bot.cpp
@@ -93,6 +93,16 @@ class CommandBSBot : public Command
ServiceBot *bi = new ServiceBot(nick, user, host, real);
+ BotInfo *botinfo = Serialize::New<BotInfo *>();
+ botinfo->SetNick(nick);
+ botinfo->SetUser(user);
+ botinfo->SetHost(host);
+ botinfo->SetRealName(real);
+ botinfo->SetCreated(Anope::CurTime);
+
+ bi->bi = botinfo;
+ botinfo->bot = bi;
+
Log(LOG_ADMIN, source, this) << "ADD " << bi->GetMask() << " " << bi->realname;
source.Reply(_("\002{0}!{1}@{2}\002 (\002{3}\002) added to the bot list."), bi->nick, bi->GetIdent(), bi->host, bi->realname);
@@ -121,7 +131,7 @@ class CommandBSBot : public Command
return;
}
- if (bi->bi->conf)
+ if (bi->bi && bi->bi->conf)
{
source.Reply(_("Bot \002{0}\002 is not changeable because it is configured in services configuration."), bi->nick.c_str());
return;
@@ -226,23 +236,27 @@ class CommandBSBot : public Command
if (!nick.equals_cs(bi->nick))
{
bi->SetNewNick(nick);
- bi->bi->SetNick(nick);
+ if (bi->bi != nullptr)
+ bi->bi->SetNick(nick);
}
if (!user.equals_cs(bi->GetIdent()))
{
bi->SetIdent(user);
- bi->bi->SetUser(user);
+ if (bi->bi != nullptr)
+ bi->bi->SetUser(user);
}
if (!host.equals_cs(bi->host))
{
bi->host = host;
- bi->bi->SetHost(host);
+ if (bi->bi != nullptr)
+ bi->bi->SetHost(host);
}
if (real.equals_cs(bi->realname))
{
bi->realname = real;
- bi->bi->SetRealName(real);
+ if (bi->bi != nullptr)
+ bi->bi->SetRealName(real);
}
if (!user.empty())
@@ -271,7 +285,7 @@ class CommandBSBot : public Command
return;
}
- if (bi->bi->conf)
+ if (bi->bi && bi->bi->conf)
{
source.Reply(_("Bot \002{0}\002 is can not be deleted because it is configured in services configuration."), bi->nick);
return;
diff --git a/modules/botserv/info.cpp b/modules/botserv/info.cpp
index 94b1bbbd7..4de86643f 100644
--- a/modules/botserv/info.cpp
+++ b/modules/botserv/info.cpp
@@ -41,8 +41,11 @@ class CommandBSInfo : public Command
source.Reply(_("Information for bot \002%s\002:"), bi->nick.c_str());
info[_("Mask")] = bi->GetIdent() + "@" + bi->host;
info[_("Real name")] = bi->realname;
- info[_("Created")] = Anope::strftime(bi->bi->GetCreated(), source.GetAccount());
- info[_("Options")] = bi->bi->GetOperOnly() ? _("Private") : _("None");
+ if (bi->bi)
+ {
+ info[_("Created")] = Anope::strftime(bi->bi->GetCreated(), source.GetAccount());
+ info[_("Options")] = bi->bi->GetOperOnly() ? _("Private") : _("None");
+ }
info[_("Used on")] = stringify(bi->GetChannelCount()) + " channel(s)";
EventManager::Get()->Dispatch(&Event::ServiceBotEvent::OnServiceBot, source, bi, ci, info);
diff --git a/modules/botserv/set.cpp b/modules/botserv/set.cpp
index 47c5337d2..bb432e3f0 100644
--- a/modules/botserv/set.cpp
+++ b/modules/botserv/set.cpp
@@ -174,7 +174,7 @@ class CommandBSSetPrivate : public Command
source.Reply(_("Services are in read-only mode. Any changes made may not persist."));
ServiceBot *bi = ServiceBot::Find(nick, true);
- if (bi == NULL)
+ if (bi == NULL || !bi->bi)
{
source.Reply(_("Bot \002{0}\002 does not exist."), nick);
return;
diff --git a/modules/chanserv/main/channeltype.cpp b/modules/chanserv/main/channeltype.cpp
index fa5e03e4c..37c290ef1 100644
--- a/modules/chanserv/main/channeltype.cpp
+++ b/modules/chanserv/main/channeltype.cpp
@@ -37,12 +37,12 @@ ChannelType::ChannelType(Module *me) : Serialize::Type<ChannelImpl>(me)
}
-void ChannelType::Name::SetField(ChannelImpl *c, const Anope::string &value)
+void ChannelType::Name::OnSet(ChannelImpl *c, const Anope::string &value)
{
ChanServ::registered_channel_map& map = ChanServ::service->GetChannels();
- map.erase(GetField(c));
-
- Serialize::Field<ChannelImpl, Anope::string>::SetField(c, value);
+ Anope::string *old = this->Get_(c);
+ if (old != nullptr)
+ map.erase(*old);
map[value] = c;
}
diff --git a/modules/chanserv/main/channeltype.h b/modules/chanserv/main/channeltype.h
index 95158427a..1f1c92201 100644
--- a/modules/chanserv/main/channeltype.h
+++ b/modules/chanserv/main/channeltype.h
@@ -27,7 +27,7 @@ class ChannelType : public Serialize::Type<ChannelImpl>
{
using Serialize::Field<ChannelImpl, Anope::string>::Field;
- void SetField(ChannelImpl *c, const Anope::string &value) override;
+ void OnSet(ChannelImpl *c, const Anope::string &value) override;
} name;
Serialize::Field<ChannelImpl, Anope::string> desc;
Serialize::Field<ChannelImpl, time_t> time_registered;
diff --git a/modules/chanserv/main/chanserv.cpp b/modules/chanserv/main/chanserv.cpp
index ec2e8a623..dc44173a0 100644
--- a/modules/chanserv/main/chanserv.cpp
+++ b/modules/chanserv/main/chanserv.cpp
@@ -322,7 +322,7 @@ class ChanServCore : public Module
{
::Log(LOG_NORMAL, "chanserv/drop", ChanServ) << "Deleting channel " << ci->GetName() << " owned by deleted nick " << nc->GetDisplay();
- delete ci;
+ ci->Delete();
continue;
}
}
@@ -330,6 +330,7 @@ class ChanServCore : public Module
if (ci->GetSuccessor() == nc)
ci->SetSuccessor(NULL);
+#warning "these arent necessary?"
/* are these necessary? */
for (unsigned j = 0; j < ci->GetAccessCount(); ++j)
{
@@ -338,7 +339,7 @@ class ChanServCore : public Module
if (anc && anc == nc)
{
- delete ca;
+ ca->Delete();
break;
}
}
@@ -348,7 +349,7 @@ class ChanServCore : public Module
AutoKick *ak = ci->GetAkick(j);
if (ak->GetAccount() == nc)
{
- delete ak;
+ ak->Delete();
break;
}
}
@@ -359,6 +360,7 @@ class ChanServCore : public Module
{
/* remove access entries that are this channel */
+#warning "also not necessary?"
for (ChanServ::Channel *c : ci->GetRefs<ChanServ::Channel *>())
{
for (unsigned j = 0; j < c->GetAccessCount(); ++j)
@@ -367,7 +369,7 @@ class ChanServCore : public Module
if (a->Mask().equals_ci(ci->GetName()))
{
- delete a;
+ a->Delete();
break;
}
}
@@ -465,7 +467,7 @@ class ChanServCore : public Module
if (!chanserv_expire || Anope::NoExpire || Anope::ReadOnly)
return;
- for (ChanServ::Channel *ci : channel_type.List<ChanServ::Channel *>())
+ for (ChanServ::Channel *ci : Serialize::GetObjects<ChanServ::Channel *>())
{
bool expire = false;
@@ -488,7 +490,7 @@ class ChanServCore : public Module
{
::Log(LOG_NORMAL, "chanserv/expire", ChanServ) << "Expiring channel " << ci->GetName() << " (founder: " << (ci->GetFounder() ? ci->GetFounder()->GetDisplay() : "(none)") << ")";
EventManager::Get()->Dispatch(&ChanServ::Event::ChanExpire::OnChanExpire, ci);
- delete ci;
+ ci->Delete();
}
}
}
@@ -505,7 +507,7 @@ class ChanServCore : public Module
void OnPreUplinkSync(Server *serv) override
{
/* Find all persistent channels and create them, as we are about to finish burst to our uplink */
- for (ChanServ::Channel *ci : channel_type.List<ChanServ::Channel *>())
+ for (ChanServ::Channel *ci : Serialize::GetObjects<ChanServ::Channel *>())
{
if (ci->HasFieldS("PERSIST"))
{
diff --git a/modules/database/old.cpp b/modules/database/old.cpp
index d63b2c4d8..61be22e9d 100644
--- a/modules/database/old.cpp
+++ b/modules/database/old.cpp
@@ -777,6 +777,10 @@ static void LoadBots()
ServiceBot *bi = ServiceBot::Find(nick, true);
if (!bi)
bi = new ServiceBot(nick, user, host, real);
+
+ if (bi->bi == nullptr)
+ bi->bi = Serialize::New<BotInfo *>();
+
bi->bi->SetCreated(created);
if (flags & OLD_BI_PRIVATE)
diff --git a/modules/database/sql.cpp b/modules/database/sql.cpp
index d7ed1963a..aa1c94bc0 100644
--- a/modules/database/sql.cpp
+++ b/modules/database/sql.cpp
@@ -22,7 +22,7 @@
using namespace SQL;
-class DBMySQL : public Module, public Pipe
+class DBSQL : public Module, public Pipe
, public EventHook<Event::SerializeEvents>
{
private:
@@ -58,8 +58,6 @@ class DBMySQL : public Module, public Pipe
SQL->RunQuery(q);
}
- Log(LOG_DEBUG_2) << query.Unsafe();
-
return SQL->RunQuery(query);
}
@@ -85,7 +83,7 @@ class DBMySQL : public Module, public Pipe
}
public:
- DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
+ DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
, EventHook<Event::SerializeEvents>(this)
{
}
@@ -129,10 +127,10 @@ class DBMySQL : public Module, public Pipe
StartTransaction();
- for (Query &q : SQL->CreateTable(prefix, type->GetName()))
+ for (Query &q : SQL->CreateTable(prefix, type))
Run(q);
- for (Query &q : SQL->AlterTable(prefix, type->GetName(), field->serialize_name, false))
+ for (Query &q : SQL->AlterTable(prefix, type, field))
Run(q);
for (const Query &q : SQL->CreateIndex(prefix + type->GetName(), field->serialize_name))
@@ -150,6 +148,7 @@ class DBMySQL : public Module, public Pipe
catch (const ConvertException &)
{
}
+
return EVENT_CONTINUE;
}
@@ -159,7 +158,7 @@ class DBMySQL : public Module, public Pipe
StartTransaction();
Query query = "SELECT `" + field->serialize_name + "` FROM `" + prefix + object->GetSerializableType()->GetName() + "` WHERE `id` = @id@";
- query.SetValue("id", object->id);
+ query.SetValue("id", object->id, false);
Result res = Run(query);
if (res.Rows() == 0)
@@ -169,6 +168,40 @@ class DBMySQL : public Module, public Pipe
return true;
}
+ void GetRefs(Serialize::Object *object, Serialize::TypeBase *type, std::vector<Serialize::Edge> &edges)
+ {
+ for (Serialize::FieldBase *field : type->GetFields())
+ {
+ if (field->object)
+ {
+ Anope::string table = prefix + type->GetName();
+
+ Query query = "SELECT " + table + ".id FROM " + table +
+ " INNER JOIN " + prefix + "objects AS o ON " +
+ table + "." + field->serialize_name + " = o.id "
+ "WHERE o.id = @id@";
+
+ query.SetValue("id", object->id, false);
+
+ Result res = Run(query);
+ for (int i = 0; i < res.Rows(); ++i)
+ {
+ Serialize::ID id = convertTo<Serialize::ID>(res.Get(i, "id"));
+
+ Serialize::Object *other = type->Require(id);
+ if (other == nullptr)
+ {
+ Log(LOG_DEBUG) << "Unable to require id " << id << " type " << type->GetName();
+ continue;
+ }
+
+ // other type, other field, direction
+ edges.emplace_back(other, field, false);
+ }
+ }
+ }
+ }
+
public:
EventReturn OnSerializeGet(Serialize::Object *object, Serialize::FieldBase *field, Anope::string &value) override
{
@@ -193,93 +226,16 @@ class DBMySQL : public Module, public Pipe
edges.clear();
- Query query;
- if (type)
- query = "SELECT field," + prefix + "edges.id,other_id,j1.type,j2.type AS other_type FROM `" + prefix + "edges` "
- "JOIN `" + prefix + "objects` AS j1 ON " + prefix + "edges.id = j1.id "
- "JOIN `" + prefix + "objects` AS j2 ON " + prefix + "edges.other_id = j2.id "
- "WHERE "
- " (" + prefix + "edges.id = @id@ AND j2.type = @other_type@) "
- "OR"
- " (other_id = @id@ AND j1.type = @other_type@)";
+ if (type == nullptr)
+ {
+ for (Serialize::TypeBase *type : Serialize::TypeBase::GetTypes())
+ GetRefs(object, type, edges);
+ }
else
- query = "SELECT field," + prefix + "edges.id,other_id,j1.type,j2.type AS other_type FROM `" + prefix + "edges` "
- "JOIN `" + prefix + "objects` AS j1 ON " + prefix + "edges.id = j1.id "
- "JOIN `" + prefix + "objects` AS j2 ON " + prefix + "edges.other_id = j2.id "
- "WHERE " + prefix + "edges.id = @id@ OR other_id = @id@";
-
- query.SetValue("type", object->GetSerializableType()->GetName());
- query.SetValue("id", object->id);
- if (type)
- query.SetValue("other_type", type->GetName());
-
- Result res = Run(query);
- for (int i = 0; i < res.Rows(); ++i)
{
- Serialize::ID id = convertTo<Serialize::ID>(res.Get(i, "id")); // object edge is on
-
- if (id == object->id)
- {
- // we want other type, this is my edge
- Anope::string t = res.Get(i, "other_type");
- Anope::string f = res.Get(i, "field");
- id = convertTo<Serialize::ID>(res.Get(i, "other_id"));
-
- Serialize::FieldBase *obj_field = object->GetSerializableType()->GetField(f);
- if (obj_field == nullptr)
- {
- Log(LOG_DEBUG) << "Unable to find field " << f << " on " << object->GetSerializableType()->GetName();
- continue;
- }
-
- Serialize::TypeBase *obj_type = Serialize::TypeBase::Find(t);
- if (obj_type == nullptr)
- {
- Log(LOG_DEBUG) << "Unable to find type " << t;
- continue;
- }
-
- Serialize::Object *other = obj_type->Require(id);
- if (other == nullptr)
- {
- Log(LOG_DEBUG) << "Unable to require id " << id << " type " << obj_type->GetName();
- continue;
- }
-
- edges.emplace_back(other, obj_field, true);
- }
- else
- {
- // edge to me
- Anope::string t = res.Get(i, "type");
- Anope::string f = res.Get(i, "field");
-
- Serialize::TypeBase *obj_type = Serialize::TypeBase::Find(t);
- if (obj_type == nullptr)
- {
- Log(LOG_DEBUG) << "Unable to find type " << t;
- continue;
- }
-
- Serialize::FieldBase *obj_field = obj_type->GetField(f);
- if (obj_field == nullptr)
- {
- Log(LOG_DEBUG) << "Unable to find field " << f << " on " << obj_type->GetName();
- continue;
- }
-
- Serialize::Object *other = obj_type->Require(id);
- if (other == nullptr)
- {
- Log(LOG_DEBUG) << "Unable to require id " << id << " type " << obj_type->GetName();
- continue;
- }
-
- // other type, other field,
- edges.emplace_back(other, obj_field, false);
- }
+ GetRefs(object, type, edges);
}
-
+
return EVENT_ALLOW;
}
@@ -288,7 +244,7 @@ class DBMySQL : public Module, public Pipe
StartTransaction();
Query query = "SELECT `id` FROM `" + prefix + type->GetName() + "` WHERE `id` = @id@";
- query.SetValue("id", id);
+ query.SetValue("id", id, false);
Result res = Run(query);
if (res.Rows() == 0)
return EVENT_CONTINUE;
@@ -302,7 +258,7 @@ class DBMySQL : public Module, public Pipe
Query query = "SELECT `" + field->serialize_name + "`,j1.type AS " + field->serialize_name + "_type FROM `" + prefix + object->GetSerializableType()->GetName() + "` "
"JOIN `" + prefix + "objects` AS j1 ON " + prefix + object->GetSerializableType()->GetName() + "." + field->serialize_name + " = j1.id "
"WHERE " + prefix + object->GetSerializableType()->GetName() + ".id = @id@";
- query.SetValue("id", object->id);
+ query.SetValue("id", object->id, false);
Result res = Run(query);
if (res.Rows() == 0)
@@ -329,16 +285,16 @@ class DBMySQL : public Module, public Pipe
StartTransaction();
- for (Query &q : SQL->CreateTable(prefix, object->GetSerializableType()->GetName()))
+ for (Query &q : SQL->CreateTable(prefix, object->GetSerializableType()))
Run(q);
- for (Query &q : SQL->AlterTable(prefix, object->GetSerializableType()->GetName(), field->serialize_name, is_object))
+ for (Query &q : SQL->AlterTable(prefix, object->GetSerializableType(), field))
Run(q);
Query q;
- q.SetValue("id", object->id);
+ q.SetValue("id", object->id, false);
if (value)
- q.SetValue(field->serialize_name, *value);
+ q.SetValue(field->serialize_name, *value, !is_object);
else
q.SetNull(field->serialize_name);
@@ -364,23 +320,10 @@ class DBMySQL : public Module, public Pipe
{
Anope::string v = stringify(value->id);
DoSet(object, field, true, &v);
-
- Query query;
- query.SetValue("field", field->serialize_name);
- query.SetValue("id", object->id);
- query.SetValue("other_id", value->id);
-
- for (Query &q : SQL->Replace(prefix + "edges", query, { "id", "field" }))
- Run(q);
}
else
{
DoSet(object, field, true, nullptr);
-
- Query query("DELETE FROM `" + prefix + "edges` WHERE `id` = @id@ AND `field` = @field@");
- query.SetValue("id", object->id);
- query.SetValue("field", field->serialize_name);
- Run(query);
}
return EVENT_STOP;
@@ -395,12 +338,6 @@ class DBMySQL : public Module, public Pipe
EventReturn OnSerializeUnsetSerializable(Serialize::Object *object, Serialize::FieldBase *field) override
{
DoSet(object, field, true, nullptr);
-
- Query query("DELETE FROM `" + prefix + "edges` WHERE `id` = @id@ AND `field` = @field@");
- query.SetValue("id", object->id);
- query.SetValue("field", field->serialize_name);
- Run(query);
-
return EVENT_STOP;
}
@@ -408,7 +345,14 @@ class DBMySQL : public Module, public Pipe
{
SQL::Result::Value v;
- return GetValue(object, field, v) && !v.null ? EVENT_STOP : EVENT_CONTINUE;
+ if (!GetValue(object, field, v))
+ return EVENT_CONTINUE;
+
+ if (v.null)
+ return EVENT_CONTINUE;
+
+ field->UnserializeFromString(object, v.value);
+ return EVENT_STOP;
}
EventReturn OnSerializableGetId(Serialize::ID &id) override
@@ -427,7 +371,7 @@ class DBMySQL : public Module, public Pipe
StartTransaction();
Query q = Query("INSERT INTO `" + prefix + "objects` (`id`,`type`) VALUES (@id@, @type@)");
- q.SetValue("id", object->id);
+ q.SetValue("id", object->id, false);
q.SetValue("type", object->GetSerializableType()->GetName());
Run(q);
}
@@ -436,10 +380,10 @@ class DBMySQL : public Module, public Pipe
{
StartTransaction();
- Query query("DELETE FROM `" + prefix + object->GetSerializableType()->GetName() + "` WHERE `id` = " + stringify(object->id));
+ Query query("DELETE FROM `" + prefix + "objects` WHERE `id` = " + stringify(object->id));
Run(query);
}
};
-MODULE_INIT(DBMySQL)
+MODULE_INIT(DBSQL)
diff --git a/modules/extra/mysql.cpp b/modules/extra/mysql.cpp
index b0aec1f6d..b5ff0c3d9 100644
--- a/modules/extra/mysql.cpp
+++ b/modules/extra/mysql.cpp
@@ -156,8 +156,8 @@ class MySQLService : public Provider
std::vector<Query> InitSchema(const Anope::string &prefix) override;
std::vector<Query> Replace(const Anope::string &table, const Query &, const std::set<Anope::string> &) override;
- std::vector<Query> CreateTable(const Anope::string &prefix, const Anope::string &table) override;
- std::vector<Query> AlterTable(const Anope::string &, const Anope::string &table, const Anope::string &field, bool) override;
+ std::vector<Query> CreateTable(const Anope::string &prefix, Serialize::TypeBase *) override;
+ std::vector<Query> AlterTable(const Anope::string &, Serialize::TypeBase *, Serialize::FieldBase *) override;
std::vector<Query> CreateIndex(const Anope::string &table, const Anope::string &field) override;
Query BeginTransaction() override;
@@ -393,24 +393,7 @@ std::vector<Query> MySQLService::InitSchema(const Anope::string &prefix)
{
std::vector<Query> queries;
- Query t = "CREATE TABLE IF NOT EXISTS `" + prefix + "id` ("
- "`id` bigint(20) NOT NULL"
- ") ENGINE=InnoDB";
- queries.push_back(t);
-
- t = "CREATE TABLE IF NOT EXISTS `" + prefix + "objects` (`id` bigint(20) NOT NULL PRIMARY KEY, `type` varchar(256)) ENGINE=InnoDB";
- queries.push_back(t);
-
- t = "CREATE TABLE IF NOT EXISTS `" + prefix + "edges` ("
- "`id` bigint(20) NOT NULL,"
- "`field` varchar(64) NOT NULL,"
- "`other_id` bigint(20) NOT NULL,"
- "PRIMARY KEY (`id`, `field`),"
- "KEY `other` (`other_id`),"
- "CONSTRAINT `edges_id_fk` FOREIGN KEY (`id`) REFERENCES `" + prefix + "objects` (`id`),"
- "CONSTRAINT `edges_other_id_fk` FOREIGN KEY (`other_id`) REFERENCES `" + prefix + "objects` (`id`)"
- ") ENGINE=InnoDB";
- queries.push_back(t);
+ queries.push_back(Query("CREATE TABLE IF NOT EXISTS `" + prefix + "objects` (`id` bigint(20) NOT NULL PRIMARY KEY, `type` TINYTEXT) ENGINE=InnoDB"));
return queries;
}
@@ -441,41 +424,52 @@ std::vector<Query> MySQLService::Replace(const Anope::string &table, const Query
return queries;
}
-std::vector<Query> MySQLService::CreateTable(const Anope::string &prefix, const Anope::string &table)
+std::vector<Query> MySQLService::CreateTable(const Anope::string &prefix, Serialize::TypeBase *base)
{
std::vector<Query> queries;
- if (active_schema.find(prefix + table) == active_schema.end())
+ if (active_schema.find(prefix + base->GetName()) == active_schema.end())
{
- Query t = "CREATE TABLE IF NOT EXISTS `" + prefix + table + "` (`id` bigint(20) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB";
+ Query t = "CREATE TABLE IF NOT EXISTS `" + prefix + base->GetName() + "` (`id` bigint(20) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB";
queries.push_back(t);
- t = "ALTER TABLE `" + prefix + table + "` "
- "ADD CONSTRAINT `" + table + "_id_fk` FOREIGN KEY (`id`) REFERENCES `" + prefix + "objects` (`id`)";
+ t = "ALTER TABLE `" + prefix + base->GetName() + "` "
+ "ADD CONSTRAINT `" + base->GetName() + "_id_fk` FOREIGN KEY (`id`) REFERENCES `" + prefix + "objects` (`id`) ON DELETE CASCADE";
queries.push_back(t);
- active_schema[prefix + table];
+ active_schema[prefix + base->GetName()];
}
return queries;
}
-std::vector<Query> MySQLService::AlterTable(const Anope::string &prefix, const Anope::string &table, const Anope::string &field, bool object)
+std::vector<Query> MySQLService::AlterTable(const Anope::string &prefix, Serialize::TypeBase *type, Serialize::FieldBase *field)
{
+ const Anope::string &table = type->GetName();
+
std::vector<Query> queries;
std::set<Anope::string> &s = active_schema[prefix + table];
- if (!s.count(field))
+ if (!s.count(field->serialize_name))
{
- Query column;
- if (!object)
- column = "ALTER TABLE `" + prefix + table + "` ADD COLUMN `" + field + "` TINYTEXT";
+ Anope::string buf = "ALTER TABLE `" + prefix + table + "` ADD COLUMN `" + field->serialize_name + "` ";
+
+ if (!field->object)
+ {
+ buf += "TINYTEXT";
+ }
else
- column = "ALTER TABLE `" + prefix + table + "` "
- "ADD COLUMN `" + field + "` bigint(20), "
- "ADD CONSTRAINT `" + table + "_" + field + "_fk` FOREIGN KEY (`" + field + "`) REFERENCES `" + prefix + "objects` (`id`)";
- queries.push_back(column);
- s.insert(field);
+ {
+ buf += "bigint(20), ADD CONSTRAINT `" + table + "_" + field->serialize_name + "_fk` FOREIGN KEY (`" + field->serialize_name + "`) REFERENCES `" + prefix + "objects` (`id`) ON DELETE ";
+
+ if (field->depends)
+ buf += "CASCADE";
+ else
+ buf += "SET NULL";
+ }
+
+ queries.push_back(Query(buf));
+ s.insert(field->serialize_name);
}
return queries;
@@ -508,25 +502,19 @@ Query MySQLService::Commit()
Serialize::ID MySQLService::GetID(const Anope::string &prefix)
{
- Query query("SELECT `id` FROM `" + prefix + "id` FOR UPDATE");
- Serialize::ID id;
+ Query query = "SELECT `id` FROM `" + prefix + "objects` ORDER BY `id` DESC LIMIT 1";
+ Serialize::ID id = 0;
Result res = RunQuery(query);
if (res.Rows())
{
id = convertTo<Serialize::ID>(res.Get(0, "id"));
- Query update_query("UPDATE `" + prefix + "id` SET `id` = `id` + 1");
- RunQuery(update_query);
+ /* next id */
+ ++id;
}
- else
- {
- id = 0;
- Query insert_query("INSERT INTO `" + prefix + "id` (id) VALUES(@id@)");
- insert_query.SetValue("id", 1);
- RunQuery(insert_query);
- }
+ /* OnSerializableCreate is called immediately after this which does the insert */
return id;
}
diff --git a/modules/extra/sqlite.cpp b/modules/extra/sqlite.cpp
index 2cd93923b..b9966af5f 100644
--- a/modules/extra/sqlite.cpp
+++ b/modules/extra/sqlite.cpp
@@ -91,8 +91,8 @@ class SQLiteService : public Provider
std::vector<Query> InitSchema(const Anope::string &prefix) override;
std::vector<Query> Replace(const Anope::string &table, const Query &, const std::set<Anope::string> &) override;
- std::vector<Query> CreateTable(const Anope::string &, const Anope::string &table) override;
- std::vector<Query> AlterTable(const Anope::string &, const Anope::string &table, const Anope::string &field, bool) override;
+ std::vector<Query> CreateTable(const Anope::string &, Serialize::TypeBase *) override;
+ std::vector<Query> AlterTable(const Anope::string &, Serialize::TypeBase *, Serialize::FieldBase *) override;
std::vector<Query> CreateIndex(const Anope::string &table, const Anope::string &field) override;
Query BeginTransaction() override;
@@ -210,7 +210,11 @@ Result SQLiteService::RunQuery(const Query &query)
int err = sqlite3_prepare_v2(this->sql, real_query.c_str(), real_query.length(), &stmt, NULL);
if (err != SQLITE_OK)
{
- return SQLiteResult(query, real_query, sqlite3_errmsg(this->sql));
+ const char *msg = sqlite3_errmsg(this->sql);
+
+ Log(LOG_DEBUG) << "sqlite: error in query " << real_query << ": " << msg;
+
+ return SQLiteResult(query, real_query, msg);
}
int id = sqlite3_last_insert_rowid(this->sql);
@@ -218,6 +222,11 @@ Result SQLiteService::RunQuery(const Query &query)
sqlite3_finalize(stmt);
+ if (!result.GetError().empty())
+ Log(LOG_DEBUG) << "sqlite: error executing query " << real_query << ": " << result.GetError();
+ else
+ Log(LOG_DEBUG) << "sqlite: executed: " << real_query;
+
return result;
}
@@ -225,23 +234,9 @@ std::vector<Query> SQLiteService::InitSchema(const Anope::string &prefix)
{
std::vector<Query> queries;
- Query t = "CREATE TABLE IF NOT EXISTS `" + prefix + "id` ("
- "`id`"
- ")";
- queries.push_back(t);
-
- t = "CREATE TABLE IF NOT EXISTS `" + prefix + "objects` (`id` PRIMARY KEY, `type`)";
- queries.push_back(t);
+ queries.push_back(Query("PRAGMA foreign_keys = ON"));
- t = "CREATE TABLE IF NOT EXISTS `" + prefix + "edges` ("
- "`id`,"
- "`field`,"
- "`other_id`,"
- "PRIMARY KEY (`id`, `field`)"
- ")";
- queries.push_back(t);
-
- t = "CREATE INDEX IF NOT EXISTS idx_edge ON `" + prefix + "edges` (other_id)";
+ Query t = "CREATE TABLE IF NOT EXISTS `" + prefix + "objects` (`id` PRIMARY KEY, `type`)";
queries.push_back(t);
return queries;
@@ -287,31 +282,77 @@ std::vector<Query> SQLiteService::Replace(const Anope::string &table, const Quer
return queries;
}
-std::vector<Query> SQLiteService::CreateTable(const Anope::string &prefix, const Anope::string &table)
+std::vector<Query> SQLiteService::CreateTable(const Anope::string &prefix, Serialize::TypeBase *base)
{
std::vector<Query> queries;
- if (active_schema.find(prefix + table) == active_schema.end())
+ if (active_schema.find(prefix + base->GetName()) == active_schema.end())
{
- Query t = "CREATE TABLE IF NOT EXISTS `" + prefix + table + "` (`id` bigint(20) NOT NULL, PRIMARY KEY (`id`))";
- queries.push_back(t);
+ Anope::string query = "CREATE TABLE IF NOT EXISTS `" + prefix + base->GetName() + "` (";
+ std::set<Anope::string> fields;
+
+ for (Serialize::FieldBase *field : base->GetFields())
+ {
+ query += "`" + field->serialize_name + "` COLLATE NOCASE";
+ fields.insert(field->serialize_name);
+
+ if (field->object)
+ {
+ query += " REFERENCES " + prefix + "objects(id) ON DELETE ";
+
+ if (field->depends)
+ {
+ query += "CASCADE";
+ }
+ else
+ {
+ query += "SET NULL";
+ }
+
+ query += " DEFERRABLE INITIALLY DEFERRED";
+ }
+
+ query += ",";
+ }
- active_schema[prefix + table];
+ query += " `id` NOT NULL PRIMARY KEY, FOREIGN KEY (id) REFERENCES " + prefix + "objects(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)";
+ queries.push_back(query);
+
+ active_schema[prefix + base->GetName()] = fields;
}
return queries;
}
-std::vector<Query> SQLiteService::AlterTable(const Anope::string &prefix, const Anope::string &table, const Anope::string &field, bool)
+std::vector<Query> SQLiteService::AlterTable(const Anope::string &prefix, Serialize::TypeBase *type, Serialize::FieldBase *field)
{
+ const Anope::string &table = type->GetName();
+
std::vector<Query> queries;
std::set<Anope::string> &s = active_schema[prefix + table];
- if (!s.count(field))
+ if (!s.count(field->serialize_name))
{
- Query t = "ALTER TABLE `" + prefix + table + "` ADD `" + field + "` COLLATE NOCASE";
- queries.push_back(t);
- s.insert(field);
+ Anope::string buf = "ALTER TABLE `" + prefix + table + "` ADD `" + field->serialize_name + "` COLLATE NOCASE";
+
+ if (field->object)
+ {
+ buf += " REFERENCES " + prefix + "objects(id) ON DELETE ";
+
+ if (field->depends)
+ {
+ buf += "CASCADE";
+ }
+ else
+ {
+ buf += "SET NULL";
+ }
+
+ buf += " DEFERRABLE INITIALLY DEFERRED";
+ }
+
+ queries.push_back(Query(buf));
+ s.insert(field->serialize_name);
}
return queries;
@@ -344,27 +385,19 @@ Query SQLiteService::Commit()
Serialize::ID SQLiteService::GetID(const Anope::string &prefix)
{
- /* must be in a deferred or reserved transaction here for atomic row update */
-
- Query query("SELECT `id` FROM `" + prefix + "id`");
- Serialize::ID id;
+ Query query = "SELECT `id` FROM `" + prefix + "objects` ORDER BY `id` DESC LIMIT 1";
+ Serialize::ID id = 0;
Result res = RunQuery(query);
if (res.Rows())
{
id = convertTo<Serialize::ID>(res.Get(0, "id"));
- Query update_query("UPDATE `" + prefix + "id` SET `id` = `id` + 1");
- RunQuery(update_query);
+ /* next id */
+ ++id;
}
- else
- {
- id = 0;
- Query insert_query("INSERT INTO `" + prefix + "id` (id) VALUES(@id@)");
- insert_query.SetValue("id", 1);
- RunQuery(insert_query);
- }
+ /* OnSerializableCreate is called immediately after this which does the insert */
return id;
}
@@ -376,10 +409,9 @@ Query SQLiteService::GetTables(const Anope::string &prefix)
Anope::string SQLiteService::Escape(const Anope::string &query)
{
- char *e = sqlite3_mprintf("%q", query.c_str());
- Anope::string buffer = e;
- sqlite3_free(e);
- return buffer;
+ std::vector<char> buffer(query.length() * 2 + 1);
+ sqlite3_snprintf(buffer.size(), &buffer[0], "%q", query.c_str());
+ return &buffer[0];
}
Anope::string SQLiteService::BuildQuery(const Query &q)
diff --git a/modules/nickserv/cert.cpp b/modules/nickserv/cert.cpp
index ea0c41f51..94978fd88 100644
--- a/modules/nickserv/cert.cpp
+++ b/modules/nickserv/cert.cpp
@@ -31,6 +31,7 @@ class CertServiceImpl : public CertService
NickServ::Account* FindAccountFromCert(const Anope::string &cert) override
{
+#warning "use serialize find"
Anope::hash_map<NickServ::Account *>::iterator it = certmap.find(cert);
if (it != certmap.end())
return it->second;
@@ -78,15 +79,11 @@ class NSCertEntryType : public Serialize::Type<NSCertEntryImpl>
{
using Serialize::ObjectField<NSCertEntryImpl, NickServ::Account *>::ObjectField;
- void SetField(NSCertEntryImpl *s, NickServ::Account *acc) override
+ void OnSet(NSCertEntryImpl *s, NickServ::Account *acc) override
{
const Anope::string &cert = s->GetCert();
- if (!cert.empty())
- certmap.erase(cert);
-
- Serialize::ObjectField<NSCertEntryImpl, NickServ::Account *>::SetField(s, acc);
- if (!cert.empty() && s->GetAccount())
+ if (!cert.empty())
certmap[cert] = acc;
}
} nc;
@@ -95,13 +92,11 @@ class NSCertEntryType : public Serialize::Type<NSCertEntryImpl>
{
using Serialize::Field<NSCertEntryImpl, Anope::string>::Field;
- void SetField(NSCertEntryImpl *s, const Anope::string &m) override
+ void OnSet(NSCertEntryImpl *s, const Anope::string &m) override
{
- const Anope::string &old = GetField(s);
- if (!old.empty())
- certmap.erase(old);
-
- Serialize::Field<NSCertEntryImpl, Anope::string>::SetField(s, m);
+ Anope::string *old = this->Get_(s);
+ if (old != nullptr)
+ certmap.erase(*old);
if (!m.empty() && s->GetAccount())
certmap[m] = s->GetAccount();
diff --git a/modules/nickserv/main/accounttype.cpp b/modules/nickserv/main/accounttype.cpp
index 16abea415..6ea32cd83 100644
--- a/modules/nickserv/main/accounttype.cpp
+++ b/modules/nickserv/main/accounttype.cpp
@@ -29,18 +29,17 @@ AccountType::AccountType(Module *me) : Serialize::Type<AccountImpl>(me)
}
-void AccountType::Display::SetField(AccountImpl *acc, const Anope::string &disp)
+void AccountType::Display::OnSet(AccountImpl *acc, const Anope::string &disp)
{
NickServ::nickcore_map& map = NickServ::service->GetAccountMap();
- if (!acc->GetDisplay().empty())
- map.erase(acc->GetDisplay());
+ Anope::string *old = this->Get_(acc);
+ if (old != nullptr)
+ map.erase(*old);
- Serialize::Field<AccountImpl, Anope::string>::SetField(acc, disp);
-
- if (!disp.empty())
- map[disp] = acc;
+ map[disp] = acc;
+#warning "this is all wrong"
acc->o = Oper::Find(disp);
}
diff --git a/modules/nickserv/main/accounttype.h b/modules/nickserv/main/accounttype.h
index 4cdba74b0..27efd90dd 100644
--- a/modules/nickserv/main/accounttype.h
+++ b/modules/nickserv/main/accounttype.h
@@ -27,7 +27,7 @@ class AccountType : public Serialize::Type<AccountImpl>
{
using Serialize::Field<AccountImpl, Anope::string>::Field;
- void SetField(AccountImpl *s, const Anope::string &) override;
+ void OnSet(AccountImpl *s, const Anope::string &) override;
} display;
/* User password in form of hashm:data */
Serialize::Field<AccountImpl, Anope::string> pass;
diff --git a/modules/nickserv/main/nickserv.cpp b/modules/nickserv/main/nickserv.cpp
index 2e766a9e2..461925927 100644
--- a/modules/nickserv/main/nickserv.cpp
+++ b/modules/nickserv/main/nickserv.cpp
@@ -219,7 +219,7 @@ class NickServCore : public Module, public NickServ::NickServService
/* On shutdown, restart, or mod unload, remove all of our holds for nicks (svshold or qlines)
* because some IRCds do not allow us to have these automatically expire
*/
- for (NickServ::Nick *na : nick_type.List<NickServ::Nick *>())
+ for (NickServ::Nick *na : Serialize::GetObjects<NickServ::Nick *>())
this->Release(na);
}
@@ -362,7 +362,7 @@ class NickServCore : public Module, public NickServ::NickServService
std::vector<NickServ::Nick *> GetNickList() override
{
- return nick_type.List<NickServ::Nick *>();
+ return Serialize::GetObjects<NickServ::Nick *>();
}
NickServ::nickalias_map& GetNickMap() override
@@ -372,7 +372,7 @@ class NickServCore : public Module, public NickServ::NickServService
std::vector<NickServ::Account *> GetAccountList() override
{
- return account_type.List<NickServ::Account *>();
+ return Serialize::GetObjects<NickServ::Account *>();
}
NickServ::nickcore_map& GetAccountMap() override
@@ -532,6 +532,7 @@ class NickServCore : public Module, public NickServ::NickServService
{
if (u->HasMode("REGISTERED") && !u->IsIdentified(true))
u->RemoveMode(NickServ, "REGISTERED");
+
if (!u->IsIdentified())
this->Validate(u);
}
@@ -640,7 +641,7 @@ class NickServCore : public Module, public NickServ::NickServService
time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "21d");
- for (NickServ::Nick *na : nick_type.List<NickServ::Nick *>())
+ for (NickServ::Nick *na : Serialize::GetObjects<NickServ::Nick *>())
{
User *u = User::Find(na->GetNick(), true);
if (u && (u->IsIdentified(true) || u->IsRecognized()))
diff --git a/modules/nickserv/main/nicktype.cpp b/modules/nickserv/main/nicktype.cpp
index 7b72f3e42..2cf1b2027 100644
--- a/modules/nickserv/main/nicktype.cpp
+++ b/modules/nickserv/main/nicktype.cpp
@@ -28,18 +28,19 @@ NickType::NickType(Module *me) : Serialize::Type<NickImpl>(me)
, last_realhost(this, "last_realhost", &NickImpl::last_realhost)
, time_registered(this, "time_registered", &NickImpl::time_registered)
, last_seen(this, "last_seen", &NickImpl::last_seen)
+#warning "this should depend?"
, nc(this, "nc", &NickImpl::account)
{
}
-void NickType::Nick::SetField(NickImpl *na, const Anope::string &value)
+void NickType::Nick::OnSet(NickImpl *na, const Anope::string &value)
{
/* Remove us from the aliases list */
NickServ::nickalias_map &map = NickServ::service->GetNickMap();
- map.erase(GetField(na));
-
- Serialize::Field<NickImpl, Anope::string>::SetField(na, value);
+ Anope::string *old = this->Get_(na);
+ if (old != nullptr)
+ map.erase(*old);
map[value] = na;
}
diff --git a/modules/nickserv/main/nicktype.h b/modules/nickserv/main/nicktype.h
index d94265132..0779b08da 100644
--- a/modules/nickserv/main/nicktype.h
+++ b/modules/nickserv/main/nicktype.h
@@ -26,7 +26,7 @@ class NickType : public Serialize::Type<NickImpl>
{
using Serialize::Field<NickImpl, Anope::string>::Field;
- void SetField(NickImpl *s, const Anope::string &value) override;
+ void OnSet(NickImpl *s, const Anope::string &value) override;
} nick;
Serialize::Field<NickImpl, Anope::string> last_quit;
Serialize::Field<NickImpl, Anope::string> last_realname;
diff --git a/src/bots.cpp b/src/bots.cpp
index 07d6ec858..2ba7bda67 100644
--- a/src/bots.cpp
+++ b/src/bots.cpp
@@ -37,15 +37,6 @@ ServiceBot::ServiceBot(const Anope::string &nnick, const Anope::string &nuser, c
this->lastmsg = Anope::CurTime;
this->introduced = false;
- bi = Serialize::New<BotInfo *>();
- bi->bot = this;
-
- bi->SetNick(nnick);
- bi->SetUser(nuser);
- bi->SetHost(nhost);
- bi->SetRealName(nreal);
- bi->SetCreated(Anope::CurTime);
-
EventManager::Get()->Dispatch(&Event::CreateBot::OnCreateBot, this);
// If we're synchronised with the uplink already, send the bot.
@@ -65,8 +56,11 @@ ServiceBot::ServiceBot(const Anope::string &nnick, const Anope::string &nuser, c
ServiceBot::~ServiceBot()
{
- bi->bot = nullptr;
- bi->Delete();
+ if (bi != nullptr)
+ {
+ bi->bot = nullptr;
+ bi->Delete();
+ }
EventManager::Get()->Dispatch(&Event::DelBot::OnDelBot, this);
@@ -109,7 +103,8 @@ void ServiceBot::SetNewNick(const Anope::string &newnick)
{
UserListByNick.erase(this->nick);
- bi->SetNick(newnick);
+ if (bi != nullptr)
+ bi->SetNick(newnick);
this->nick = newnick;
UserListByNick[this->nick] = this;
@@ -117,7 +112,7 @@ void ServiceBot::SetNewNick(const Anope::string &newnick)
std::vector<ChanServ::Channel *> ServiceBot::GetChannels() const
{
- return bi->GetRefs<ChanServ::Channel *>();
+ return bi != nullptr ? bi->GetRefs<ChanServ::Channel *>() : std::vector<ChanServ::Channel *>();
}
void ServiceBot::Assign(User *u, ChanServ::Channel *ci)
diff --git a/src/config.cpp b/src/config.cpp
index 0f083e3f8..6d671401e 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -317,72 +317,7 @@ Conf::Conf() : Block("")
this->MyOperTypes.push_back(ot);
}
- for (int i = 0; i < this->CountBlock("oper"); ++i)
- {
- Block *oper = this->GetBlock("oper", i);
-
- const Anope::string &nname = oper->Get<Anope::string>("name"),
- &type = oper->Get<Anope::string>("type"),
- &password = oper->Get<Anope::string>("password"),
- &certfp = oper->Get<Anope::string>("certfp"),
- &host = oper->Get<Anope::string>("host"),
- &vhost = oper->Get<Anope::string>("vhost");
- bool require_oper = oper->Get<bool>("require_oper");
-
- ValidateNotEmpty("oper", "name", nname);
- ValidateNotEmpty("oper", "type", type);
-
- OperType *ot = NULL;
- for (unsigned j = 0; j < this->MyOperTypes.size(); ++j)
- if (this->MyOperTypes[j]->GetName() == type)
- ot = this->MyOperTypes[j];
- if (ot == NULL)
- throw ConfigException("Oper block for " + nname + " has invalid oper type " + type);
-
- Oper *o = Serialize::New<Oper *>();
- o->conf = this;
- o->SetName(nname);
- o->SetType(ot);
- o->SetRequireOper(require_oper);
- o->SetPassword(password);
- o->SetCertFP(certfp);
- o->SetHost(host);
- o->SetVhost(vhost);
- }
-
- for (BotInfo *bi : Serialize::GetObjects<BotInfo *>())
- bi->conf = nullptr;
- for (int i = 0; i < this->CountBlock("service"); ++i)
- {
- Block *service = this->GetBlock("service", i);
-
- const Anope::string &nick = service->Get<Anope::string>("nick"),
- &user = service->Get<Anope::string>("user"),
- &host = service->Get<Anope::string>("host"),
- &gecos = service->Get<Anope::string>("gecos"),
- &modes = service->Get<Anope::string>("modes"),
- &channels = service->Get<Anope::string>("channels");
-
- ValidateNotEmpty("service", "nick", nick);
- ValidateNotEmpty("service", "user", user);
- ValidateNotEmpty("service", "host", host);
- ValidateNotEmpty("service", "gecos", gecos);
- ValidateNoSpaces("service", "channels", channels);
-
- if (User *u = User::Find(nick, true))
- {
- if (u->type != UserType::BOT)
- {
- u->Kill(Me, "Nickname required by services");
- }
- }
-
- ServiceBot *sb = ServiceBot::Find(nick, true);
- if (!sb)
- sb = new ServiceBot(nick, user, host, gecos, modes);
-
- sb->bi->conf = service;
- }
+ this->LoadBots();
for (int i = 0; i < this->CountBlock("log"); ++i)
{
@@ -635,6 +570,9 @@ void Conf::Post(Conf *old)
if (std::find(old->ModulesAutoLoad.begin(), old->ModulesAutoLoad.end(), this->ModulesAutoLoad[i]) == old->ModulesAutoLoad.end())
ModuleManager::LoadModule(this->ModulesAutoLoad[i], NULL);
+ LoadOpers();
+ ApplyBots();
+
ModeManager::Apply(old);
/* Apply opertype changes, as non-conf opers still point to the old oper types */
@@ -699,6 +637,105 @@ void Conf::Post(Conf *old)
}
}
+void Conf::LoadBots()
+{
+ for (BotInfo *bi : Serialize::GetObjects<BotInfo *>())
+ bi->conf = nullptr;
+ for (int i = 0; i < this->CountBlock("service"); ++i)
+ {
+ Block *service = this->GetBlock("service", i);
+
+ const Anope::string &nick = service->Get<Anope::string>("nick"),
+ &user = service->Get<Anope::string>("user"),
+ &host = service->Get<Anope::string>("host"),
+ &gecos = service->Get<Anope::string>("gecos"),
+ &modes = service->Get<Anope::string>("modes"),
+ &channels = service->Get<Anope::string>("channels");
+
+ ValidateNotEmpty("service", "nick", nick);
+ ValidateNotEmpty("service", "user", user);
+ ValidateNotEmpty("service", "host", host);
+ ValidateNotEmpty("service", "gecos", gecos);
+ ValidateNoSpaces("service", "channels", channels);
+
+ if (User *u = User::Find(nick, true))
+ {
+ if (u->type != UserType::BOT)
+ {
+ u->Kill(Me, "Nickname required by services");
+ }
+ }
+
+ ServiceBot *sb = ServiceBot::Find(nick, true);
+ if (!sb)
+ sb = new ServiceBot(nick, user, host, gecos, modes);
+ }
+}
+
+void Conf::ApplyBots()
+{
+ for (std::pair<Anope::string, User *> p : UserListByNick)
+ {
+ User *u = p.second;
+ if (u->type != UserType::BOT)
+ continue;
+
+ ServiceBot *sb = anope_dynamic_static_cast<ServiceBot *>(u);
+ if (sb->bi != nullptr)
+ continue;
+
+ sb->bi = Serialize::New<BotInfo *>();
+ sb->bi->bot = sb;
+
+ sb->bi->SetNick(sb->nick);
+ sb->bi->SetUser(sb->GetIdent());
+ sb->bi->SetHost(sb->host);
+ sb->bi->SetRealName(sb->realname);
+ sb->bi->SetCreated(Anope::CurTime);
+ }
+}
+
+void Conf::LoadOpers()
+{
+ for (int i = 0; i < this->CountBlock("oper"); ++i)
+ {
+ Block *oper = this->GetBlock("oper", i);
+
+ const Anope::string &nname = oper->Get<Anope::string>("name"),
+ &type = oper->Get<Anope::string>("type"),
+ &password = oper->Get<Anope::string>("password"),
+ &certfp = oper->Get<Anope::string>("certfp"),
+ &host = oper->Get<Anope::string>("host"),
+ &vhost = oper->Get<Anope::string>("vhost");
+ bool require_oper = oper->Get<bool>("require_oper");
+
+ ValidateNotEmpty("oper", "name", nname);
+ ValidateNotEmpty("oper", "type", type);
+
+ OperType *ot = NULL;
+ for (unsigned j = 0; j < this->MyOperTypes.size(); ++j)
+ if (this->MyOperTypes[j]->GetName() == type)
+ ot = this->MyOperTypes[j];
+ if (ot == NULL)
+ {
+ Log() << "Oper block for " << nname << " has invalid oper type " << type;
+ continue;
+ }
+
+ Oper *o = Serialize::New<Oper *>();
+ o->conf = this;
+ o->SetName(nname);
+ o->SetType(ot);
+ o->SetRequireOper(require_oper);
+ o->SetPassword(password);
+ o->SetCertFP(certfp);
+ o->SetHost(host);
+ o->SetVhost(vhost);
+
+ Log(LOG_DEBUG) << "Creating oper " << nname << " of type " << ot->GetName();
+ }
+}
+
Block *Conf::GetModule(Module *m)
{
if (!m)
diff --git a/src/init.cpp b/src/init.cpp
index ec23a7b4b..9ee720ebd 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -543,6 +543,9 @@ void Anope::Init(int ac, char **av)
for (int i = 0; i < Config->CountBlock("module"); ++i)
ModuleManager::LoadModule(Config->GetBlock("module", i)->Get<Anope::string>("name"), NULL);
+ Config->LoadOpers();
+ Config->ApplyBots();
+
#ifndef _WIN32
/* We won't background later, so we should setuid now */
if (Anope::NoFork)
diff --git a/src/service_manager.cpp b/src/service_manager.cpp
index ef26fb13b..abebd1c3d 100644
--- a/src/service_manager.cpp
+++ b/src/service_manager.cpp
@@ -82,7 +82,7 @@ void ServiceManager::Register(Service *service)
throw ModuleException("Service of type " + service->GetType() + " with name " + service->GetName() + " already exists");
}
- Log(LOG_DEBUG_2) << "Service registered: " << service->GetType() << " " << service->GetName() << " address " << static_cast<void *>(this) << " by " << service->GetOwner();
+ Log(LOG_DEBUG_3) << "Service registered: " << service->GetType() << " " << service->GetName() << " address " << static_cast<void *>(this) << " by " << service->GetOwner();
services.push_back(service);
@@ -91,7 +91,7 @@ void ServiceManager::Register(Service *service)
void ServiceManager::Unregister(Service *service)
{
- Log(LOG_DEBUG_2) << "Service unregistered: " << service->GetType() << " " << service->GetName() << " address " << static_cast<void *>(service) << " by " << service->GetOwner();
+ Log(LOG_DEBUG_3) << "Service unregistered: " << service->GetType() << " " << service->GetName() << " address " << static_cast<void *>(service) << " by " << service->GetOwner();
auto it = std::find(services.begin(), services.end(), service);
if (it != services.end())
@@ -107,13 +107,13 @@ void ServiceManager::Lookup(ServiceReferenceBase *reference)
if (reference->GetName().empty())
{
std::vector<Service *> services = this->FindServices(reference->GetType());
- Log(LOG_DEBUG_2) << "Service lookup " << static_cast<void *>(reference) << " type " << reference->GetType() << " name " << reference->GetName() << ": " << services.size() << " services";
+ Log(LOG_DEBUG_3) << "Service lookup " << static_cast<void *>(reference) << " type " << reference->GetType() << " name " << reference->GetName() << ": " << services.size() << " services";
reference->SetServices(services);
}
else
{
Service *service = this->FindService(reference->GetType(), reference->GetName());
- Log(LOG_DEBUG_2) << "Service lookup " << static_cast<void *>(reference) << " type " << reference->GetType() << " name " << reference->GetName() << ": " << service;
+ Log(LOG_DEBUG_3) << "Service lookup " << static_cast<void *>(reference) << " type " << reference->GetType() << " name " << reference->GetName() << ": " << service;
reference->SetService(service);
}
}
diff --git a/src/xline.cpp b/src/xline.cpp
index df65ae7dd..7d26461b4 100644
--- a/src/xline.cpp
+++ b/src/xline.cpp
@@ -215,9 +215,8 @@ XLineManager *XLine::GetManager()
return ServiceManager::Get()->FindService<XLineManager *>(GetType());
}
-void XLineType::Mask::SetField(XLine *s, const Anope::string &value)
+void XLineType::Mask::OnSet(XLine *s, const Anope::string &value)
{
- Serialize::Field<XLine, Anope::string>::SetField(s, value);
s->Recache();
}