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