anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

serialize.h (7963B)

      1 /*
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  *
      8  * Based on the original code of Epona by Lara.
      9  * Based on the original code of Services by Andy Church.
     10  */
     11 
     12 #ifndef SERIALIZE_H
     13 #define SERIALIZE_H
     14 
     15 #include <sstream>
     16 
     17 #include "anope.h"
     18 #include "base.h"
     19 
     20 namespace Serialize
     21 {
     22 	class Data
     23 	{
     24 	 public:
     25 		enum Type
     26 		{
     27 			DT_TEXT,
     28 			DT_INT
     29 		};
     30 
     31 		virtual ~Data() { }
     32 
     33 		virtual std::iostream& operator[](const Anope::string &key) = 0;
     34 		virtual std::set<Anope::string> KeySet() const { throw CoreException("Not supported"); }
     35 		virtual size_t Hash() const { throw CoreException("Not supported"); }
     36 
     37 		virtual void SetType(const Anope::string &key, Type t) { }
     38 		virtual Type GetType(const Anope::string &key) const { return DT_TEXT; }
     39 	};
     40 
     41 	extern void RegisterTypes();
     42 	extern void CheckTypes();
     43 
     44 	class Type;
     45 	template<typename T> class Checker;
     46 	template<typename T> class Reference;
     47 }
     48 
     49 /** A serializable object. Serializable objects can be serialized into
     50  * abstract data types (Serialize::Data), and then reconstructed or
     51  * updated later at any time.
     52  */
     53 class CoreExport Serializable : public virtual Base
     54 {
     55  private:
     56 	/* A list of every serializable item in Anope.
     57 	 * Some of these are static and constructed at runtime,
     58 	 * so this list must be on the heap, as it is not always
     59 	 * constructed before other objects are if it isn't.
     60 	 */
     61 	static std::list<Serializable *> *SerializableItems;
     62 	friend class Serialize::Type;
     63 	/* The type of item this object is */
     64 	Serialize::Type *s_type;
     65 	/* Iterator into serializable_items */
     66 	std::list<Serializable *>::iterator s_iter;
     67 	/* The hash of the last serialized form of this object committed to the database */
     68 	size_t last_commit;
     69 	/* The last time this object was committed to the database */
     70 	time_t last_commit_time;
     71 
     72  protected:
     73 	Serializable(const Anope::string &serialize_type);
     74 	Serializable(const Serializable &);
     75 
     76 	Serializable &operator=(const Serializable &);
     77 
     78  public:
     79 	virtual ~Serializable();
     80 
     81 	/* Unique ID (per type, not globally) for this object */
     82 	uint64_t id;
     83 
     84 	/* Only used by redis, to ignore updates */
     85 	unsigned short redis_ignore;
     86 
     87 	/** Marks the object as potentially being updated "soon".
     88 	 */
     89 	void QueueUpdate();
     90 
     91 	bool IsCached(Serialize::Data &);
     92 	void UpdateCache(Serialize::Data &);
     93 
     94 	bool IsTSCached();
     95 	void UpdateTS();
     96 
     97 	/** Get the type of serializable object this is
     98 	 * @return The serializable object type
     99 	 */
    100 	Serialize::Type* GetSerializableType() const { return this->s_type; }
    101 
    102 	virtual void Serialize(Serialize::Data &data) const = 0;
    103 
    104 	static const std::list<Serializable *> &GetItems();
    105 };
    106 
    107 /* A serializable type. There should be one of these classes for each type
    108  * of class that inherits from Serializable. Used for unserializing objects
    109  * of this type, as it requires a function pointer to a static member function.
    110  */
    111 class CoreExport Serialize::Type : public Base
    112 {
    113 	typedef Serializable* (*unserialize_func)(Serializable *obj, Serialize::Data &);
    114 
    115 	static std::vector<Anope::string> TypeOrder;
    116 	static std::map<Anope::string, Serialize::Type *> Types;
    117 
    118 	/* The name of this type, should be a class name */
    119 	Anope::string name;
    120 	unserialize_func unserialize;
    121 	/* Owner of this type. Used for placing objects of this type in separate databases
    122 	 * based on what module, if any, owns it.
    123 	 */
    124 	Module *owner;
    125 
    126 	/* The timestamp for this type. All objects of this type are as up to date as
    127 	 * this timestamp. if curtime == timestamp then we have the most up to date
    128 	 * version of every object of this type.
    129 	 */
    130 	time_t timestamp;
    131 
    132  public:
    133 	/* Map of Serializable::id to Serializable objects */
    134 	std::map<uint64_t, Serializable *> objects;
    135 
    136 	/** Creates a new serializable type
    137 	 * @param n Type name
    138 	 * @param f Func to unserialize objects
    139 	 * @param owner Owner of this type. Leave NULL for the core.
    140 	 */
    141 	Type(const Anope::string &n, unserialize_func f, Module *owner = NULL);
    142 	~Type();
    143 
    144 	/** Gets the name for this type
    145 	 * @return The name, eg "NickAlias"
    146 	 */
    147 	const Anope::string &GetName() { return this->name; }
    148 
    149 	/** Unserialized an object.
    150 	 * @param obj NULL if this object doesn't yet exist. If this isn't NULL, instead
    151 	 * update the contents of this object.
    152 	 * @param data The data to unserialize
    153 	 * @return The unserialized object. If obj != NULL this should be obj.
    154 	 */
    155 	Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
    156 
    157 	/** Check if this object type has any pending changes and update them.
    158 	 */
    159 	void Check();
    160 
    161 	/** Gets the timestamp for the object type. That is, the time we know
    162 	 * all objects of this type are updated at least to.
    163 	 */
    164 	time_t GetTimestamp() const;
    165 
    166 	/** Bumps object type timestamp to current time
    167 	 */
    168 	void UpdateTimestamp();
    169 
    170 	Module* GetOwner() const { return this->owner; }
    171 
    172 	static Serialize::Type *Find(const Anope::string &name);
    173 
    174 	static const std::vector<Anope::string> &GetTypeOrder();
    175 
    176 	static const std::map<Anope::string, Serialize::Type *>& GetTypes();
    177 };
    178 
    179 /** Should be used to hold lists and other objects of a specific type,
    180  * but not a specific object. Used for ensuring that any access to
    181  * this object type is always up to date. These are usually constructed
    182  * at run time, before main is called, so no types are registered. This
    183  * is why there are static Serialize::Type* variables in every function.
    184  */
    185 template<typename T>
    186 class Serialize::Checker
    187 {
    188 	Anope::string name;
    189 	T obj;
    190 	mutable ::Reference<Serialize::Type> type;
    191 
    192 	inline void Check() const
    193 	{
    194 		if (!type)
    195 			type = Serialize::Type::Find(this->name);
    196 		if (type)
    197 			type->Check();
    198 	}
    199 
    200  public:
    201 	Checker(const Anope::string &n) : name(n), type(NULL) { }
    202 
    203 	inline const T* operator->() const
    204 	{
    205 		this->Check();
    206 		return &this->obj;
    207 	}
    208 	inline T* operator->()
    209 	{
    210 		this->Check();
    211 		return &this->obj;
    212 	}
    213 
    214 	inline const T& operator*() const
    215 	{
    216 		this->Check();
    217 		return this->obj;
    218 	}
    219 	inline T& operator*()
    220 	{
    221 		this->Check();
    222 		return this->obj;
    223 	}
    224 
    225 	inline operator const T&() const
    226 	{
    227 		this->Check();
    228 		return this->obj;
    229 	}
    230 	inline operator T&()
    231 	{
    232 		this->Check();
    233 		return this->obj;
    234 	}
    235 };
    236 
    237 /** Used to hold references to serializable objects. Reference should always be
    238  * used when holding references to serializable objects for extended periods of time
    239  * to ensure that the object it refers to it always up to date. This also behaves like
    240  * Reference in that it will invalidate itself if the object it refers to is
    241  * destructed.
    242  */
    243 template<typename T>
    244 class Serialize::Reference : public ReferenceBase
    245 {
    246  protected:
    247 	T *ref;
    248 
    249  public:
    250 	Reference() : ref(NULL)
    251 	{
    252 	}
    253 
    254 	Reference(T *obj) : ref(obj)
    255 	{
    256 		if (obj)
    257 			obj->AddReference(this);
    258 	}
    259 
    260 	Reference(const Reference<T> &other) : ReferenceBase(other), ref(other.ref)
    261 	{
    262 		if (ref && !invalid)
    263 			this->ref->AddReference(this);
    264 	}
    265 
    266 	~Reference()
    267 	{
    268 		if (ref && !invalid)
    269 			this->ref->DelReference(this);
    270 	}
    271 
    272 	inline Reference<T>& operator=(const Reference<T> &other)
    273 	{
    274 		if (this != &other)
    275 		{
    276 			if (ref && !invalid)
    277 				this->ref->DelReference(this);
    278 
    279 			this->ref = other.ref;
    280 			this->invalid = other.invalid;
    281 
    282 			if (ref && !invalid)
    283 				this->ref->AddReference(this);
    284 		}
    285 		return *this;
    286 	}
    287 
    288 	inline operator bool() const
    289 	{
    290 		if (!this->invalid)
    291 			return this->ref != NULL;
    292 		return false;
    293 	}
    294 
    295 	inline operator T*() const
    296 	{
    297 		if (!this->invalid)
    298 		{
    299 			if (this->ref)
    300 				// This can invalidate me
    301 				this->ref->QueueUpdate();
    302 			if (!this->invalid)
    303 				return this->ref;
    304 		}
    305 		return NULL;
    306 	}
    307 
    308 	inline T* operator*() const
    309 	{
    310 		if (!this->invalid)
    311 		{
    312 			if (this->ref)
    313 				// This can invalidate me
    314 				this->ref->QueueUpdate();
    315 			if (!this->invalid)
    316 				return this->ref;
    317 		}
    318 		return NULL;
    319 	}
    320 
    321 	inline T* operator->() const
    322 	{
    323 		if (!this->invalid)
    324 		{
    325 			if (this->ref)
    326 				// This can invalidate me
    327 				this->ref->QueueUpdate();
    328 			if (!this->invalid)
    329 				return this->ref;
    330 		}
    331 		return NULL;
    332 	}
    333 };
    334 
    335 #endif // SERIALIZE_H