diff options
| author | Adam <Adam@anope.org> | 2014-11-24 14:27:23 -0500 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2014-11-24 14:27:23 -0500 |
| commit | 42238034490fb5479d787bd1695750387d508200 (patch) | |
| tree | c93c62e0e1c936e656ae5b9ee1b62380ce2a194c /include | |
| parent | d492923610d9c9146b2a2b63de38deab2cfd4ca7 (diff) | |
Rewrite serializable to have field level granularity
Represent serializable objects in a digraph, and as a result made most
object relationships implicitly defined, and use the graph to trace
references between objects to determine relationships. Edges may
also be marked as having a dependency of the object they point to,
which allows for automatic cleanup and deletion of most objects when
no longer needed.
Additionally, this allows not having to require in-memory copies of
everything when using external databases. db_sql has been rewritten
for this and now always requires a database to function. db_sql with
MySQL now requires InnoDB to make use of transactions and foreign
key constraints.
Diffstat (limited to 'include')
50 files changed, 2013 insertions, 1270 deletions
diff --git a/include/anope.h b/include/anope.h index 839d201cf..218e75d47 100644 --- a/include/anope.h +++ b/include/anope.h @@ -502,21 +502,21 @@ namespace Anope * @param nc The account to use language settings for to translate this string, if applicable * @return A human readable string, eg "1 minute" */ - extern CoreExport Anope::string Duration(time_t seconds, const NickServ::Account *nc = NULL); + extern CoreExport Anope::string Duration(time_t seconds, NickServ::Account *nc = NULL); /** Generates a human readable string of type "expires in ..." * @param expires time in seconds * @param nc The account to use language settings for to translate this string, if applicable * @return A human readable string, eg "expires in 5 days" */ - extern CoreExport Anope::string Expires(time_t seconds, const NickServ::Account *nc = NULL); + extern CoreExport Anope::string Expires(time_t seconds, NickServ::Account *nc = NULL); /** Converts a time in seconds (epoch) to a human readable format. * @param t The time * @param nc The account to use language settings for to translate this string, if applicable * @param short_output If true, the output is just a date (eg, "Apr 12 20:18:22 2009 MSD"), else it includes the date and how long ago/from now that date is, (eg "Apr 12 20:18:22 2009 MSD (1313 days, 9 hours, 32 minutes ago)" */ - extern CoreExport Anope::string strftime(time_t t, const NickServ::Account *nc = NULL, bool short_output = false); + extern CoreExport Anope::string strftime(time_t t, NickServ::Account *nc = NULL, bool short_output = false); /** Normalize buffer, stripping control characters and colors * @param A string to be parsed for control and color codes @@ -704,6 +704,22 @@ class ConvertException : public CoreException virtual ~ConvertException() throw() { } }; +template<typename T> +typename std::enable_if<std::is_enum<T>::value, std::ostream &>::type +operator<<(std::ostream &os, T t) +{ + // XXX + return os; +} + +template<typename T> +typename std::enable_if<std::is_enum<T>::value, std::istream &>::type +operator>>(std::istream &is, T& t) +{ + // XXX + return is; +} + /** Convert something to a string */ template<typename T> inline Anope::string stringify(const T &x) @@ -790,7 +806,7 @@ struct kwarg inline kwarg operator"" _kw(const char *literal, size_t n) { - return kwarg{ literal }; + return { literal }; } struct FormatInfo diff --git a/include/bots.h b/include/bots.h index ef57d31f3..7d490d4f5 100644 --- a/include/bots.h +++ b/include/bots.h @@ -17,17 +17,12 @@ typedef Anope::hash_map<BotInfo *> botinfo_map; -extern CoreExport Serialize::Checker<botinfo_map> BotListByNick, BotListByUID; - /* A service bot (NickServ, ChanServ, a BotServ bot, etc). */ -class CoreExport BotInfo : public User, public Serializable +class CoreExport ServiceBot : public LocalUser { - /* Channels this bot is assigned to */ - Serialize::Checker<std::set<ChanServ::Channel *> > channels; public: - time_t created; - /* Last time this bot said something (via privmsg) */ - time_t lastmsg; + /* Underlying botinfo for this bot */ + Serialize::Reference<BotInfo> bi; /* Map of actual command names -> service name/permission required */ CommandInfo::map commands; /* Modes the bot should have as configured in service:modes */ @@ -36,8 +31,6 @@ class CoreExport BotInfo : public User, public Serializable std::vector<Anope::string> botchannels; /* Whether or not this bot is introduced to the network */ bool introduced; - /* Bot can only be assigned by irc ops */ - bool oper_only; /* Bot is defined in the configuration file */ bool conf; @@ -48,14 +41,11 @@ class CoreExport BotInfo : public User, public Serializable * @param real The realname to give the bot. * @param bmodes The modes to give the bot. */ - BotInfo(const Anope::string &nick, const Anope::string &user = "", const Anope::string &host = "", const Anope::string &real = "", const Anope::string &bmodes = ""); + ServiceBot(const Anope::string &nick, const Anope::string &user = "", const Anope::string &host = "", const Anope::string &real = "", const Anope::string &bmodes = ""); /** Destroy a bot, clearing up appropriately. */ - virtual ~BotInfo(); - - void Serialize(Serialize::Data &data) const; - static Serializable* Unserialize(Serializable *obj, Serialize::Data &); + virtual ~ServiceBot(); void GenerateUID(); @@ -68,7 +58,7 @@ class CoreExport BotInfo : public User, public Serializable /** Return the channels this bot is assigned to */ - const std::set<ChanServ::Channel *> &GetChannels() const; + std::vector<ChanServ::Channel *> GetChannels() const; /** Assign this bot to a given channel, removing the existing assigned bot if one exists. * @param u The user assigning the bot, or NULL @@ -131,6 +121,53 @@ class CoreExport BotInfo : public User, public Serializable * @param nick_only True to only look by nick, and not by UID * @return The bot, if it exists */ - static BotInfo* Find(const Anope::string &nick, bool nick_only = false); + static ServiceBot* Find(const Anope::string &nick, bool nick_only = false); +}; + +class BotInfo : public Serialize::Object +{ + public: + ServiceBot *bot; + + BotInfo(Serialize::TypeBase *type) : Serialize::Object(type) { } + BotInfo(Serialize::TypeBase *type, Serialize::ID id) : Serialize::Object(type, id) { } + + void SetNick(const Anope::string &); + Anope::string GetNick(); + + void SetUser(const Anope::string &); + Anope::string GetUser(); + + void SetHost(const Anope::string &); + Anope::string GetHost(); + + void SetRealName(const Anope::string &); + Anope::string GetRealName(); + + void SetCreated(const time_t &); + time_t GetCreated(); + + void SetOperOnly(const bool &); + bool GetOperOnly(); }; +class BotInfoType : public Serialize::Type<BotInfo> +{ + public: + Serialize::Field<BotInfo, Anope::string> nick, user, host, realname; + Serialize::Field<BotInfo, time_t> created; + Serialize::Field<BotInfo, bool> operonly; + + BotInfoType() : Serialize::Type<BotInfo>(nullptr, "BotInfo") + , nick(this, "nick") + , user(this, "user") + , host(this, "host") + , realname(this, "realname") + , created(this, "created") + , operonly(this, "operonly") + { + } +}; + +static Serialize::TypeReference<BotInfo> botinfo("BotInfo"); + diff --git a/include/commands.h b/include/commands.h index bd786633a..bc78dda78 100644 --- a/include/commands.h +++ b/include/commands.h @@ -15,13 +15,14 @@ #include "anope.h" #include "channels.h" #include "language.h" +#include "modules/nickserv.h"// XXX clang struct CommandGroup { Anope::string name, description; }; -/* Used in BotInfo::commands */ +/* Used in ServiceBot::commands */ struct CommandInfo { typedef Anope::map<CommandInfo> map; @@ -66,13 +67,13 @@ class CoreExport CommandSource /* Channel the command was executed on (fantasy) */ Reference<Channel> c; /* The service this command is on */ - Reference<BotInfo> service; + Reference<ServiceBot> service; /* The actual name of the command being executed */ Anope::string command; /* The permission of the command being executed */ Anope::string permission; - CommandSource(const Anope::string &n, User *user, NickServ::Account *core, CommandReply *reply, BotInfo *bi); + CommandSource(const Anope::string &n, User *user, NickServ::Account *core, CommandReply *reply, ServiceBot *bi); const Anope::string &GetNick() const; User *GetUser(); @@ -185,6 +186,6 @@ class CoreExport Command : public Service * @param name If found, is set to the comand name, eg REGISTER * @return true if the given command service exists */ - static bool FindCommandFromService(const Anope::string &command_service, BotInfo* &bi, Anope::string &name); + static bool FindCommandFromService(const Anope::string &command_service, ServiceBot* &bi, Anope::string &name); }; diff --git a/include/config.h b/include/config.h index efb0ecfba..455785096 100644 --- a/include/config.h +++ b/include/config.h @@ -14,7 +14,6 @@ #include "users.h" #include "opertype.h" -#include <stack> namespace Configuration { @@ -113,8 +112,8 @@ namespace Configuration std::vector<Anope::string> Ulines; /* List of available opertypes */ std::vector<OperType *> MyOperTypes; - /* List of pairs of opers and their opertype from the config */ - std::vector<Oper *> Opers; + /* names of opers configured in the configuration */ + std::vector<Anope::string> Opers; /* Map of fantasy commands */ CommandInfo::map Fantasy; /* Command groups */ @@ -137,7 +136,7 @@ namespace Configuration Block *GetModule(Module *); Block *GetModule(const Anope::string &name); - BotInfo *GetClient(const Anope::string &name); + ServiceBot *GetClient(const Anope::string &name); Block *GetCommand(CommandSource &); }; diff --git a/include/defs.h b/include/defs.h index 4c1e9ce91..19e9214b9 100644 --- a/include/defs.h +++ b/include/defs.h @@ -14,6 +14,7 @@ class AutoKick; class BotInfo; class Channel; +class ChannelMode; class ChannelStatus; namespace ChanServ { @@ -28,6 +29,7 @@ class CommandSource; namespace Configuration { struct Conf; } class ConnectionSocket; class Entry; +class ExtensibleBase; class InfoFormatter; class IRCDProto; class ListenSocket; @@ -42,23 +44,29 @@ namespace NickServ namespace MemoServ { class Memo; - struct MemoInfo; + class MemoInfo; } class MessageSource; class Module; class OperType; class ReferenceBase; class Regex; -class Serializable; +class ServiceBot; +namespace Serialize +{ + using ID = uint64_t; + struct Edge; + class FieldBase; + class TypeBase; + class Object; +} class Server; class Socket; class Thread; class User; class XLine; class XLineManager; -struct BadWord; -struct Exception; -struct ModeLock; -struct Oper; +class Oper; namespace SASL { struct Message; } +class UserMode; diff --git a/include/event.h b/include/event.h index 381db967b..a8c8999cd 100644 --- a/include/event.h +++ b/include/event.h @@ -10,11 +10,19 @@ #pragma once #include "service.h" -#include "modules.h" + +/** Possible return types from events. + */ +enum EventReturn +{ + EVENT_STOP, + EVENT_CONTINUE, + EVENT_ALLOW +}; struct Events { - virtual ~Events() { } + virtual ~Events() = default; }; /* uninstantiated */ @@ -174,7 +182,7 @@ namespace Event * @param bi The bot being assigned. * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the assign. */ - virtual EventReturn OnPreBotAssign(User *sender, ChanServ::Channel *ci, BotInfo *bi) anope_abstract; + virtual EventReturn OnPreBotAssign(User *sender, ChanServ::Channel *ci, ServiceBot *bi) anope_abstract; }; extern CoreExport EventHandlers<PreBotAssign> OnPreBotAssign; @@ -182,7 +190,7 @@ namespace Event { /** Called when a bot is assigned ot a channel */ - virtual void OnBotAssign(User *sender, ChanServ::Channel *ci, BotInfo *bi) anope_abstract; + virtual void OnBotAssign(User *sender, ChanServ::Channel *ci, ServiceBot *bi) anope_abstract; }; extern CoreExport EventHandlers<BotAssign> OnBotAssign; @@ -288,13 +296,13 @@ namespace Event { /** Called when a bot is created or destroyed */ - virtual void OnCreateBot(BotInfo *bi) anope_abstract; + virtual void OnCreateBot(ServiceBot *bi) anope_abstract; }; extern CoreExport EventHandlers<CreateBot> OnCreateBot; struct CoreExport DelBot : Events { - virtual void OnDelBot(BotInfo *bi) anope_abstract; + virtual void OnDelBot(ServiceBot *bi) anope_abstract; }; extern CoreExport EventHandlers<DelBot> OnDelBot; @@ -854,7 +862,7 @@ namespace Event * @param message The message * @return EVENT_STOP to halt processing */ - virtual EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) anope_abstract; + virtual EventReturn OnBotPrivmsg(User *u, ServiceBot *bi, Anope::string &message) anope_abstract; }; extern CoreExport EventHandlers<BotPrivmsg> OnBotPrivmsg; @@ -865,7 +873,7 @@ namespace Event * @param bi The target of the NOTICE * @param message The message */ - virtual void OnBotNotice(User *u, BotInfo *bi, Anope::string &message) anope_abstract; + virtual void OnBotNotice(User *u, ServiceBot *bi, Anope::string &message) anope_abstract; }; extern CoreExport EventHandlers<BotNotice> OnBotNotice; @@ -935,36 +943,6 @@ namespace Event }; extern CoreExport EventHandlers<SetCorrectModes> OnSetCorrectModes; - struct CoreExport SerializeCheck : Events - { - virtual void OnSerializeCheck(Serialize::Type *) anope_abstract; - }; - extern CoreExport EventHandlers<SerializeCheck> OnSerializeCheck; - - struct CoreExport SerializableConstruct : Events - { - virtual void OnSerializableConstruct(Serializable *) anope_abstract; - }; - extern CoreExport EventHandlers<SerializableConstruct> OnSerializableConstruct; - - struct CoreExport SerializableDestruct : Events - { - virtual void OnSerializableDestruct(Serializable *) anope_abstract; - }; - extern CoreExport EventHandlers<SerializableDestruct> OnSerializableDestruct; - - struct CoreExport SerializableUpdate : Events - { - virtual void OnSerializableUpdate(Serializable *) anope_abstract; - }; - extern CoreExport EventHandlers<SerializableUpdate> OnSerializableUpdate; - - struct CoreExport SerializeTypeCreate : Events - { - virtual void OnSerializeTypeCreate(Serialize::Type *) anope_abstract; - }; - extern CoreExport EventHandlers<SerializeTypeCreate> OnSerializeTypeCreate; - struct CoreExport Message : Events { /** Called whenever a message is received from the uplink @@ -1002,5 +980,36 @@ namespace Event }; extern CoreExport EventHandlers<ExpireTick> OnExpireTick; + struct CoreExport SerializeEvents : Events + { + virtual EventReturn OnSerializeList(Serialize::TypeBase *type, std::vector<Serialize::ID> &ids) anope_abstract; + + virtual EventReturn OnSerializeFind(Serialize::TypeBase *type, Serialize::FieldBase *field, const Anope::string &value, Serialize::ID &id) anope_abstract; + + virtual EventReturn OnSerializeGet(Serialize::Object *object, Serialize::FieldBase *field, Anope::string &value) anope_abstract; + + virtual EventReturn OnSerializeGetSerializable(Serialize::Object *object, Serialize::FieldBase *field, Anope::string &type, Serialize::ID &id) anope_abstract; + + virtual EventReturn OnSerializeGetRefs(Serialize::Object *object, Serialize::TypeBase *type, std::vector<Serialize::Edge> &) anope_abstract; + + virtual EventReturn OnSerializeDeref(Serialize::ID value, Serialize::TypeBase *type) anope_abstract; + + virtual EventReturn OnSerializableGetId(Serialize::ID &id) anope_abstract; + + virtual void OnSerializableDelete(Serialize::Object *) anope_abstract; + + virtual EventReturn OnSerializeSet(Serialize::Object *object, Serialize::FieldBase *field, const Anope::string &value) anope_abstract; + + virtual EventReturn OnSerializeSetSerializable(Serialize::Object *object, Serialize::FieldBase *field, Serialize::Object *value) anope_abstract; + + virtual EventReturn OnSerializeUnset(Serialize::Object *object, Serialize::FieldBase *field) anope_abstract; + + virtual EventReturn OnSerializeUnsetSerializable(Serialize::Object *object, Serialize::FieldBase *field) anope_abstract; + + virtual EventReturn OnSerializeHasField(Serialize::Object *object, Serialize::FieldBase *field) anope_abstract; + + virtual void OnSerializableCreate(Serialize::Object *) anope_abstract; + }; + extern CoreExport EventHandlers<SerializeEvents> OnSerialize; } diff --git a/include/extensible.h b/include/extensible.h index 58e577f42..4faff818b 100644 --- a/include/extensible.h +++ b/include/extensible.h @@ -10,7 +10,6 @@ #pragma once #include "anope.h" -#include "serialize.h" #include "service.h" #include "logger.h" @@ -22,45 +21,36 @@ class CoreExport ExtensibleBase : public Service std::map<Extensible *, void *> items; ExtensibleBase(Module *m, const Anope::string &n); + ExtensibleBase(Module *m, const Anope::string &t, const Anope::string &n); ~ExtensibleBase(); public: virtual void Unset(Extensible *obj) anope_abstract; - - /* called when an object we are keep track of is serializing */ - virtual void ExtensibleSerialize(const Extensible *, const Serializable *, Serialize::Data &) const { } - virtual void ExtensibleUnserialize(Extensible *, Serializable *, Serialize::Data &) { } }; class CoreExport Extensible { public: - std::set<ExtensibleBase *> extension_items; + std::vector<ExtensibleBase *> extension_items; virtual ~Extensible(); - template<typename T> T* GetExt(const Anope::string &name) const; - bool HasExt(const Anope::string &name) const; + template<typename T> T* GetExt(const Anope::string &name); + bool HasExtOK(const Anope::string &name); template<typename T> T* Extend(const Anope::string &name, const T &what); - template<typename T> T* Extend(const Anope::string &name); - template<typename T> T* Require(const Anope::string &name); - template<typename T> void Shrink(const Anope::string &name); - static void ExtensibleSerialize(const Extensible *, const Serializable *, Serialize::Data &data); - static void ExtensibleUnserialize(Extensible *, Serializable *, Serialize::Data &data); + template<typename T> void ShrinkOK(const Anope::string &name); }; template<typename T> -class BaseExtensibleItem : public ExtensibleBase +class ExtensibleItem : public ExtensibleBase { - protected: - virtual T *Create(Extensible *) anope_abstract; - public: - BaseExtensibleItem(Module *m, const Anope::string &n) : ExtensibleBase(m, n) { } + ExtensibleItem(Module *m, const Anope::string &n) : ExtensibleBase(m, n) { } + ExtensibleItem(Module *m, const Anope::string &t, const Anope::string &n) : ExtensibleBase(m, t, n) { } - ~BaseExtensibleItem() + ~ExtensibleItem() { while (!items.empty()) { @@ -68,48 +58,49 @@ class BaseExtensibleItem : public ExtensibleBase Extensible *obj = it->first; T *value = static_cast<T *>(it->second); - obj->extension_items.erase(this); + auto it2 = std::find(obj->extension_items.begin(), obj->extension_items.end(), this); + if (it2 != obj->extension_items.end()) + obj->extension_items.erase(it2); items.erase(it); + delete value; } } T* Set(Extensible *obj, const T &value) { - T* t = Set(obj); - if (t) - *t = value; - return t; - } - - T* Set(Extensible *obj) - { - T* t = Create(obj); + T* t = new T(value); Unset(obj); + items[obj] = t; - obj->extension_items.insert(this); + obj->extension_items.push_back(this); + return t; } void Unset(Extensible *obj) override { T *value = Get(obj); + items.erase(obj); - obj->extension_items.erase(this); + auto it = std::find(obj->extension_items.begin(), obj->extension_items.end(), this); + if (it != obj->extension_items.end()) + obj->extension_items.erase(it); + delete value; } - T* Get(const Extensible *obj) const + T* Get(Extensible *obj) { - std::map<Extensible *, void *>::const_iterator it = items.find(const_cast<Extensible *>(obj)); + std::map<Extensible *, void *>::const_iterator it = items.find(obj); if (it != items.end()) return static_cast<T *>(it->second); - return NULL; + return nullptr; } - bool HasExt(const Extensible *obj) const + bool HasExt(Extensible *obj) { - return items.find(const_cast<Extensible *>(obj)) != items.end(); + return items.find(obj) != items.end(); } T* Require(Extensible *obj) @@ -118,98 +109,19 @@ class BaseExtensibleItem : public ExtensibleBase if (t) return t; - return Set(obj); + return Set(obj, T()); } }; template<typename T> -class ExtensibleItem : public BaseExtensibleItem<T> +struct ExtensibleRef : ServiceReference<ExtensibleItem<T>> { - protected: - T* Create(Extensible *obj) override - { - return new T(obj); - } - public: - ExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { } + ExtensibleRef(const Anope::string &n) : ServiceReference<ExtensibleItem<T>>("Extensible", n) { } + ExtensibleRef(const Anope::string &t, const Anope::string &n) : ServiceReference<ExtensibleItem<T>>(t, n) { } }; template<typename T> -class PrimitiveExtensibleItem : public BaseExtensibleItem<T> -{ - protected: - T* Create(Extensible *obj) override - { - return new T(); - } - public: - PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { } -}; - -template<> -class PrimitiveExtensibleItem<bool> : public BaseExtensibleItem<bool> -{ - protected: - bool* Create(Extensible *) override - { - return NULL; - } - public: - PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<bool>(m, n) { } -}; - -template<typename T> -class SerializableExtensibleItem : public PrimitiveExtensibleItem<T> -{ - public: - SerializableExtensibleItem(Module *m, const Anope::string &n) : PrimitiveExtensibleItem<T>(m, n) { } - - void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override - { - T* t = this->Get(e); - data[this->name] << *t; - } - - void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override - { - T t; - if (data[this->name] >> t) - this->Set(e, t); - else - this->Unset(e); - } -}; - -template<> -class SerializableExtensibleItem<bool> : public PrimitiveExtensibleIte |
