mirror of
https://github.com/anope/anope.git
synced 2026-06-12 19:14:47 +02:00
Optimize much of the database code and serialize code.
This commit is contained in:
@@ -353,13 +353,6 @@ check_function_exists(epoll_wait HAVE_EPOLL)
|
||||
check_function_exists(poll HAVE_POLL)
|
||||
check_function_exists(kqueue HAVE_KQUEUE)
|
||||
|
||||
# Check if eventfd works
|
||||
try_run(EVENTFD_TEST_RUN_RESULT EVENTFD_TEST_COMPILE_RESULT ${CMAKE_CURRENT_BINARY_DIR} ${Anope_SOURCE_DIR}/cmake/eventfd_test.cpp)
|
||||
set(HAVE_EVENTFD FALSE)
|
||||
if (EVENTFD_TEST_COMPILE_RESULT AND EVENTFD_TEST_RUN_RESULT EQUAL 1)
|
||||
set(HAVE_EVENTFD TRUE)
|
||||
endif(EVENTFD_TEST_COMPILE_RESULT AND EVENTFD_TEST_RUN_RESULT EQUAL 1)
|
||||
|
||||
# Strip the leading and trailing spaces from the compile flags
|
||||
if(CXXFLAGS)
|
||||
strip_string(${CXXFLAGS} CXXFLAGS)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = eventfd(0, EFD_NONBLOCK);
|
||||
return i >= 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
+11
-1
@@ -1135,6 +1135,15 @@ db_flatfile
|
||||
* The database name db_flatfile should use
|
||||
*/
|
||||
database = "anope.db"
|
||||
|
||||
/*
|
||||
* If enabled, services will fork a child process to save databases.
|
||||
*
|
||||
* This is only useful with very large databases, with hundreds
|
||||
* of thousands of objects, that have a noticable delay from
|
||||
* writing databases.
|
||||
*/
|
||||
fork = no
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1154,7 +1163,8 @@ db_flatfile
|
||||
* This module allows saving and loading databases using one of the SQL engines.
|
||||
* This module reads and writes to SQL in real time. Changes to the SQL tables
|
||||
* will be immediately reflected into Anope. This module should not be loaded
|
||||
* in conjunction with db_sql.
|
||||
* in conjunction with db_sql, except during the initial import of existing
|
||||
* databases to SQL.
|
||||
*/
|
||||
#module { name = "db_sql_live" }
|
||||
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ class CoreExport ChanAccess : public Serializable
|
||||
ChanAccess(AccessProvider *p);
|
||||
virtual ~ChanAccess();
|
||||
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Check if this access entry matches the given user or account
|
||||
|
||||
+2
-2
@@ -122,7 +122,7 @@ class CoreExport NickAlias : public Serializable, public Extensible, public Flag
|
||||
NickAlias(const Anope::string &nickname, NickCore *nickcore);
|
||||
~NickAlias();
|
||||
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Release a nick
|
||||
@@ -227,7 +227,7 @@ class CoreExport NickCore : public Serializable, public Extensible, public Flags
|
||||
NickCore(const Anope::string &nickdisplay);
|
||||
~NickCore();
|
||||
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Changes the display for this account
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#ifndef ANOPE_H
|
||||
#define ANOPE_H
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "hashcomp.h"
|
||||
|
||||
namespace Anope
|
||||
@@ -282,9 +284,12 @@ namespace Anope
|
||||
* Stream insertion operator, must be friend because they cannot be inside the class.
|
||||
*/
|
||||
friend std::ostream &operator<<(std::ostream &os, const string &_str);
|
||||
friend std::istream &operator>>(std::istream &is, string &_str);
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const string &_str) { return os << _str._string; }
|
||||
/* This is not standard to make operator>> behave like operator<< in that it will allow extracting a whole line, not just one word */
|
||||
inline std::istream &operator>>(std::istream &is, string &_str) { return std::getline(is, _str._string); }
|
||||
|
||||
inline const string operator+(char chr, const string &str) { string tmp(chr); tmp += str; return tmp; }
|
||||
inline const string operator+(const char *_str, const string &str) { string tmp(_str); tmp += str; return tmp; }
|
||||
@@ -318,6 +323,8 @@ namespace Anope
|
||||
/** The value to return from main()
|
||||
*/
|
||||
extern int ReturnValue;
|
||||
|
||||
extern sig_atomic_t Signal;
|
||||
extern bool Quitting;
|
||||
extern bool Restarting;
|
||||
extern Anope::string QuitReason;
|
||||
@@ -376,6 +383,10 @@ namespace Anope
|
||||
*/
|
||||
extern void Fork();
|
||||
|
||||
/** Does something with the signal in Anope::Signal
|
||||
*/
|
||||
extern void HandleSignal();
|
||||
|
||||
/** One of the first functions called, does general initialization such as reading
|
||||
* command line args, loading the configuration, doing the initial fork() if necessary,
|
||||
* initializating language support, loading modules, and loading databases.
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
class CoreExport Base
|
||||
{
|
||||
/* References to this base class */
|
||||
std::set<ReferenceBase *> references;
|
||||
std::set<ReferenceBase *> *references;
|
||||
public:
|
||||
Base();
|
||||
virtual ~Base();
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ class CoreExport BotInfo : public User, public Flags<BotFlag>, public Serializab
|
||||
*/
|
||||
virtual ~BotInfo();
|
||||
|
||||
Serialize::Data Serialize() const;
|
||||
void Serialize(Serialize::Data &data) const;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
void GenerateUID();
|
||||
|
||||
+29
-17
@@ -38,22 +38,25 @@ class CoreExport Extensible
|
||||
{
|
||||
private:
|
||||
typedef std::map<Anope::string, ExtensibleItem *> extensible_map;
|
||||
extensible_map extension_items;
|
||||
extensible_map *extension_items;
|
||||
|
||||
public:
|
||||
/** Default constructor, does nothing
|
||||
/** Default constructor
|
||||
*/
|
||||
Extensible() { }
|
||||
Extensible() : extension_items(NULL) { }
|
||||
|
||||
/** Destructor, deletes all of the extensible items in this object
|
||||
* then clears the map
|
||||
*/
|
||||
virtual ~Extensible()
|
||||
{
|
||||
for (extensible_map::iterator it = extension_items.begin(), it_end = extension_items.end(); it != it_end; ++it)
|
||||
if (it->second)
|
||||
it->second->OnDelete();
|
||||
extension_items.clear();
|
||||
if (extension_items)
|
||||
{
|
||||
for (extensible_map::iterator it = extension_items->begin(), it_end = extension_items->end(); it != it_end; ++it)
|
||||
if (it->second)
|
||||
it->second->OnDelete();
|
||||
delete extension_items;
|
||||
}
|
||||
}
|
||||
|
||||
/** Extend an Extensible class.
|
||||
@@ -70,7 +73,9 @@ class CoreExport Extensible
|
||||
void Extend(const Anope::string &key, ExtensibleItem *p)
|
||||
{
|
||||
this->Shrink(key);
|
||||
this->extension_items[key] = p;
|
||||
if (!extension_items)
|
||||
extension_items = new extensible_map();
|
||||
(*this->extension_items)[key] = p;
|
||||
}
|
||||
|
||||
/** Shrink an Extensible class.
|
||||
@@ -83,8 +88,11 @@ class CoreExport Extensible
|
||||
*/
|
||||
bool Shrink(const Anope::string &key)
|
||||
{
|
||||
extensible_map::iterator it = this->extension_items.find(key);
|
||||
if (it != this->extension_items.end())
|
||||
if (!extension_items)
|
||||
return false;
|
||||
|
||||
extensible_map::iterator it = this->extension_items->find(key);
|
||||
if (it != this->extension_items->end())
|
||||
{
|
||||
if (it->second != NULL)
|
||||
it->second->OnDelete();
|
||||
@@ -92,7 +100,7 @@ class CoreExport Extensible
|
||||
* returns the number of elements removed, std::map
|
||||
* is single-associative so this should only be 0 or 1
|
||||
*/
|
||||
return this->extension_items.erase(key) > 0;
|
||||
return this->extension_items->erase(key) > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -105,9 +113,12 @@ class CoreExport Extensible
|
||||
*/
|
||||
template<typename T> T GetExt(const Anope::string &key) const
|
||||
{
|
||||
extensible_map::const_iterator it = this->extension_items.find(key);
|
||||
if (it != this->extension_items.end())
|
||||
return anope_dynamic_static_cast<T>(it->second);
|
||||
if (this->extension_items)
|
||||
{
|
||||
extensible_map::const_iterator it = this->extension_items->find(key);
|
||||
if (it != this->extension_items->end())
|
||||
return anope_dynamic_static_cast<T>(it->second);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -119,7 +130,7 @@ class CoreExport Extensible
|
||||
*/
|
||||
bool HasExt(const Anope::string &key) const
|
||||
{
|
||||
return this->extension_items.count(key) > 0;
|
||||
return this->extension_items != NULL && this->extension_items->count(key) > 0;
|
||||
}
|
||||
|
||||
/** Get a list of all extension items names.
|
||||
@@ -129,8 +140,9 @@ class CoreExport Extensible
|
||||
*/
|
||||
void GetExtList(std::deque<Anope::string> &list) const
|
||||
{
|
||||
for (extensible_map::const_iterator it = extension_items.begin(), it_end = extension_items.end(); it != it_end; ++it)
|
||||
list.push_back(it->first);
|
||||
if (extension_items)
|
||||
for (extensible_map::const_iterator it = extension_items->begin(), it_end = extension_items->end(); it != it_end; ++it)
|
||||
list.push_back(it->first);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ class CoreExport Memo : public Flags<MemoFlag>, public Serializable
|
||||
public:
|
||||
Memo();
|
||||
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
Anope::string owner;
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include "servers.h"
|
||||
#include "service.h"
|
||||
#include "services.h"
|
||||
#include "signals.h"
|
||||
#include "socketengine.h"
|
||||
#include "sockets.h"
|
||||
#include "threadengine.h"
|
||||
|
||||
@@ -143,7 +143,7 @@ struct CoreExport BadWord : Serializable
|
||||
BadWordType type;
|
||||
|
||||
BadWord() : Serializable("BadWord") { }
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
};
|
||||
|
||||
@@ -172,7 +172,7 @@ class CoreExport AutoKick : public Flags<AutoKickFlag>, public Serializable
|
||||
time_t last_used;
|
||||
|
||||
AutoKick();
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
};
|
||||
|
||||
@@ -188,7 +188,7 @@ struct CoreExport ModeLock : Serializable
|
||||
|
||||
ModeLock(ChannelInfo *ch, bool s, ChannelModeName n, const Anope::string &p, const Anope::string &se = "", time_t c = Anope::CurTime);
|
||||
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
};
|
||||
|
||||
@@ -206,7 +206,7 @@ struct CoreExport LogSetting : Serializable
|
||||
time_t created;
|
||||
|
||||
LogSetting() : Serializable("LogSetting") { }
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
};
|
||||
|
||||
@@ -263,7 +263,7 @@ class CoreExport ChannelInfo : public Serializable, public Extensible, public Fl
|
||||
|
||||
~ChannelInfo();
|
||||
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Change the founder of the channek
|
||||
|
||||
+20
-37
@@ -20,42 +20,25 @@
|
||||
|
||||
namespace Serialize
|
||||
{
|
||||
enum DataType
|
||||
class Data
|
||||
{
|
||||
DT_TEXT,
|
||||
DT_INT
|
||||
};
|
||||
|
||||
class CoreExport stringstream : public std::stringstream
|
||||
{
|
||||
private:
|
||||
Serialize::DataType type;
|
||||
unsigned _max;
|
||||
|
||||
public:
|
||||
stringstream();
|
||||
stringstream(const stringstream &ss);
|
||||
Anope::string astr() const;
|
||||
|
||||
template<typename T> std::istream &operator>>(T &val)
|
||||
enum Type
|
||||
{
|
||||
std::istringstream is(this->str());
|
||||
is >> val;
|
||||
return *this;
|
||||
}
|
||||
std::istream &operator>>(Anope::string &val);
|
||||
DT_TEXT,
|
||||
DT_INT
|
||||
};
|
||||
|
||||
bool operator==(const stringstream &other) const;
|
||||
bool operator!=(const stringstream &other) const;
|
||||
virtual ~Data() { }
|
||||
|
||||
stringstream &SetType(Serialize::DataType t);
|
||||
Serialize::DataType GetType() const;
|
||||
stringstream &SetMax(unsigned m);
|
||||
unsigned GetMax() const;
|
||||
virtual std::iostream& operator[](const Anope::string &key) = 0;
|
||||
|
||||
virtual bool IsEqual(Data *other) { throw CoreException("Not supported"); }
|
||||
|
||||
virtual void SetType(const Anope::string &key, Type t) { }
|
||||
virtual Type GetType(const Anope::string &key) const { return DT_TEXT; }
|
||||
};
|
||||
|
||||
typedef std::map<Anope::string, stringstream> Data;
|
||||
|
||||
extern void RegisterTypes();
|
||||
|
||||
class Type;
|
||||
@@ -64,7 +47,7 @@ namespace Serialize
|
||||
}
|
||||
|
||||
/** A serialziable object. Serializable objects can be serialized into
|
||||
* a map of stringstreams (Serialize::Data), and then reconstructed or
|
||||
* abstract data types (Serialize::Data), and then reconstructed or
|
||||
* updated later at any time.
|
||||
*/
|
||||
class CoreExport Serializable : public virtual Base
|
||||
@@ -82,7 +65,7 @@ class CoreExport Serializable : public virtual Base
|
||||
/* Iterator into serializable_items */
|
||||
std::list<Serializable *>::iterator s_iter;
|
||||
/* The last serialized form of this object commited to the database */
|
||||
Serialize::Data last_commit;
|
||||
Serialize::Data *last_commit;
|
||||
/* The last time this object was commited to the database */
|
||||
time_t last_commit_time;
|
||||
|
||||
@@ -108,8 +91,8 @@ class CoreExport Serializable : public virtual Base
|
||||
*/
|
||||
void QueueUpdate();
|
||||
|
||||
bool IsCached();
|
||||
void UpdateCache();
|
||||
bool IsCached(Serialize::Data *);
|
||||
void UpdateCache(Serialize::Data *);
|
||||
|
||||
bool IsTSCached();
|
||||
void UpdateTS();
|
||||
@@ -117,9 +100,9 @@ class CoreExport Serializable : public virtual Base
|
||||
/** Get the type of serializable object this is
|
||||
* @return The serializable object type
|
||||
*/
|
||||
Serialize::Type* GetSerializableType() const;
|
||||
Serialize::Type* GetSerializableType() const { return this->s_type; }
|
||||
|
||||
virtual Serialize::Data Serialize() const = 0;
|
||||
virtual void Serialize(Serialize::Data &data) const = 0;
|
||||
|
||||
static const std::list<Serializable *> &GetItems();
|
||||
};
|
||||
@@ -164,7 +147,7 @@ class CoreExport Serialize::Type
|
||||
/** Gets the name for this type
|
||||
* @return The name, eg "NickAlias"
|
||||
*/
|
||||
const Anope::string &GetName();
|
||||
const Anope::string &GetName() { return this->name; }
|
||||
|
||||
/** Unserialized an object.
|
||||
* @param obj NULL if this object doesn't yet exist. If this isn't NULL, instead
|
||||
@@ -187,7 +170,7 @@ class CoreExport Serialize::Type
|
||||
*/
|
||||
void UpdateTimestamp();
|
||||
|
||||
Module* GetOwner() const;
|
||||
Module* GetOwner() const { return this->owner; }
|
||||
|
||||
static Serialize::Type *Find(const Anope::string &name);
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2003-2012 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SIGNAL_H
|
||||
#define SIGNAL_H
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "sockets.h"
|
||||
|
||||
/** Represents a signal handler
|
||||
*/
|
||||
class Signal : public Pipe
|
||||
{
|
||||
static std::vector<Signal *> SignalHandlers;
|
||||
static void SignalHandler(int signal);
|
||||
|
||||
struct sigaction action, old;
|
||||
public:
|
||||
int signal;
|
||||
|
||||
/** Constructor
|
||||
* @param s The signal to listen for
|
||||
*/
|
||||
Signal(int s);
|
||||
~Signal();
|
||||
|
||||
/**
|
||||
* Called when the signal is received.
|
||||
* Note this is not *immediatly* called when the signal is received,
|
||||
* but it is saved and called at a later time when we are not doing something
|
||||
* important. This is always called on the main thread, even on systems that
|
||||
* spawn threads for signals, like Windows.
|
||||
*/
|
||||
virtual void OnNotify() anope_override = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
class CoreExport SocketEngine
|
||||
{
|
||||
static const int DefaultSize = 8; // Uplink, DNS, Signal handlers, Mode stacker
|
||||
static const int DefaultSize = 2; // Uplink, mode stacker
|
||||
public:
|
||||
/* Map of sockets */
|
||||
static std::map<int, Socket *> Sockets;
|
||||
|
||||
+25
-8
@@ -225,15 +225,11 @@ class CoreExport Socket : public Flags<SocketFlag>
|
||||
*/
|
||||
bool IsIPv6() const;
|
||||
|
||||
/** Mark a socket as blocking
|
||||
/** Mark a socket as (non)blocking
|
||||
* @param state true to enable blocking, false to disable blocking
|
||||
* @return true if the socket is now blocking
|
||||
*/
|
||||
bool SetBlocking();
|
||||
|
||||
/** Mark a socket as non-blocking
|
||||
* @return true if the socket is now non-blocking
|
||||
*/
|
||||
bool SetNonBlocking();
|
||||
bool SetBlocking(bool state);
|
||||
|
||||
/** Bind the socket to an ip and port
|
||||
* @param ip The ip
|
||||
@@ -456,7 +452,7 @@ class CoreExport ClientSocket : public virtual Socket
|
||||
class CoreExport Pipe : public Socket
|
||||
{
|
||||
public:
|
||||
/** The FD of the write pipe (if this isn't evenfd)
|
||||
/** The FD of the write pipe
|
||||
* this->sock is the readfd
|
||||
*/
|
||||
int write_pipe;
|
||||
@@ -468,7 +464,28 @@ class CoreExport Pipe : public Socket
|
||||
*/
|
||||
bool ProcessRead() anope_override;
|
||||
|
||||
/** Write data to this pipe
|
||||
* @param data The data to write
|
||||
* @param sz The amount of data to wirite
|
||||
*/
|
||||
void Write(const char *data, size_t sz);
|
||||
inline void Write(const Anope::string &data) { this->Write(data.c_str(), data.length() + 1); }
|
||||
|
||||
/** Read data from this pipe
|
||||
* @param data A buffer to read data into
|
||||
* @param sz The size of the buffer
|
||||
* @return The amount of data read
|
||||
*/
|
||||
int Read(char *data, size_t sz);
|
||||
|
||||
/** Mark the write end of this pipe (non)blocking
|
||||
* @param state true to enable blocking, false to disable blocking
|
||||
* @return true if the socket is now blocking
|
||||
*/
|
||||
bool SetWriteBlocking(bool state);
|
||||
|
||||
/** Called when this pipe needs to be woken up
|
||||
* Is the same as Write("\0", 1)
|
||||
*/
|
||||
void Notify();
|
||||
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ class CoreExport XLine : public Serializable
|
||||
bool HasNickOrReal() const;
|
||||
bool IsRegex() const;
|
||||
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
};
|
||||
|
||||
|
||||
@@ -28,16 +28,12 @@ struct EntryMsg : Serializable
|
||||
this->when = ct;
|
||||
}
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &data) const anope_override
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["ci"] << this->ci->name;
|
||||
data["creator"] << this->creator;
|
||||
data["message"] << this->message;
|
||||
data["when"].SetType(Serialize::DT_INT) << this->when;
|
||||
|
||||
return data;
|
||||
data.SetType("when", Serialize::Data::DT_INT); data["when"] << this->when;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
@@ -52,7 +48,13 @@ struct EntryMessageList : Serialize::Checker<std::vector<EntryMsg *> >, Extensib
|
||||
|
||||
Serializable* EntryMsg::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
ChannelInfo *ci = ChannelInfo::Find(data["ci"].astr());
|
||||
Anope::string sci, screator, smessage;
|
||||
|
||||
data["ci"] >> sci;
|
||||
data["creator"] >> screator;
|
||||
data["message"] >> smessage;
|
||||
|
||||
ChannelInfo *ci = ChannelInfo::Find(sci);
|
||||
if (!ci)
|
||||
return NULL;
|
||||
|
||||
@@ -73,7 +75,7 @@ Serializable* EntryMsg::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
ci->Extend("cs_entrymsg", messages);
|
||||
}
|
||||
|
||||
EntryMsg *m = new EntryMsg(ci, data["creator"].astr(), data["message"].astr());
|
||||
EntryMsg *m = new EntryMsg(ci, screator, smessage);
|
||||
(*messages)->push_back(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
#include "module.h"
|
||||
#include "../extra/sql.h"
|
||||
|
||||
class MySQLInterface : public SQLInterface
|
||||
class MySQLInterface : public SQL::Interface
|
||||
{
|
||||
public:
|
||||
MySQLInterface(Module *o) : SQLInterface(o) { }
|
||||
MySQLInterface(Module *o) : SQL::Interface(o) { }
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
void OnResult(const SQL::Result &r) anope_override
|
||||
{
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r) anope_override
|
||||
void OnError(const SQL::Result &r) anope_override
|
||||
{
|
||||
if (!r.GetQuery().query.empty())
|
||||
Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
|
||||
@@ -66,7 +66,7 @@ class CSStats : public Module
|
||||
{
|
||||
CommandCSStats commandcsstats;
|
||||
CommandCSGStats commandcsgstats;
|
||||
ServiceReference<SQLProvider> sql;
|
||||
ServiceReference<SQL::Provider> sql;
|
||||
MySQLInterface sqlinterface;
|
||||
Anope::string prefix;
|
||||
public:
|
||||
@@ -86,17 +86,17 @@ class CSStats : public Module
|
||||
ConfigReader config;
|
||||
prefix = config.ReadValue("chanstats", "prefix", "anope_", 0);
|
||||
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
|
||||
this->sql = ServiceReference<SQLProvider>("SQLProvider", engine);
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
|
||||
}
|
||||
|
||||
SQLResult RunQuery(const SQLQuery &query)
|
||||
SQL::Result RunQuery(const SQL::Query &query)
|
||||
{
|
||||
if (!this->sql)
|
||||
throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
|
||||
throw SQL::Exception("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
|
||||
|
||||
SQLResult res = this->sql->RunQuery(query);
|
||||
SQL::Result res = this->sql->RunQuery(query);
|
||||
if (!res.GetError().empty())
|
||||
throw SQLException(res.GetError());
|
||||
throw SQL::Exception(res.GetError());
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -118,16 +118,16 @@ class CSStats : public Module
|
||||
|
||||
try
|
||||
{
|
||||
SQLQuery query;
|
||||
SQL::Query query;
|
||||
query = "SELECT letters, words, line, smileys_happy+smileys_sad+smileys_other as smileys,"
|
||||
"actions FROM `" + prefix + "chanstats` "
|
||||
"WHERE `nick` = @nick@ AND `chan` = @channel@ AND `type` = 'total';";
|
||||
if (is_global)
|
||||
query.setValue("channel", "");
|
||||
query.SetValue("channel", "");
|
||||
else
|
||||
query.setValue("channel", source.c->ci->name);
|
||||
query.setValue("nick", display);
|
||||
SQLResult res = this->RunQuery(query);
|
||||
query.SetValue("channel", source.c->ci->name);
|
||||
query.SetValue("nick", display);
|
||||
SQL::Result res = this->RunQuery(query);
|
||||
|
||||
if (res.Rows() > 0)
|
||||
{
|
||||
@@ -144,7 +144,7 @@ class CSStats : public Module
|
||||
else
|
||||
source.Reply(_("No stats for %s"), display.c_str());
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
catch (const SQL::Exception &ex)
|
||||
{
|
||||
Log(LOG_DEBUG) << ex.GetReason();
|
||||
}
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
#include "module.h"
|
||||
#include "../extra/sql.h"
|
||||
|
||||
class MySQLInterface : public SQLInterface
|
||||
class MySQLInterface : public SQL::Interface
|
||||
{
|
||||
public:
|
||||
MySQLInterface(Module *o) : SQLInterface(o) { }
|
||||
MySQLInterface(Module *o) : SQL::Interface(o) { }
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
void OnResult(const SQL::Result &r) anope_override
|
||||
{
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r) anope_override
|
||||
void OnError(const SQL::Result &r) anope_override
|
||||
{
|
||||
if (!r.GetQuery().query.empty())
|
||||
Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
|
||||
@@ -93,7 +93,7 @@ class CSTop : public Module
|
||||
CommandCSGTop commandcsgtop;
|
||||
CommandCSTop10 commandcstop10;
|
||||
CommandCSGTop10 commandcsgtop10;
|
||||
ServiceReference<SQLProvider> sql;
|
||||
ServiceReference<SQL::Provider> sql;
|
||||
MySQLInterface sqlinterface;
|
||||
Anope::string prefix;
|
||||
|
||||
@@ -115,17 +115,17 @@ class CSTop : public Module
|
||||
ConfigReader config;
|
||||
prefix = config.ReadValue("chanstats", "prefix", "anope_", 0);
|
||||
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
|
||||
this->sql = ServiceReference<SQLProvider>("SQLProvider", engine);
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
|
||||
}
|
||||
|
||||
SQLResult RunQuery(const SQLQuery &query)
|
||||
SQL::Result RunQuery(const SQL::Query &query)
|
||||
{
|
||||
if (!this->sql)
|
||||
throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
|
||||
throw SQL::Exception("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
|
||||
|
||||
SQLResult res = sql->RunQuery(query);
|
||||
SQL::Result res = sql->RunQuery(query);
|
||||
if (!res.GetError().empty())
|
||||
throw SQLException(res.GetError());
|
||||
throw SQL::Exception(res.GetError());
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -147,20 +147,20 @@ class CSTop : public Module
|
||||
|
||||
try
|
||||
{
|
||||
SQLQuery query;
|
||||
SQL::Query query;
|
||||
query = "SELECT nick, letters, words, line, actions,"
|
||||
"smileys_happy+smileys_sad+smileys_other as smileys "
|
||||
"FROM `" + prefix + "chanstats` "
|
||||
"WHERE `nick` != '' AND `chan` = @channel@ AND `type` = 'total' "
|
||||
"ORDER BY `letters` DESC LIMIT @limit@;";
|
||||
query.setValue("limit", limit, false);
|
||||
query.SetValue("limit", limit, false);
|
||||
|
||||
if (is_global)
|
||||
query.setValue("channel", "");
|
||||
query.SetValue("channel", "");
|
||||
else
|
||||
query.setValue("channel", channel.c_str());
|
||||
query.SetValue("channel", channel.c_str());
|
||||
|
||||
SQLResult res = this->RunQuery(query);
|
||||
SQL::Result res = this->RunQuery(query);
|
||||
|
||||
if (res.Rows() > 0)
|
||||
{
|
||||
@@ -176,7 +176,7 @@ class CSTop : public Module
|
||||
else
|
||||
source.Reply(_("No stats for %s"), is_global ? "Network" : channel.c_str());
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
catch (const SQL::Exception &ex)
|
||||
{
|
||||
Log(LOG_DEBUG) << ex.GetReason();
|
||||
}
|
||||
|
||||
@@ -38,30 +38,30 @@ struct SeenInfo : Serializable
|
||||
{
|
||||
}
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &data) const anope_override
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["nick"] << nick;
|
||||
data["vhost"] << vhost;
|
||||
data["type"] << type;
|
||||
data["nick2"] << nick2;
|
||||
data["channel"] << channel;
|
||||
data["message"] << message;
|
||||
data["last"].SetType(Serialize::DT_INT) << last;
|
||||
|
||||
return data;
|
||||
data.SetType("last", Serialize::Data::DT_INT); data["last"] << last;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
Anope::string snick;
|
||||
|
||||
data["nick"] >> snick;
|
||||
|
||||
SeenInfo *s;
|
||||
if (obj)
|
||||
s = anope_dynamic_static_cast<SeenInfo *>(obj);
|
||||
else
|
||||
{
|
||||
/* ignore duplicate entries in the db, created by an old bug */
|
||||
s = FindInfo(data["nick"].str());
|
||||
s = FindInfo(snick);
|
||||
if (!s)
|
||||
s = new SeenInfo();
|
||||
}
|
||||
|
||||
@@ -22,20 +22,22 @@ struct CSMiscData : ExtensibleItem, Serializable
|
||||
{
|
||||
}
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &sdata) const anope_override
|
||||
{
|
||||
Serialize::Data sdata;
|
||||
|
||||
sdata["ci"] << this->ci->name;
|
||||
sdata["name"] << this->name;
|
||||
sdata["data"] << this->data;
|
||||
|
||||
return sdata;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
ChannelInfo *ci = ChannelInfo::Find(data["ci"].astr());
|
||||
Anope::string sci, sname, sdata;
|
||||
|
||||
data["ci"] >> sci;
|
||||
data["name"] >> sname;
|
||||
data["data"] >> sdata;
|
||||
|
||||
ChannelInfo *ci = ChannelInfo::Find(sci);
|
||||
if (ci == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -49,8 +51,8 @@ struct CSMiscData : ExtensibleItem, Serializable
|
||||
}
|
||||
else
|
||||
{
|
||||
d = new CSMiscData(ci, data["name"].astr(), data["data"].astr());
|
||||
ci->Extend(data["name"].astr(), d);
|
||||
d = new CSMiscData(ci, sname, sdata);
|
||||
ci->Extend(sname, d);
|
||||
}
|
||||
|
||||
return d;
|
||||
|
||||
@@ -22,19 +22,19 @@ struct ChanSuspend : ExtensibleItem, Serializable
|
||||
{
|
||||
}
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &sd) const anope_override
|
||||
{
|
||||
Serialize::Data sd;
|
||||
|
||||
sd["chan"] << this->chan;
|
||||
sd["when"] << this->when;
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &sd)
|
||||
{
|
||||
ChannelInfo *ci = ChannelInfo::Find(sd["chan"].astr());
|
||||
Anope::string schan;
|
||||
|
||||
sd["chan"] >> schan;
|
||||
|
||||
ChannelInfo *ci = ChannelInfo::Find(schan);
|
||||
if (ci == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -32,21 +32,20 @@ struct HostRequest : ExtensibleItem, Serializable
|
||||
|
||||
HostRequest() : Serializable("HostRequest") { }
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &data) const anope_override
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["nick"] << this->nick;
|
||||
data["ident"] << this->ident;
|
||||
data["host"] << this->host;
|
||||
data["time"].SetType(Serialize::DT_INT) << this->time;
|
||||
|
||||
return data;
|
||||
data.SetType("time", Serialize::Data::DT_INT); data["time"] << this->time;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
NickAlias *na = NickAlias::Find(data["nick"].astr());
|
||||
Anope::string snick;
|
||||
data["nick"] >> snick;
|
||||
|
||||
NickAlias *na = NickAlias::Find(snick);
|
||||
if (na == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -28,23 +28,23 @@ struct AJoinEntry : Serializable
|
||||
|
||||
AJoinEntry() : Serializable("AJoinEntry") { }
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &sd) const anope_override
|
||||
{
|
||||
Serialize::Data sd;
|
||||
|
||||
if (!this->owner)
|
||||
return sd;
|
||||
return;
|
||||
|
||||
sd["owner"] << this->owner->display;
|
||||
sd["channel"] << this->channel;
|
||||
sd["key"] << this->key;
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &sd)
|
||||
{
|
||||
NickCore *nc = NickCore::Find(sd["owner"].astr());
|
||||
Anope::string sowner;
|
||||
|
||||
sd["owner"] >> sowner;
|
||||
|
||||
NickCore *nc = NickCore::Find(sowner);
|
||||
if (nc == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -23,20 +23,22 @@ struct NSMiscData : ExtensibleItem, Serializable
|
||||
{
|
||||
}
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &sdata) const anope_override
|
||||
{
|
||||
Serialize::Data sdata;
|
||||
|
||||
sdata["nc"] << this->nc->display;
|
||||
sdata["name"] << this->name;
|
||||
sdata["data"] << this->data;
|
||||
|
||||
return sdata;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
NickCore *nc = NickCore::Find(data["nc"].astr());
|
||||
Anope::string snc, sname, sdata;
|
||||
|
||||
data["nc"] >> snc;
|
||||
data["name"] >> sname;
|
||||
data["data"] >> sdata;
|
||||
|
||||
NickCore *nc = NickCore::Find(snc);
|
||||
if (nc == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -50,8 +52,8 @@ struct NSMiscData : ExtensibleItem, Serializable
|
||||
}
|
||||
else
|
||||
{
|
||||
d = new NSMiscData(nc, data["name"].astr(), data["data"].astr());
|
||||
nc->Extend(data["name"].astr(), d);
|
||||
d = new NSMiscData(nc, sname, sdata);
|
||||
nc->Extend(sname, d);
|
||||
}
|
||||
|
||||
return d;
|
||||
|
||||
@@ -22,19 +22,19 @@ struct NickSuspend : ExtensibleItem, Serializable
|
||||
{
|
||||
}
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &sd) const anope_override
|
||||
{
|
||||
Serialize::Data sd;
|
||||
|
||||
sd["nick"] << this->nick;
|
||||
sd["when"] << this->when;
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &sd)
|
||||
{
|
||||
const NickAlias *na = NickAlias::Find(sd["nick"].astr());
|
||||
Anope::string snick;
|
||||
|
||||
sd["nick"] >> snick;
|
||||
|
||||
const NickAlias *na = NickAlias::Find(snick);
|
||||
if (na == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -49,17 +49,13 @@ class DNSServer : public Serializable
|
||||
}
|
||||
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &data) const anope_override
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["server_name"] << server_name;
|
||||
for (unsigned i = 0; i < ips.size(); ++i)
|
||||
data["ip" + stringify(i)] << ips[i];
|
||||
data["limit"] << limit;
|
||||
data["pooled"] << pooled;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
@@ -72,12 +68,16 @@ class DNSServer : public Serializable
|
||||
req = new DNSServer();
|
||||
|
||||
data["server_name"] >> req->server_name;
|
||||
for (unsigned i = 0; data.count("ip" + stringify(i)); ++i)
|
||||
|
||||
for (unsigned i = 0; true; ++i)
|
||||
{
|
||||
Anope::string ip_str;
|
||||
data["ip" + stringify(i)] >> ip_str;
|
||||
if (ip_str.empty())
|
||||
break;
|
||||
req->ips.push_back(ip_str);
|
||||
}
|
||||
|
||||
data["limit"] >> req->limit;
|
||||
data["pooled"] >> req->pooled;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ struct ForbidData : Serializable
|
||||
ForbidType type;
|
||||
|
||||
ForbidData() : Serializable("ForbidData") { }
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
};
|
||||
|
||||
@@ -39,18 +39,14 @@ class ForbidService : public Service
|
||||
|
||||
static ServiceReference<ForbidService> forbid_service("ForbidService", "forbid");
|
||||
|
||||
Serialize::Data ForbidData::Serialize() const
|
||||
void ForbidData::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["mask"] << this->mask;
|
||||
data["creator"] << this->creator;
|
||||
data["reason"] << this->reason;
|
||||
data["created"] << this->created;
|
||||
data["expires"] << this->expires;
|
||||
data["type"] << this->type;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* ForbidData::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
|
||||
@@ -18,7 +18,7 @@ struct IgnoreData : Serializable
|
||||
time_t time; /* When do we stop ignoring them? */
|
||||
|
||||
IgnoreData() : Serializable("IgnoreData") { }
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
};
|
||||
|
||||
@@ -43,16 +43,12 @@ class IgnoreService : public Service
|
||||
|
||||
static ServiceReference<IgnoreService> ignore_service("IgnoreService", "ignore");
|
||||
|
||||
Serialize::Data IgnoreData::Serialize() const
|
||||
void IgnoreData::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["mask"] << this->mask;
|
||||
data["creator"] << this->creator;
|
||||
data["reason"] << this->reason;
|
||||
data["time"] << this->time;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* IgnoreData::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
@@ -70,9 +66,14 @@ Serializable* IgnoreData::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
return ign;
|
||||
}
|
||||
|
||||
Anope::string smask, screator, sreason;
|
||||
time_t t;
|
||||
|
||||
data["mask"] >> smask;
|
||||
data["creator"] >> screator;
|
||||
data["reason"] >> sreason;
|
||||
data["time"] >> t;
|
||||
|
||||
return ignore_service->AddIgnore(data["mask"].astr(), data["creator"].astr(), data["reason"].astr(), t);
|
||||
return ignore_service->AddIgnore(smask, screator, sreason, t);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ struct NewsItem : Serializable
|
||||
time_t time;
|
||||
|
||||
NewsItem() : Serializable("NewsItem") { }
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
};
|
||||
|
||||
@@ -41,16 +41,12 @@ class NewsService : public Service
|
||||
|
||||
static ServiceReference<NewsService> news_service("NewsService", "news");
|
||||
|
||||
Serialize::Data NewsItem::Serialize() const
|
||||
void NewsItem::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["type"] << this->type;
|
||||
data["text"] << this->text;
|
||||
data["who"] << this->who;
|
||||
data["time"] << this->time;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* NewsItem::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
|
||||
@@ -17,22 +17,23 @@ struct MyOper : Oper, Serializable
|
||||
{
|
||||
MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &data) const anope_override
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["name"] << this->name;
|
||||
data["type"] << this->ot->GetName();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
OperType *ot = OperType::Find(data["type"].astr());
|
||||
Anope::string stype, sname;
|
||||
|
||||
data["type"] >> stype;
|
||||
data["name"] >> sname;
|
||||
|
||||
OperType *ot = OperType::Find(stype);
|
||||
if (ot == NULL)
|
||||
return NULL;
|
||||
NickCore *nc = NickCore::Find(data["name"].astr());
|
||||
NickCore *nc = NickCore::Find(sname);
|
||||
if (nc == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ struct Exception : Serializable
|
||||
time_t expires; /* Time when it expires. 0 == no expiry */
|
||||
|
||||
Exception() : Serializable("Exception") { }
|
||||
Serialize::Data Serialize() const anope_override;
|
||||
void Serialize(Serialize::Data &data) const anope_override;
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
};
|
||||
|
||||
@@ -53,18 +53,14 @@ class SessionService : public Service
|
||||
|
||||
static ServiceReference<SessionService> session_service("SessionService", "session");
|
||||
|
||||
Serialize::Data Exception::Serialize() const
|
||||
void Exception::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["mask"] << this->mask;
|
||||
data["limit"] << this->limit;
|
||||
data["who"] << this->who;
|
||||
data["reason"] << this->reason;
|
||||
data["time"] << this->time;
|
||||
data["expires"] << this->expires;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* Exception::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
|
||||
@@ -18,14 +18,10 @@ struct Stats : Serializable
|
||||
{
|
||||
Stats() : Serializable("Stats") { }
|
||||
|
||||
Serialize::Data Serialize() const anope_override
|
||||
void Serialize(Serialize::Data &data) const anope_override
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["maxusercnt"] << MaxUserCount;
|
||||
data["maxusertime"] << MaxUserTime;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
|
||||
+232
-144
@@ -12,17 +12,123 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class DBFlatFile : public Module
|
||||
class SaveData : public Serialize::Data
|
||||
{
|
||||
Anope::string DatabaseFile;
|
||||
Anope::string BackupFile;
|
||||
public:
|
||||
std::fstream *fs;
|
||||
|
||||
SaveData() : fs(NULL) { }
|
||||
|
||||
std::iostream& operator[](const Anope::string &key) anope_override
|
||||
{
|
||||
*fs << "\nDATA " << key << " ";
|
||||
return *fs;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadData : public Serialize::Data
|
||||
{
|
||||
public:
|
||||
std::fstream *fs;
|
||||
std::map<Anope::string, Anope::string> data;
|
||||
std::stringstream ss;
|
||||
bool read;
|
||||
|
||||
LoadData() : fs(NULL), read(false) { }
|
||||
|
||||
std::iostream& operator[](const Anope::string &key) anope_override
|
||||
{
|
||||
if (!read)
|
||||
{
|
||||
for (Anope::string token; std::getline(*this->fs, token.str());)
|
||||
{
|
||||
if (token.find("DATA ") != 0)
|
||||
break;
|
||||
|
||||
size_t sp = token.find(' ', 5); // Skip DATA
|
||||
if (sp != Anope::string::npos)
|
||||
data[token.substr(5, sp - 5)] = token.substr(sp + 1);
|
||||
}
|
||||
|
||||
read = true;
|
||||
}
|
||||
|
||||
ss.clear();
|
||||
this->ss << this->data[key];
|
||||
return this->ss;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
read = false;
|
||||
data.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class DBFlatFile : public Module, public Pipe
|
||||
{
|
||||
Anope::string database_file;
|
||||
/* Day the last backup was on */
|
||||
int LastDay;
|
||||
int last_day;
|
||||
/* Backup file names */
|
||||
std::list<Anope::string> Backups;
|
||||
std::map<Anope::string, std::list<Anope::string> > backups;
|
||||
bool use_fork;
|
||||
|
||||
void BackupDatabase()
|
||||
{
|
||||
tm *tm = localtime(&Anope::CurTime);
|
||||
|
||||
if (tm->tm_mday != last_day)
|
||||
{
|
||||
last_day = tm->tm_mday;
|
||||
|
||||
const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder();
|
||||
|
||||
std::set<Anope::string> dbs;
|
||||
dbs.insert(database_file);
|
||||
|
||||
for (unsigned i = 0; i < type_order.size(); ++i)
|
||||
{
|
||||
Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
|
||||
|
||||
if (stype && stype->GetOwner())
|
||||
dbs.insert("module_" + stype->GetOwner()->name + ".db");
|
||||
}
|
||||
|
||||
|
||||
for (std::set<Anope::string>::const_iterator it = dbs.begin(), it_end = dbs.end(); it != it_end; ++it)
|
||||
{
|
||||
const Anope::string &oldname = Anope::DataDir + "/" + *it;
|
||||
Anope::string newname = Anope::DataDir + "/backups/" + *it + "." + stringify(tm->tm_year) + "." + stringify(tm->tm_mon) + "." + stringify(tm->tm_mday);
|
||||
|
||||
/* Backup already exists */
|
||||
if (Anope::IsFile(newname))
|
||||
continue;
|
||||
|
||||
Log(LOG_DEBUG) << "db_flatfile: Attemping to rename " << *it << " to " << newname;
|
||||
if (rename(oldname.c_str(), newname.c_str()))
|
||||
{
|
||||
Log(this) << "Unable to back up database " << *it << "!";
|
||||
|
||||
if (!Config->NoBackupOkay)
|
||||
Anope::Quitting = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
backups[*it].push_back(newname);
|
||||
|
||||
if (Config->KeepBackups > 0 && backups[*it].size() > static_cast<unsigned>(Config->KeepBackups))
|
||||
{
|
||||
unlink(backups[*it].front().c_str());
|
||||
backups[*it].pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE)
|
||||
DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), last_day(0), use_fork(false)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
@@ -30,126 +136,77 @@ class DBFlatFile : public Module
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
OnReload();
|
||||
|
||||
LastDay = 0;
|
||||
}
|
||||
|
||||
void BackupDatabase()
|
||||
void OnNotify() anope_override
|
||||
{
|
||||
/* Do not backup a database that doesn't exist */
|
||||
if (!Anope::IsFile(DatabaseFile))
|
||||
char buf[512];
|
||||
int i = this->Read(buf, sizeof(buf) - 1);
|
||||
if (i <= 0)
|
||||
return;
|
||||
buf[i] = 0;
|
||||
|
||||
time_t now = Anope::CurTime;
|
||||
tm *tm = localtime(&now);
|
||||
|
||||
if (tm->tm_mday != LastDay)
|
||||
if (!*buf)
|
||||
{
|
||||
LastDay = tm->tm_mday;
|
||||
Anope::string newname = BackupFile + "." + stringify(tm->tm_year) + "." + stringify(tm->tm_mon) + "." + stringify(tm->tm_mday);
|
||||
|
||||
/* Backup already exists */
|
||||
if (IsFile(newname))
|
||||
return;
|
||||
|
||||
Log(LOG_DEBUG) << "db_flatfile: Attemping to rename " << DatabaseFile << " to " << newname;
|
||||
if (rename(DatabaseFile.c_str(), newname.c_str()))
|
||||
{
|
||||
Log(this) << "Unable to back up database!";
|
||||
|
||||
if (!Config->NoBackupOkay)
|
||||
Anope::Quitting = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Backups.push_back(newname);
|
||||
|
||||
if (Config->KeepBackups > 0 && Backups.size() > static_cast<unsigned>(Config->KeepBackups))
|
||||
{
|
||||
unlink(Backups.front().c_str());
|
||||
Backups.pop_front();
|
||||
}
|
||||
Log(this) << "Finished saving databases";
|
||||
return;
|
||||
}
|
||||
|
||||
Log(this) << "Error saving databases: " << buf;
|
||||
|
||||
if (!Config->NoBackupOkay)
|
||||
Anope::Quitting = true;
|
||||
}
|
||||
|
||||
void OnReload() anope_override
|
||||
{
|
||||
ConfigReader config;
|
||||
DatabaseFile = Anope::DataDir + "/" + config.ReadValue("db_flatfile", "database", "anope.db", 0);
|
||||
BackupFile = Anope::DataDir + "/backups/" + config.ReadValue("db_flatfile", "database", "anope.db", 0);
|
||||
database_file = config.ReadValue("db_flatfile", "database", "anope.db", 0);
|
||||
use_fork = config.ReadFlag("db_flatfile", "fork", "no", 0);
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase() anope_override
|
||||
{
|
||||
std::map<Module *, std::fstream *> databases;
|
||||
databases[NULL] = new std::fstream(DatabaseFile.c_str(), std::ios_base::in);
|
||||
const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder();
|
||||
std::set<Anope::string> tried_dbs;
|
||||
|
||||
if (!databases[NULL]->is_open())
|
||||
const Anope::string &db_name = Anope::DataDir + "/" + database_file;
|
||||
|
||||
std::fstream fd(db_name.c_str(), std::ios_base::in);
|
||||
if (!fd.is_open())
|
||||
{
|
||||
delete databases[NULL];
|
||||
Log(this) << "Unable to open " << DatabaseFile << " for reading!";
|
||||
return EVENT_CONTINUE;
|
||||
Log(this) << "Unable to open " << db_name << " for reading!";
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
|
||||
std::map<Anope::string, std::vector<std::streampos> > positions;
|
||||
|
||||
for (Anope::string buf; std::getline(fd, buf.str());)
|
||||
if (buf.find("OBJECT ") == 0)
|
||||
positions[buf.substr(7)].push_back(fd.tellg());
|
||||
|
||||
LoadData ld;
|
||||
ld.fs = &fd;
|
||||
|
||||
for (unsigned i = 0; i < type_order.size(); ++i)
|
||||
{
|
||||
Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
|
||||
if (stype && !databases.count(stype->GetOwner()))
|
||||
{
|
||||
Anope::string db_name = Anope::DataDir + "/module_" + stype->GetOwner()->name + ".db";
|
||||
databases[stype->GetOwner()] = new std::fstream(db_name.c_str(), std::ios_base::in);
|
||||
}
|
||||
}
|
||||
|
||||
std::multimap<Serialize::Type *, Serialize::Data> objects;
|
||||
for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
|
||||
{
|
||||
std::fstream *db = it->second;
|
||||
Serialize::Type *st = NULL;
|
||||
Serialize::Data data;
|
||||
for (Anope::string buf, token; std::getline(*db, buf.str());)
|
||||
{
|
||||
spacesepstream sep(buf);
|
||||
|
||||
if (!sep.GetToken(token))
|
||||
continue;
|
||||
|
||||
if (token == "OBJECT" && sep.GetToken(token))
|
||||
{
|
||||
st = Serialize::Type::Find(token);
|
||||
data.clear();
|
||||
}
|
||||
else if (token == "DATA" && st != NULL && sep.GetToken(token))
|
||||
data[token] << sep.GetRemaining();
|
||||
else if (token == "END" && st != NULL)
|
||||
{
|
||||
objects.insert(std::make_pair(st, data));
|
||||
|
||||
st = NULL;
|
||||
data.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < type_order.size(); ++i)
|
||||
{
|
||||
Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
|
||||
|
||||
std::multimap<Serialize::Type *, Serialize::Data>::iterator it = objects.find(stype), it_end = objects.upper_bound(stype);
|
||||
if (it == objects.end())
|
||||
if (!stype || stype->GetOwner())
|
||||
continue;
|
||||
for (; it != it_end; ++it)
|
||||
it->first->Unserialize(NULL, it->second);
|
||||
|
||||
std::vector<std::streampos> &pos = positions[stype->GetName()];
|
||||
|
||||
for (unsigned j = 0; j < pos.size(); ++j)
|
||||
{
|
||||
fd.clear();
|
||||
fd.seekg(pos[j]);
|
||||
|
||||
stype->Unserialize(NULL, ld);
|
||||
ld.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
|
||||
{
|
||||
it->second->close();
|
||||
delete it->second;
|
||||
}
|
||||
fd.close();
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
@@ -159,61 +216,92 @@ class DBFlatFile : public Module
|
||||
{
|
||||
BackupDatabase();
|
||||
|
||||
Anope::string tmp_db = DatabaseFile + ".tmp";
|
||||
if (IsFile(DatabaseFile))
|
||||
rename(DatabaseFile.c_str(), tmp_db.c_str());
|
||||
|
||||
std::map<Module *, std::fstream *> databases;
|
||||
databases[NULL] = new std::fstream(DatabaseFile.c_str(), std::ios_base::out | std::ios_base::trunc);
|
||||
if (!databases[NULL]->is_open())
|
||||
int i = -1;
|
||||
if (use_fork)
|
||||
{
|
||||
delete databases[NULL];
|
||||
Log(this) << "Unable to open " << DatabaseFile << " for writing";
|
||||
if (IsFile(tmp_db))
|
||||
rename(tmp_db.c_str(), DatabaseFile.c_str());
|
||||
return EVENT_CONTINUE;
|
||||
i = fork();
|
||||
if (i > 0)
|
||||
return EVENT_CONTINUE;
|
||||
else if (i < 0)
|
||||
Log(this) << "Unable to fork for database save";
|
||||
}
|
||||
|
||||
const std::list<Serializable *> &items = Serializable::GetItems();
|
||||
for (std::list<Serializable *>::const_iterator it = items.begin(), it_end = items.end(); it != it_end; ++it)
|
||||
try
|
||||
{
|
||||
Serializable *base = *it;
|
||||
Serialize::Type *s_type = base->GetSerializableType();
|
||||
std::map<Module *, std::fstream *> databases;
|
||||
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
Serialize::Data data = base->Serialize();
|
||||
|
||||
if (!databases.count(s_type->GetOwner()))
|
||||
SaveData data;
|
||||
const std::list<Serializable *> &items = Serializable::GetItems();
|
||||
for (std::list<Serializable *>::const_iterator it = items.begin(), it_end = items.end(); it != it_end; ++it)
|
||||
{
|
||||
Anope::string db_name = Anope::DataDir + "/module_" + s_type->GetOwner()->name + ".db";
|
||||
databases[s_type->GetOwner()] = new std::fstream(db_name.c_str(), std::ios_base::out | std::ios_base::trunc);
|
||||
Serializable *base = *it;
|
||||
Serialize::Type *s_type = base->GetSerializableType();
|
||||
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
data.fs = databases[s_type->GetOwner()];
|
||||
|
||||
if (!data.fs)
|
||||
{
|
||||
Anope::string db_name;
|
||||
if (s_type->GetOwner())
|
||||
db_name = Anope::DataDir + "/module_" + s_type->GetOwner()->name + ".db";
|
||||
else
|
||||
db_name = Anope::DataDir + "/" + database_file;
|
||||
|
||||
if (Anope::IsFile(db_name))
|
||||
rename(db_name.c_str(), (db_name + ".tmp").c_str());
|
||||
|
||||
data.fs = databases[s_type->GetOwner()] = new std::fstream(db_name.c_str(), std::ios_base::out | std::ios_base::trunc);
|
||||
|
||||
if (!data.fs->is_open())
|
||||
{
|
||||
Log(this) << "Unable to open " << db_name << " for writing";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!data.fs->is_open())
|
||||
continue;
|
||||
|
||||
*data.fs << "OBJECT " << s_type->GetName();
|
||||
base->Serialize(data);
|
||||
*data.fs << "\nEND\n";
|
||||
}
|
||||
std::fstream *fd = databases[s_type->GetOwner()];
|
||||
|
||||
*fd << "OBJECT " << s_type->GetName() << "\n";
|
||||
for (Serialize::Data::iterator dit = data.begin(), dit_end = data.end(); dit != dit_end; ++dit)
|
||||
*fd << "DATA " << dit->first << " " << dit->second.astr() << "\n";
|
||||
*fd << "END\n";
|
||||
|
||||
for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
|
||||
{
|
||||
std::fstream *f = it->second;
|
||||
const Anope::string &db_name = Anope::DataDir + "/" + (it->first ? (it->first->name + ".db") : database_file);
|
||||
|
||||
if (!f->is_open() || !f->good())
|
||||
{
|
||||
this->Write("Unable to write database " + db_name);
|
||||
|
||||
f->close();
|
||||
|
||||
if (Anope::IsFile((db_name + ".tmp").c_str()))
|
||||
rename((db_name + ".tmp").c_str(), db_name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
f->close();
|
||||
unlink((db_name + ".tmp").c_str());
|
||||
}
|
||||
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (i)
|
||||
throw;
|
||||
}
|
||||
|
||||
if (databases[NULL]->good() == false)
|
||||
if (!i)
|
||||
{
|
||||
Log(this) << "Unable to write database";
|
||||
databases[NULL]->close();
|
||||
if (!Config->NoBackupOkay)
|
||||
Anope::Quitting = true;
|
||||
if (IsFile(tmp_db))
|
||||
rename(tmp_db.c_str(), DatabaseFile.c_str());
|
||||
}
|
||||
else
|
||||
unlink(tmp_db.c_str());
|
||||
|
||||
for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
|
||||
{
|
||||
it->second->close();
|
||||
delete it->second;
|
||||
this->Notify();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
+39
-23
@@ -11,18 +11,19 @@
|
||||
#include "module.h"
|
||||
#include "../extra/sql.h"
|
||||
|
||||
class SQLSQLInterface : public SQLInterface
|
||||
using namespace SQL;
|
||||
|
||||
class SQLSQLInterface : public Interface
|
||||
{
|
||||
public:
|
||||
SQLSQLInterface(Module *o) : SQLInterface(o) { }
|
||||
virtual ~SQLSQLInterface() { }
|
||||
SQLSQLInterface(Module *o) : Interface(o) { }
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
void OnResult(const Result &r) anope_override
|
||||
{
|
||||
Log(LOG_DEBUG) << "SQL successfully executed query: " << r.finished_query;
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r) anope_override
|
||||
void OnError(const Result &r) anope_override
|
||||
{
|
||||
if (!r.GetQuery().query.empty())
|
||||
Log(LOG_DEBUG) << "Error executing query " << r.finished_query << ": " << r.GetError();
|
||||
@@ -38,7 +39,7 @@ class ResultSQLSQLInterface : public SQLSQLInterface
|
||||
public:
|
||||
ResultSQLSQLInterface(Module *o, Serializable *ob) : SQLSQLInterface(o), obj(ob) { }
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
void OnResult(const Result &r) anope_override
|
||||
{
|
||||
SQLSQLInterface::OnResult(r);
|
||||
if (r.GetID() > 0 && this->obj)
|
||||
@@ -46,7 +47,7 @@ public:
|
||||
delete this;
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r) anope_override
|
||||
void OnError(const Result &r) anope_override
|
||||
{
|
||||
SQLSQLInterface::OnError(r);
|
||||
delete this;
|
||||
@@ -55,13 +56,14 @@ public:
|
||||
|
||||
class DBSQL : public Module, public Pipe
|
||||
{
|
||||
ServiceReference<SQLProvider> sql;
|
||||
ServiceReference<Provider> sql;
|
||||
SQLSQLInterface sqlinterface;
|
||||
Anope::string prefix;
|
||||
std::set<Reference<Serializable> > updated_items;
|
||||
bool shutting_down;
|
||||
bool loading_databases;
|
||||
|
||||
void RunBackground(const SQLQuery &q, SQLInterface *iface = NULL)
|
||||
void RunBackground(const Query &q, Interface *iface = NULL)
|
||||
{
|
||||
if (!this->sql)
|
||||
{
|
||||
@@ -83,7 +85,7 @@ class DBSQL : public Module, public Pipe
|
||||
}
|
||||
|
||||
public:
|
||||
DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sql("", ""), sqlinterface(this), shutting_down(false)
|
||||
DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sql("", ""), sqlinterface(this), shutting_down(false), loading_databases(false)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
@@ -101,21 +103,26 @@ class DBSQL : public Module, public Pipe
|
||||
|
||||
if (obj && this->sql)
|
||||
{
|
||||
if (obj->IsCached())
|
||||
Data *data = new Data();
|
||||
obj->Serialize(*data);
|
||||
|
||||
if (obj->IsCached(data))
|
||||
{
|
||||
delete data;
|
||||
continue;
|
||||
obj->UpdateCache();
|
||||
}
|
||||
|
||||
obj->UpdateCache(data);
|
||||
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
Serialize::Data data = obj->Serialize();
|
||||
|
||||
std::vector<SQLQuery> create = this->sql->CreateTable(this->prefix + s_type->GetName(), data);
|
||||
std::vector<Query> create = this->sql->CreateTable(this->prefix + s_type->GetName(), *data);
|
||||
for (unsigned i = 0; i < create.size(); ++i)
|
||||
this->RunBackground(create[i]);
|
||||
|
||||
SQLQuery insert = this->sql->BuildInsert(this->prefix + s_type->GetName(), obj->id, data);
|
||||
Query insert = this->sql->BuildInsert(this->prefix + s_type->GetName(), obj->id, *data);
|
||||
this->RunBackground(insert, new ResultSQLSQLInterface(this, obj));
|
||||
}
|
||||
}
|
||||
@@ -127,7 +134,7 @@ class DBSQL : public Module, public Pipe
|
||||
{
|
||||
ConfigReader config;
|
||||
Anope::string engine = config.ReadValue("db_sql", "engine", "", 0);
|
||||
this->sql = ServiceReference<SQLProvider>("SQLProvider", engine);
|
||||
this->sql = ServiceReference<Provider>("SQL::Provider", engine);
|
||||
this->prefix = config.ReadValue("db_sql", "prefix", "anope_db_", 0);
|
||||
}
|
||||
|
||||
@@ -150,23 +157,25 @@ class DBSQL : public Module, public Pipe
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
this->loading_databases = true;
|
||||
|
||||
const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
|
||||
for (unsigned i = 0; i < type_order.size(); ++i)
|
||||
{
|
||||
Serialize::Type *sb = Serialize::Type::Find(type_order[i]);
|
||||
|
||||
SQLQuery query("SELECT * FROM `" + this->prefix + sb->GetName() + "`");
|
||||
SQLResult res = this->sql->RunQuery(query);
|
||||
Query query("SELECT * FROM `" + this->prefix + sb->GetName() + "`");
|
||||
Result res = this->sql->RunQuery(query);
|
||||
|
||||
for (int j = 0; j < res.Rows(); ++j)
|
||||
{
|
||||
Serialize::Data data;
|
||||
Data *data = new Data();
|
||||
|
||||
const std::map<Anope::string, Anope::string> &row = res.Row(j);
|
||||
for (std::map<Anope::string, Anope::string>::const_iterator rit = row.begin(), rit_end = row.end(); rit != rit_end; ++rit)
|
||||
data[rit->first] << rit->second;
|
||||
(*data)[rit->first] << rit->second;
|
||||
|
||||
Serializable *obj = sb->Unserialize(NULL, data);
|
||||
Serializable *obj = sb->Unserialize(NULL, *data);
|
||||
try
|
||||
{
|
||||
if (obj)
|
||||
@@ -176,15 +185,22 @@ class DBSQL : public Module, public Pipe
|
||||
{
|
||||
Log(this) << "Unable to convert id for object #" << j << " of type " << sb->GetName();
|
||||
}
|
||||
|
||||
if (obj)
|
||||
obj->UpdateCache(data); /* We know this is the most up to date copy */
|
||||
else
|
||||
delete data;
|
||||
}
|
||||
}
|
||||
|
||||
this->loading_databases = false;
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
void OnSerializableConstruct(Serializable *obj) anope_override
|
||||
{
|
||||
if (this->shutting_down)
|
||||
if (this->shutting_down || this->loading_databases)
|
||||
return;
|
||||
this->updated_items.insert(obj);
|
||||
this->Notify();
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
#include "../extra/sql.h"
|
||||
#include "../commands/os_session.h"
|
||||
|
||||
using namespace SQL;
|
||||
|
||||
class DBMySQL : public Module, public Pipe
|
||||
{
|
||||
private:
|
||||
Anope::string engine;
|
||||
Anope::string prefix;
|
||||
ServiceReference<SQLProvider> SQL;
|
||||
ServiceReference<Provider> SQL;
|
||||
time_t lastwarn;
|
||||
bool ro;
|
||||
bool init;
|
||||
@@ -43,24 +45,24 @@ class DBMySQL : public Module, public Pipe
|
||||
return init && SQL;
|
||||
}
|
||||
|
||||
void RunQuery(const SQLQuery &query)
|
||||
void RunQuery(const Query &query)
|
||||
{
|
||||
/* Can this be threaded? */
|
||||
this->RunQueryResult(query);
|
||||
}
|
||||
|
||||
SQLResult RunQueryResult(const SQLQuery &query)
|
||||
Result RunQueryResult(const Query &query)
|
||||
{
|
||||
if (this->CheckSQL())
|
||||
{
|
||||
SQLResult res = SQL->RunQuery(query);
|
||||
Result res = SQL->RunQuery(query);
|
||||
if (!res.GetError().empty())
|
||||
Log(LOG_DEBUG) << "SQL-live got error " << res.GetError() << " for " + res.finished_query;
|
||||
else
|
||||
Log(LOG_DEBUG) << "SQL-live got " << res.Rows() << " rows for " << res.finished_query;
|
||||
return res;
|
||||
}
|
||||
throw SQLException("No SQL!");
|
||||
throw SQL::Exception("No SQL!");
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -87,21 +89,26 @@ class DBMySQL : public Module, public Pipe
|
||||
|
||||
if (obj && this->SQL)
|
||||
{
|
||||
if (obj->IsCached())
|
||||
Data *data = new Data();
|
||||
obj->Serialize(*data);
|
||||
|
||||
if (obj->IsCached(data))
|
||||
{
|
||||
delete data;
|
||||
continue;
|
||||
obj->UpdateCache();
|
||||
}
|
||||
|
||||
obj->UpdateCache(data);
|
||||
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
Serialize::Data data = obj->Serialize();
|
||||
|
||||
std::vector<SQLQuery> create = this->SQL->CreateTable(this->prefix + s_type->GetName(), data);
|
||||
std::vector<Query> create = this->SQL->CreateTable(this->prefix + s_type->GetName(), *data);
|
||||
for (unsigned i = 0; i < create.size(); ++i)
|
||||
this->RunQueryResult(create[i]);
|
||||
|
||||
SQLResult res = this->RunQueryResult(this->SQL->BuildInsert(this->prefix + s_type->GetName(), obj->id, data));
|
||||
Result res = this->RunQueryResult(this->SQL->BuildInsert(this->prefix + s_type->GetName(), obj->id, *data));
|
||||
if (obj->id != res.GetID())
|
||||
{
|
||||
/* In this case obj is new, so place it into the object map */
|
||||
@@ -129,7 +136,7 @@ class DBMySQL : public Module, public Pipe
|
||||
{
|
||||
ConfigReader config;
|
||||
this->engine = config.ReadValue("db_sql", "engine", "", 0);
|
||||
this->SQL = ServiceReference<SQLProvider>("SQLProvider", this->engine);
|
||||
this->SQL = ServiceReference<Provider>("SQL::Provider", this->engine);
|
||||
this->prefix = config.ReadValue("db_sql", "prefix", "anope_db_", 0);
|
||||
}
|
||||
|
||||
@@ -157,11 +164,11 @@ class DBMySQL : public Module, public Pipe
|
||||
if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime)
|
||||
return;
|
||||
|
||||
SQLQuery query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` > " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
|
||||
Query query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` > " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
|
||||
|
||||
obj->UpdateTimestamp();
|
||||
|
||||
SQLResult res = this->RunQueryResult(query);
|
||||
Result res = this->RunQueryResult(query);
|
||||
|
||||
bool clear_null = false;
|
||||
for (int i = 0; i < res.Rows(); ++i)
|
||||
@@ -191,17 +198,17 @@ class DBMySQL : public Module, public Pipe
|
||||
}
|
||||
else
|
||||
{
|
||||
Serialize::Data data;
|
||||
Data *data = new Data();
|
||||
|
||||
for (std::map<Anope::string, Anope::string>::const_iterator it = row.begin(), it_end = row.end(); it != it_end; ++it)
|
||||
data[it->first] << it->second;
|
||||
(*data)[it->first] << it->second;
|
||||
|
||||
Serializable *s = NULL;
|
||||
std::map<unsigned int, Serializable *>::iterator it = obj->objects.find(id);
|
||||
if (it != obj->objects.end())
|
||||
s = it->second;
|
||||
|
||||
Serializable *new_s = obj->Unserialize(s, data);
|
||||
Serializable *new_s = obj->Unserialize(s, *data);
|
||||
if (new_s)
|
||||
{
|
||||
// If s == new_s then s->id == new_s->id
|
||||
@@ -209,11 +216,16 @@ class DBMySQL : public Module, public Pipe
|
||||
{
|
||||
new_s->id = id;
|
||||
obj->objects[id] = new_s;
|
||||
new_s->UpdateCache(); /* We know this is the most up to date copy */
|
||||
new_s->UpdateCache(data); /* We know this is the most up to date copy */
|
||||
}
|
||||
else
|
||||
delete data;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete data;
|
||||
s->Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#include "module.h"
|
||||
#include "../extra/sql.h"
|
||||
|
||||
class MySQLInterface : public SQLInterface
|
||||
class MySQLInterface : public SQL::Interface
|
||||
{
|
||||
public:
|
||||
MySQLInterface(Module *o) : SQLInterface(o) { }
|
||||
MySQLInterface(Module *o) : SQL::Interface(o) { }
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
void OnResult(const SQL::Result &r) anope_override
|
||||
{
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r) anope_override
|
||||
void OnError(const SQL::Result &r) anope_override
|
||||
{
|
||||
if (!r.GetQuery().query.empty())
|
||||
Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
|
||||
@@ -21,13 +21,13 @@ class MySQLInterface : public SQLInterface
|
||||
|
||||
class MChanstats : public Module
|
||||
{
|
||||
ServiceReference<SQLProvider> sql;
|
||||
ServiceReference<SQL::Provider> sql;
|
||||
MySQLInterface sqlinterface;
|
||||
SQLQuery query;
|
||||
SQL::Query query;
|
||||
Anope::string SmileysHappy, SmileysSad, SmileysOther, prefix;
|
||||
std::vector<Anope::string> TableList, ProcedureList, EventList;
|
||||
|
||||
void RunQuery(const SQLQuery &q)
|
||||
void RunQuery(const SQL::Query &q)
|
||||
{
|
||||
if (sql)
|
||||
sql->Run(&sqlinterface, q);
|
||||
@@ -70,7 +70,7 @@ class MChanstats : public Module
|
||||
if (!sql)
|
||||
return;
|
||||
|
||||
SQLResult r = this->sql->RunQuery(this->sql->GetTables(prefix));
|
||||
SQL::Result r = this->sql->RunQuery(this->sql->GetTables(prefix));
|
||||
for (int i = 0; i < r.Rows(); ++i)
|
||||
{
|
||||
const std::map<Anope::string, Anope::string> &map = r.Row(i);
|
||||
@@ -359,7 +359,7 @@ class MChanstats : public Module
|
||||
SmileysOther = config.ReadValue("chanstats", "SmileysOther", ":/", 0);
|
||||
|
||||
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
|
||||
this->sql = ServiceReference<SQLProvider>("SQLProvider", engine);
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
|
||||
if (sql)
|
||||
this->CheckTables();
|
||||
else
|
||||
@@ -371,8 +371,8 @@ class MChanstats : public Module
|
||||
if (!u || !u->Account() || !c->ci || !c->ci->HasFlag(CI_STATS))
|
||||
return;
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);";
|
||||
query.setValue("channel", c->name);
|
||||
query.setValue("nick", GetDisplay(u));
|
||||
query.SetValue("channel", c->name);
|
||||
query.SetValue("nick", GetDisplay(u));
|
||||
this->RunQuery(query);
|
||||
}
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelModeName Name, const Anope::string ¶m) anope_override
|
||||
@@ -392,8 +392,8 @@ class MChanstats : public Module
|
||||
return;
|
||||
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);";
|
||||
query.setValue("channel", c->name);
|
||||
query.setValue("nick", GetDisplay(u));
|
||||
query.SetValue("channel", c->name);
|
||||
query.SetValue("nick", GetDisplay(u));
|
||||
this->RunQuery(query);
|
||||
}
|
||||
public:
|
||||
@@ -403,13 +403,13 @@ class MChanstats : public Module
|
||||
return;
|
||||
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0);";
|
||||
query.setValue("channel", c->name);
|
||||
query.setValue("nick", GetDisplay(target));
|
||||
query.SetValue("channel", c->name);
|
||||
query.SetValue("nick", GetDisplay(target));
|
||||
this->RunQuery(query);
|
||||
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);";
|
||||
query.setValue("channel", c->name);
|
||||
query.setValue("nick", GetDisplay(source.GetUser()));
|
||||
query.SetValue("channel", c->name);
|
||||
query.SetValue("nick", GetDisplay(source.GetUser()));
|
||||
this->RunQuery(query);
|
||||
}
|
||||
void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
|
||||
@@ -437,33 +437,33 @@ class MChanstats : public Module
|
||||
words = words - smileys_happy - smileys_sad - smileys_other;
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 1, @letters@, @words@, @action@, "
|
||||
"@smileys_happy@, @smileys_sad@, @smileys_other@, '0', '0', '0', '0');";
|
||||
query.setValue("channel", c->name);
|
||||
query.setValue("nick", GetDisplay(u));
|
||||
query.setValue("letters", letters);
|
||||
query.setValue("words", words);
|
||||
query.setValue("action", action);
|
||||
query.setValue("smileys_happy", smileys_happy);
|
||||
query.setValue("smileys_sad", smileys_sad);
|
||||
query.setValue("smileys_other", smileys_other);
|
||||
query.SetValue("channel", c->name);
|
||||
query.SetValue("nick", GetDisplay(u));
|
||||
query.SetValue("letters", letters);
|
||||
query.SetValue("words", words);
|
||||
query.SetValue("action", action);
|
||||
query.SetValue("smileys_happy", smileys_happy);
|
||||
query.SetValue("smileys_sad", smileys_sad);
|
||||
query.SetValue("smileys_other", smileys_other);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
void OnDelCore(NickCore *nc) anope_override
|
||||
{
|
||||
query = "DELETE FROM `" + prefix + "chanstats` WHERE `nick` = @nick@;";
|
||||
query.setValue("nick", nc->display);
|
||||
query.SetValue("nick", nc->display);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) anope_override
|
||||
{
|
||||
query = "CALL " + prefix + "chanstats_proc_chgdisplay(@old_display@, @new_display@);";
|
||||
query.setValue("old_display", nc->display);
|
||||
query.setValue("new_display", newdisplay);
|
||||
query.SetValue("old_display", nc->display);
|
||||
query.SetValue("new_display", newdisplay);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
void OnChanDrop(ChannelInfo *ci) anope_override
|
||||
{
|
||||
query = "DELETE FROM `" + prefix + "chanstats` WHERE `chan` = @channel@;";
|
||||
query.setValue("channel", ci->name);
|
||||
query.SetValue("channel", ci->name);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
};
|
||||
|
||||
+49
-47
@@ -5,6 +5,8 @@
|
||||
#include <mysql/mysql.h>
|
||||
#include "sql.h"
|
||||
|
||||
using namespace SQL;
|
||||
|
||||
/** Non blocking threaded MySQL API, based loosely from InspIRCd's m_mysql.cpp
|
||||
*
|
||||
* This module spawns a single thread that is used to execute blocking MySQL queries.
|
||||
@@ -24,32 +26,32 @@ struct QueryRequest
|
||||
/* The connection to the database */
|
||||
MySQLService *service;
|
||||
/* The interface to use once we have the result to send the data back */
|
||||
SQLInterface *sqlinterface;
|
||||
Interface *sqlinterface;
|
||||
/* The actual query */
|
||||
SQLQuery query;
|
||||
Query query;
|
||||
|
||||
QueryRequest(MySQLService *s, SQLInterface *i, const SQLQuery &q) : service(s), sqlinterface(i), query(q) { }
|
||||
QueryRequest(MySQLService *s, Interface *i, const Query &q) : service(s), sqlinterface(i), query(q) { }
|
||||
};
|
||||
|
||||
/** A query result */
|
||||
struct QueryResult
|
||||
{
|
||||
/* The interface to send the data back on */
|
||||
SQLInterface *sqlinterface;
|
||||
Interface *sqlinterface;
|
||||
/* The result */
|
||||
SQLResult result;
|
||||
Result result;
|
||||
|
||||
QueryResult(SQLInterface *i, SQLResult &r) : sqlinterface(i), result(r) { }
|
||||
QueryResult(Interface *i, Result &r) : sqlinterface(i), result(r) { }
|
||||
};
|
||||
|
||||
/** A MySQL result
|
||||
*/
|
||||
class MySQLResult : public SQLResult
|
||||
class MySQLResult : public Result
|
||||
{
|
||||
MYSQL_RES *res;
|
||||
|
||||
public:
|
||||
MySQLResult(unsigned int i, const SQLQuery &q, const Anope::string &fq, MYSQL_RES *r) : SQLResult(i, q, fq), res(r)
|
||||
MySQLResult(unsigned int i, const Query &q, const Anope::string &fq, MYSQL_RES *r) : Result(i, q, fq), res(r)
|
||||
{
|
||||
unsigned num_fields = res ? mysql_num_fields(res) : 0;
|
||||
|
||||
@@ -79,7 +81,7 @@ class MySQLResult : public SQLResult
|
||||
}
|
||||
}
|
||||
|
||||
MySQLResult(const SQLQuery &q, const Anope::string &fq, const Anope::string &err) : SQLResult(0, q, fq, err), res(NULL)
|
||||
MySQLResult(const Query &q, const Anope::string &fq, const Anope::string &err) : Result(0, q, fq, err), res(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -92,7 +94,7 @@ class MySQLResult : public SQLResult
|
||||
|
||||
/** A MySQL connection, there can be multiple
|
||||
*/
|
||||
class MySQLService : public SQLProvider
|
||||
class MySQLService : public Provider
|
||||
{
|
||||
std::map<Anope::string, std::set<Anope::string> > active_schema;
|
||||
|
||||
@@ -120,21 +122,21 @@ class MySQLService : public SQLProvider
|
||||
|
||||
~MySQLService();
|
||||
|
||||
void Run(SQLInterface *i, const SQLQuery &query) anope_override;
|
||||
void Run(Interface *i, const Query &query) anope_override;
|
||||
|
||||
SQLResult RunQuery(const SQLQuery &query) anope_override;
|
||||
Result RunQuery(const Query &query) anope_override;
|
||||
|
||||
std::vector<SQLQuery> CreateTable(const Anope::string &table, const Serialize::Data &data) anope_override;
|
||||
std::vector<Query> CreateTable(const Anope::string &table, const Data &data) anope_override;
|
||||
|
||||
SQLQuery BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data);
|
||||
Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) anope_override;
|
||||
|
||||
SQLQuery GetTables(const Anope::string &prefix) anope_override;
|
||||
Query GetTables(const Anope::string &prefix) anope_override;
|
||||
|
||||
void Connect();
|
||||
|
||||
bool CheckConnection();
|
||||
|
||||
Anope::string BuildQuery(const SQLQuery &q);
|
||||
Anope::string BuildQuery(const Query &q);
|
||||
|
||||
Anope::string FromUnixtime(time_t);
|
||||
};
|
||||
@@ -235,7 +237,7 @@ class ModuleSQL : public Module, public Pipe
|
||||
|
||||
Log(LOG_NORMAL, "mysql") << "MySQL: Successfully connected to server " << connname << " (" << server << ")";
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
catch (const SQL::Exception &ex)
|
||||
{
|
||||
Log(LOG_NORMAL, "mysql") << "MySQL: " << ex.GetReason();
|
||||
}
|
||||
@@ -280,7 +282,7 @@ class ModuleSQL : public Module, public Pipe
|
||||
const QueryResult &qr = *it;
|
||||
|
||||
if (!qr.sqlinterface)
|
||||
throw SQLException("NULL qr.sqlinterface in MySQLPipe::OnNotify() ?");
|
||||
throw SQL::Exception("NULL qr.sqlinterface in MySQLPipe::OnNotify() ?");
|
||||
|
||||
if (qr.result.GetError().empty())
|
||||
qr.sqlinterface->OnResult(qr.result);
|
||||
@@ -291,7 +293,7 @@ class ModuleSQL : public Module, public Pipe
|
||||
};
|
||||
|
||||
MySQLService::MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, int po)
|
||||
: SQLProvider(o, n), database(d), server(s), user(u), password(p), port(po), sql(NULL)
|
||||
: Provider(o, n), database(d), server(s), user(u), password(p), port(po), sql(NULL)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
@@ -310,7 +312,7 @@ MySQLService::~MySQLService()
|
||||
if (r.service == this)
|
||||
{
|
||||
if (r.sqlinterface)
|
||||
r.sqlinterface->OnError(SQLResult(0, r.query, "SQL Interface is going away"));
|
||||
r.sqlinterface->OnError(Result(0, r.query, "SQL Interface is going away"));
|
||||
me->QueryRequests.erase(me->QueryRequests.begin() + i - 1);
|
||||
}
|
||||
}
|
||||
@@ -318,7 +320,7 @@ MySQLService::~MySQLService()
|
||||
me->DThread->Unlock();
|
||||
}
|
||||
|
||||
void MySQLService::Run(SQLInterface *i, const SQLQuery &query)
|
||||
void MySQLService::Run(Interface *i, const Query &query)
|
||||
{
|
||||
me->DThread->Lock();
|
||||
me->QueryRequests.push_back(QueryRequest(this, i, query));
|
||||
@@ -326,7 +328,7 @@ void MySQLService::Run(SQLInterface *i, const SQLQuery &query)
|
||||
me->DThread->Wakeup();
|
||||
}
|
||||
|
||||
SQLResult MySQLService::RunQuery(const SQLQuery &query)
|
||||
Result MySQLService::RunQuery(const Query &query)
|
||||
{
|
||||
this->Lock.Lock();
|
||||
|
||||
@@ -348,16 +350,16 @@ SQLResult MySQLService::RunQuery(const SQLQuery &query)
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, const Serialize::Data &data)
|
||||
std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const Data &data)
|
||||
{
|
||||
std::vector<SQLQuery> queries;
|
||||
std::vector<Query> queries;
|
||||
std::set<Anope::string> &known_cols = this->active_schema[table];
|
||||
|
||||
if (known_cols.empty())
|
||||
{
|
||||
Log(LOG_DEBUG) << "m_mysql: Fetching columns for " << table;
|
||||
|
||||
SQLResult columns = this->RunQuery("SHOW COLUMNS FROM `" + table + "`");
|
||||
Result columns = this->RunQuery("SHOW COLUMNS FROM `" + table + "`");
|
||||
for (int i = 0; i < columns.Rows(); ++i)
|
||||
{
|
||||
const Anope::string &column = columns.Get(i, "Field");
|
||||
@@ -371,15 +373,13 @@ std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, cons
|
||||
{
|
||||
Anope::string query_text = "CREATE TABLE `" + table + "` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,"
|
||||
" `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP";
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
{
|
||||
known_cols.insert(it->first);
|
||||
|
||||
query_text += ", `" + it->first + "` ";
|
||||
if (it->second.GetType() == Serialize::DT_INT)
|
||||
if (data.GetType(it->first) == Serialize::Data::DT_INT)
|
||||
query_text += "int(11)";
|
||||
else if (it->second.GetMax() > 0)
|
||||
query_text += "varchar(" + stringify(it->second.GetMax()) + ")";
|
||||
else
|
||||
query_text += "text";
|
||||
}
|
||||
@@ -387,7 +387,7 @@ std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, cons
|
||||
queries.push_back(query_text);
|
||||
}
|
||||
else
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
{
|
||||
if (known_cols.count(it->first) > 0)
|
||||
continue;
|
||||
@@ -395,10 +395,8 @@ std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, cons
|
||||
known_cols.insert(it->first);
|
||||
|
||||
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + it->first + "` ";
|
||||
if (it->second.GetType() == Serialize::DT_INT)
|
||||
if (data.GetType(it->first) == Serialize::Data::DT_INT)
|
||||
query_text += "int(11)";
|
||||
else if (it->second.GetMax() > 0)
|
||||
query_text += "varchar(" + stringify(it->second.GetMax()) + ")";
|
||||
else
|
||||
query_text += "text";
|
||||
|
||||
@@ -408,35 +406,39 @@ std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, cons
|
||||
return queries;
|
||||
}
|
||||
|
||||
SQLQuery MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data)
|
||||
Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Data &data) anope_override
|
||||
{
|
||||
/* Empty columns not present in the data set */
|
||||
const std::set<Anope::string> &known_cols = this->active_schema[table];
|
||||
for (std::set<Anope::string>::iterator it = known_cols.begin(), it_end = known_cols.end(); it != it_end; ++it)
|
||||
if (*it != "id" && *it != "timestamp" && data.count(*it) == 0)
|
||||
if (*it != "id" && *it != "timestamp" && data.data.count(*it) == 0)
|
||||
data[*it] << "";
|
||||
|
||||
Anope::string query_text = "INSERT INTO `" + table + "` (`id`";
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
query_text += ",`" + it->first + "`";
|
||||
query_text += ") VALUES (" + stringify(id);
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
query_text += ",@" + it->first + "@";
|
||||
query_text += ") ON DUPLICATE KEY UPDATE ";
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
query_text += "`" + it->first + "`=VALUES(`" + it->first + "`),";
|
||||
query_text.erase(query_text.end() - 1);
|
||||
|
||||
SQLQuery query(query_text);
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query.setValue(it->first, it->second.astr());
|
||||
Query query(query_text);
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
{
|
||||
Anope::string buf;
|
||||
*it->second >> buf;
|
||||
query.SetValue(it->first, buf);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
SQLQuery MySQLService::GetTables(const Anope::string &prefix)
|
||||
Query MySQLService::GetTables(const Anope::string &prefix)
|
||||
{
|
||||
return SQLQuery("SHOW TABLES LIKE '" + prefix + "%';");
|
||||
return Query("SHOW TABLES LIKE '" + prefix + "%';");
|
||||
}
|
||||
|
||||
void MySQLService::Connect()
|
||||
@@ -449,7 +451,7 @@ void MySQLService::Connect()
|
||||
bool connect = mysql_real_connect(this->sql, this->server.c_str(), this->user.c_str(), this->password.c_str(), this->database.c_str(), this->port, NULL, CLIENT_MULTI_RESULTS);
|
||||
|
||||
if (!connect)
|
||||
throw SQLException("Unable to connect to MySQL service " + this->name + ": " + mysql_error(this->sql));
|
||||
throw SQL::Exception("Unable to connect to MySQL service " + this->name + ": " + mysql_error(this->sql));
|
||||
|
||||
Log(LOG_DEBUG) << "Successfully connected to MySQL service " << this->name << " at " << this->server << ":" << this->port;
|
||||
}
|
||||
@@ -463,7 +465,7 @@ bool MySQLService::CheckConnection()
|
||||
{
|
||||
this->Connect();
|
||||
}
|
||||
catch (const SQLException &)
|
||||
catch (const SQL::Exception &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -479,7 +481,7 @@ Anope::string MySQLService::Escape(const Anope::string &query)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Anope::string MySQLService::BuildQuery(const SQLQuery &q)
|
||||
Anope::string MySQLService::BuildQuery(const Query &q)
|
||||
{
|
||||
Anope::string real_query = q.query;
|
||||
|
||||
@@ -505,7 +507,7 @@ void DispatcherThread::Run()
|
||||
QueryRequest &r = me->QueryRequests.front();
|
||||
this->Unlock();
|
||||
|
||||
SQLResult sresult = r.service->RunQuery(r.query);
|
||||
Result sresult = r.service->RunQuery(r.query);
|
||||
|
||||
this->Lock();
|
||||
if (!me->QueryRequests.empty() && me->QueryRequests.front().query == r.query)
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
static Module *me;
|
||||
|
||||
class SQLAuthenticationResult : public SQLInterface
|
||||
class SQLAuthenticationResult : public SQL::Interface
|
||||
{
|
||||
Reference<User> user;
|
||||
IdentifyRequest *req;
|
||||
|
||||
public:
|
||||
SQLAuthenticationResult(User *u, IdentifyRequest *r) : SQLInterface(me), user(u), req(r)
|
||||
SQLAuthenticationResult(User *u, IdentifyRequest *r) : SQL::Interface(me), user(u), req(r)
|
||||
{
|
||||
req->Hold(me);
|
||||
}
|
||||
@@ -19,7 +19,7 @@ class SQLAuthenticationResult : public SQLInterface
|
||||
req->Release(me);
|
||||
}
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
void OnResult(const SQL::Result &r) anope_override
|
||||
{
|
||||
if (r.Rows() == 0)
|
||||
{
|
||||
@@ -35,7 +35,7 @@ class SQLAuthenticationResult : public SQLInterface
|
||||
{
|
||||
email = r.Get(0, "email");
|
||||
}
|
||||
catch (const SQLException &) { }
|
||||
catch (const SQL::Exception &) { }
|
||||
|
||||
NickAlias *na = NickAlias::Find(req->GetAccount());
|
||||
if (na == NULL)
|
||||
@@ -62,7 +62,7 @@ class SQLAuthenticationResult : public SQLInterface
|
||||
delete this;
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r) anope_override
|
||||
void OnError(const SQL::Result &r) anope_override
|
||||
{
|
||||
Log(this->owner) << "m_sql_authentication: Error executing query " << r.GetQuery().query << ": " << r.GetError();
|
||||
delete this;
|
||||
@@ -76,7 +76,7 @@ class ModuleSQLAuthentication : public Module
|
||||
bool disable_register;
|
||||
Anope::string disable_reason;
|
||||
|
||||
ServiceReference<SQLProvider> SQL;
|
||||
ServiceReference<SQL::Provider> SQL;
|
||||
|
||||
public:
|
||||
ModuleSQLAuthentication(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED)
|
||||
@@ -100,7 +100,7 @@ class ModuleSQLAuthentication : public Module
|
||||
this->disable_register = config.ReadFlag("m_sql_authentication", "disable_ns_register", "false", 0);
|
||||
this->disable_reason = config.ReadValue("m_sql_authentication", "disable_reason", "", 0);
|
||||
|
||||
this->SQL = ServiceReference<SQLProvider>("SQLProvider", this->engine);
|
||||
this->SQL = ServiceReference<SQL::Provider>("SQL::Provider", this->engine);
|
||||
}
|
||||
|
||||
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) anope_override
|
||||
@@ -122,18 +122,18 @@ class ModuleSQLAuthentication : public Module
|
||||
return;
|
||||
}
|
||||
|
||||
SQLQuery q(this->query);
|
||||
q.setValue("a", req->GetAccount());
|
||||
q.setValue("p", req->GetPassword());
|
||||
SQL::Query q(this->query);
|
||||
q.SetValue("a", req->GetAccount());
|
||||
q.SetValue("p", req->GetPassword());
|
||||
if (u)
|
||||
{
|
||||
q.setValue("n", u->nick);
|
||||
q.setValue("i", u->ip);
|
||||
q.SetValue("n", u->nick);
|
||||
q.SetValue("i", u->ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
q.setValue("n", "");
|
||||
q.setValue("i", "");
|
||||
q.SetValue("n", "");
|
||||
q.SetValue("i", "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "module.h"
|
||||
#include "sql.h"
|
||||
|
||||
class SQLOperResult : public SQLInterface
|
||||
class SQLOperResult : public SQL::Interface
|
||||
{
|
||||
Reference<User> user;
|
||||
|
||||
@@ -13,9 +13,9 @@ class SQLOperResult : public SQLInterface
|
||||
};
|
||||
|
||||
public:
|
||||
SQLOperResult(Module *m, User *u) : SQLInterface(m), user(u) { }
|
||||
SQLOperResult(Module *m, User *u) : SQL::Interface(m), user(u) { }
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
void OnResult(const SQL::Result &r) anope_override
|
||||
{
|
||||
SQLOperResultDeleter d(this);
|
||||
|
||||
@@ -27,7 +27,7 @@ class SQLOperResult : public SQLInterface
|
||||
{
|
||||
opertype = r.Get(0, "opertype");
|
||||
}
|
||||
catch (const SQLException &)
|
||||
catch (const SQL::Exception &)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ class SQLOperResult : public SQLInterface
|
||||
{
|
||||
modes = r.Get(0, "modes");
|
||||
}
|
||||
catch (const SQLException &) { }
|
||||
catch (const SQL::Exception &) { }
|
||||
|
||||
if (opertype.empty())
|
||||
{
|
||||
@@ -79,7 +79,7 @@ class SQLOperResult : public SQLInterface
|
||||
}
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r) anope_override
|
||||
void OnError(const SQL::Result &r) anope_override
|
||||
{
|
||||
SQLOperResultDeleter d(this);
|
||||
Log(this->owner) << "m_sql_oper: Error executing query " << r.GetQuery().query << ": " << r.GetError();
|
||||
@@ -91,7 +91,7 @@ class ModuleSQLOper : public Module
|
||||
Anope::string engine;
|
||||
Anope::string query;
|
||||
|
||||
ServiceReference<SQLProvider> SQL;
|
||||
ServiceReference<SQL::Provider> SQL;
|
||||
|
||||
public:
|
||||
ModuleSQLOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED)
|
||||
@@ -111,7 +111,7 @@ class ModuleSQLOper : public Module
|
||||
this->engine = config.ReadValue("m_sql_oper", "engine", "", 0);
|
||||
this->query = config.ReadValue("m_sql_oper", "query", "", 0);
|
||||
|
||||
this->SQL = ServiceReference<SQLProvider>("SQLProvider", this->engine);
|
||||
this->SQL = ServiceReference<SQL::Provider>("SQL::Provider", this->engine);
|
||||
}
|
||||
|
||||
void OnNickIdentify(User *u) anope_override
|
||||
@@ -122,9 +122,9 @@ class ModuleSQLOper : public Module
|
||||
return;
|
||||
}
|
||||
|
||||
SQLQuery q(this->query);
|
||||
q.setValue("a", u->Account()->display);
|
||||
q.setValue("i", u->ip);
|
||||
SQL::Query q(this->query);
|
||||
q.SetValue("a", u->Account()->display);
|
||||
q.SetValue("i", u->ip);
|
||||
|
||||
this->SQL->Run(new SQLOperResult(this, u), q);
|
||||
|
||||
|
||||
+41
-35
@@ -4,22 +4,24 @@
|
||||
#include <sqlite3.h>
|
||||
#include "sql.h"
|
||||
|
||||
using namespace SQL;
|
||||
|
||||
/* SQLite3 API, based from InspiRCd */
|
||||
|
||||
/** A SQLite result
|
||||
*/
|
||||
class SQLiteResult : public SQLResult
|
||||
class SQLiteResult : public Result
|
||||
{
|
||||
public:
|
||||
SQLiteResult(unsigned int i, const SQLQuery &q, const Anope::string &fq) : SQLResult(i, q, fq)
|
||||
SQLiteResult(unsigned int i, const Query &q, const Anope::string &fq) : Result(i, q, fq)
|
||||
{
|
||||
}
|
||||
|
||||
SQLiteResult(const SQLQuery &q, const Anope::string &fq, const Anope::string &err) : SQLResult(0, q, fq, err)
|
||||
SQLiteResult(const Query &q, const Anope::string &fq, const Anope::string &err) : Result(0, q, fq, err)
|
||||
{
|
||||
}
|
||||
|
||||
void addRow(const std::map<Anope::string, Anope::string> &data)
|
||||
void AddRow(const std::map<Anope::string, Anope::string> &data)
|
||||
{
|
||||
this->entries.push_back(data);
|
||||
}
|
||||
@@ -27,7 +29,7 @@ class SQLiteResult : public SQLResult
|
||||
|
||||
/** A SQLite database, there can be multiple
|
||||
*/
|
||||
class SQLiteService : public SQLProvider
|
||||
class SQLiteService : public Provider
|
||||
{
|
||||
std::map<Anope::string, std::set<Anope::string> > active_schema;
|
||||
|
||||
@@ -42,17 +44,17 @@ class SQLiteService : public SQLProvider
|
||||
|
||||
~SQLiteService();
|
||||
|
||||
void Run(SQLInterface *i, const SQLQuery &query) anope_override;
|
||||
void Run(Interface *i, const Query &query) anope_override;
|
||||
|
||||
SQLResult RunQuery(const SQLQuery &query);
|
||||
Result RunQuery(const Query &query);
|
||||
|
||||
std::vector<SQLQuery> CreateTable(const Anope::string &table, const Serialize::Data &data) anope_override;
|
||||
std::vector<Query> CreateTable(const Anope::string &table, const Data &data) anope_override;
|
||||
|
||||
SQLQuery BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data);
|
||||
Query BuildInsert(const Anope::string &table, unsigned int id, Data &data);
|
||||
|
||||
SQLQuery GetTables(const Anope::string &prefix);
|
||||
Query GetTables(const Anope::string &prefix);
|
||||
|
||||
Anope::string BuildQuery(const SQLQuery &q);
|
||||
Anope::string BuildQuery(const Query &q);
|
||||
|
||||
Anope::string FromUnixtime(time_t);
|
||||
};
|
||||
@@ -116,7 +118,7 @@ class ModuleSQLite : public Module
|
||||
|
||||
Log(LOG_NORMAL, "sqlite") << "SQLite: Successfully added database " << database;
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
catch (const SQL::Exception &ex)
|
||||
{
|
||||
Log(LOG_NORMAL, "sqlite") << "SQLite: " << ex.GetReason();
|
||||
}
|
||||
@@ -126,11 +128,11 @@ class ModuleSQLite : public Module
|
||||
};
|
||||
|
||||
SQLiteService::SQLiteService(Module *o, const Anope::string &n, const Anope::string &d)
|
||||
: SQLProvider(o, n), database(d), sql(NULL)
|
||||
: Provider(o, n), database(d), sql(NULL)
|
||||
{
|
||||
int db = sqlite3_open_v2(database.c_str(), &this->sql, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
|
||||
if (db != SQLITE_OK)
|
||||
throw SQLException("Unable to open SQLite database " + database + ": " + sqlite3_errmsg(this->sql));
|
||||
throw SQL::Exception("Unable to open SQLite database " + database + ": " + sqlite3_errmsg(this->sql));
|
||||
}
|
||||
|
||||
SQLiteService::~SQLiteService()
|
||||
@@ -139,16 +141,16 @@ SQLiteService::~SQLiteService()
|
||||
sqlite3_close(this->sql);
|
||||
}
|
||||
|
||||
void SQLiteService::Run(SQLInterface *i, const SQLQuery &query)
|
||||
void SQLiteService::Run(Interface *i, const Query &query)
|
||||
{
|
||||
SQLResult res = this->RunQuery(query);
|
||||
Result res = this->RunQuery(query);
|
||||
if (!res.GetError().empty())
|
||||
i->OnError(res);
|
||||
else
|
||||
i->OnResult(res);
|
||||
}
|
||||
|
||||
SQLResult SQLiteService::RunQuery(const SQLQuery &query)
|
||||
Result SQLiteService::RunQuery(const Query &query)
|
||||
{
|
||||
Anope::string real_query = this->BuildQuery(query);
|
||||
sqlite3_stmt *stmt;
|
||||
@@ -173,7 +175,7 @@ SQLResult SQLiteService::RunQuery(const SQLQuery &query)
|
||||
if (data && *data)
|
||||
items[columns[i]] = data;
|
||||
}
|
||||
result.addRow(items);
|
||||
result.AddRow(items);
|
||||
}
|
||||
|
||||
result.id = sqlite3_last_insert_rowid(this->sql);
|
||||
@@ -186,16 +188,16 @@ SQLResult SQLiteService::RunQuery(const SQLQuery &query)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, const Serialize::Data &data)
|
||||
std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const Data &data)
|
||||
{
|
||||
std::vector<SQLQuery> queries;
|
||||
std::vector<Query> queries;
|
||||
std::set<Anope::string> &known_cols = this->active_schema[table];
|
||||
|
||||
if (known_cols.empty())
|
||||
{
|
||||
Log(LOG_DEBUG) << "m_sqlite: Fetching columns for " << table;
|
||||
|
||||
SQLResult columns = this->RunQuery("PRAGMA table_info(" + table + ")");
|
||||
Result columns = this->RunQuery("PRAGMA table_info(" + table + ")");
|
||||
for (int i = 0; i < columns.Rows(); ++i)
|
||||
{
|
||||
const Anope::string &column = columns.Get(i, "name");
|
||||
@@ -209,12 +211,12 @@ std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, con
|
||||
{
|
||||
Anope::string query_text = "CREATE TABLE `" + table + "` (`id` INTEGER PRIMARY KEY, `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP";
|
||||
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
{
|
||||
known_cols.insert(it->first);
|
||||
|
||||
query_text += ", `" + it->first + "` ";
|
||||
if (it->second.GetType() == Serialize::DT_INT)
|
||||
if (data.GetType(it->first) == Serialize::Data::DT_INT)
|
||||
query_text += "int(11)";
|
||||
else
|
||||
query_text += "text";
|
||||
@@ -234,7 +236,7 @@ std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, con
|
||||
queries.push_back(query_text);
|
||||
}
|
||||
else
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
{
|
||||
if (known_cols.count(it->first) > 0)
|
||||
continue;
|
||||
@@ -242,7 +244,7 @@ std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, con
|
||||
known_cols.insert(it->first);
|
||||
|
||||
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + it->first + "` ";
|
||||
if (it->second.GetType() == Serialize::DT_INT)
|
||||
if (data.GetType(it->first) == Serialize::Data::DT_INT)
|
||||
query_text += "int(11)";
|
||||
else
|
||||
query_text += "text";
|
||||
@@ -253,38 +255,42 @@ std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, con
|
||||
return queries;
|
||||
}
|
||||
|
||||
SQLQuery SQLiteService::BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data)
|
||||
Query SQLiteService::BuildInsert(const Anope::string &table, unsigned int id, Data &data)
|
||||
{
|
||||
/* Empty columns not present in the data set */
|
||||
const std::set<Anope::string> &known_cols = this->active_schema[table];
|
||||
for (std::set<Anope::string>::iterator it = known_cols.begin(), it_end = known_cols.end(); it != it_end; ++it)
|
||||
if (*it != "id" && *it != "timestamp" && data.count(*it) == 0)
|
||||
if (*it != "id" && *it != "timestamp" && data.data.count(*it) == 0)
|
||||
data[*it] << "";
|
||||
|
||||
Anope::string query_text = "REPLACE INTO `" + table + "` (";
|
||||
if (id > 0)
|
||||
query_text += "`id`,";
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
query_text += "`" + it->first + "`,";
|
||||
query_text.erase(query_text.length() - 1);
|
||||
query_text += ") VALUES (";
|
||||
if (id > 0)
|
||||
query_text += stringify(id) + ",";
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
query_text += "@" + it->first + "@,";
|
||||
query_text.erase(query_text.length() - 1);
|
||||
query_text += ")";
|
||||
|
||||
SQLQuery query(query_text);
|
||||
for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query.setValue(it->first, it->second.astr());
|
||||
Query query(query_text);
|
||||
for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
|
||||
{
|
||||
Anope::string buf;
|
||||
*it->second >> buf;
|
||||
query.SetValue(it->first, buf);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
SQLQuery SQLiteService::GetTables(const Anope::string &prefix)
|
||||
Query SQLiteService::GetTables(const Anope::string &prefix)
|
||||
{
|
||||
return SQLQuery("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '" + prefix + "%';");
|
||||
return Query("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '" + prefix + "%';");
|
||||
}
|
||||
|
||||
Anope::string SQLiteService::Escape(const Anope::string &query)
|
||||
@@ -295,7 +301,7 @@ Anope::string SQLiteService::Escape(const Anope::string &query)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Anope::string SQLiteService::BuildQuery(const SQLQuery &q)
|
||||
Anope::string SQLiteService::BuildQuery(const Query &q)
|
||||
{
|
||||
Anope::string real_query = q.query;
|
||||
|
||||
|
||||
+191
-111
@@ -1,139 +1,219 @@
|
||||
|
||||
/** A SQL exception, can be thrown at various points
|
||||
*/
|
||||
class SQLException : public ModuleException
|
||||
{
|
||||
public:
|
||||
SQLException(const Anope::string &reason) : ModuleException(reason) { }
|
||||
|
||||
virtual ~SQLException() throw() { }
|
||||
};
|
||||
|
||||
/** A SQL query
|
||||
/*
|
||||
* (C) 2003-2012 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
struct QueryData
|
||||
namespace SQL
|
||||
{
|
||||
Anope::string data;
|
||||
bool escape;
|
||||
};
|
||||
|
||||
struct SQLQuery
|
||||
{
|
||||
Anope::string query;
|
||||
std::map<Anope::string, QueryData> parameters;
|
||||
|
||||
SQLQuery() { }
|
||||
SQLQuery(const Anope::string &q) : query(q) { }
|
||||
|
||||
SQLQuery& operator=(const Anope::string &q)
|
||||
class Data : public Serialize::Data
|
||||
{
|
||||
this->query = q;
|
||||
this->parameters.clear();
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
typedef std::map<Anope::string, std::stringstream *> Map;
|
||||
Map data;
|
||||
std::map<Anope::string, Type> types;
|
||||
|
||||
bool operator==(const SQLQuery &other) const
|
||||
{
|
||||
return this->query == other.query;
|
||||
}
|
||||
|
||||
inline bool operator!=(const SQLQuery &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template<typename T> void setValue(const Anope::string &key, const T& value, bool escape = true)
|
||||
{
|
||||
try
|
||||
~Data()
|
||||
{
|
||||
Anope::string string_value = stringify(value);
|
||||
this->parameters[key].data = string_value;
|
||||
this->parameters[key].escape = escape;
|
||||
Clear();
|
||||
}
|
||||
catch (const ConvertException &ex) { }
|
||||
}
|
||||
};
|
||||
|
||||
/** A result from a SQL query
|
||||
*/
|
||||
class SQLResult
|
||||
{
|
||||
protected:
|
||||
/* Rows, column, item */
|
||||
std::vector<std::map<Anope::string, Anope::string> > entries;
|
||||
SQLQuery query;
|
||||
Anope::string error;
|
||||
public:
|
||||
unsigned int id;
|
||||
Anope::string finished_query;
|
||||
|
||||
SQLResult() : id(0) { }
|
||||
SQLResult(unsigned int i, const SQLQuery &q, const Anope::string &fq, const Anope::string &err = "") : query(q), error(err), id(i), finished_query(fq) { }
|
||||
|
||||
inline operator bool() const { return this->error.empty(); }
|
||||
|
||||
inline const unsigned int GetID() const { return this->id; }
|
||||
inline const SQLQuery &GetQuery() const { return this->query; }
|
||||
inline const Anope::string &GetError() const { return this->error; }
|
||||
|
||||
int Rows() const { return this->entries.size(); }
|
||||
|
||||
const std::map<Anope::string, Anope::string> &Row(size_t index) const
|
||||
{
|
||||
try
|
||||
std::iostream& operator[](const Anope::string &key) anope_override
|
||||
{
|
||||
return this->entries.at(index);
|
||||
std::stringstream *&ss = data[key];
|
||||
if (!ss)
|
||||
ss = new std::stringstream();
|
||||
return *ss;
|
||||
}
|
||||
catch (const std::out_of_range &)
|
||||
|
||||
bool IsEqual(Serialize::Data *other) anope_override
|
||||
{
|
||||
throw SQLException("Out of bounds access to SQLResult");
|
||||
try
|
||||
{
|
||||
Data *o = anope_dynamic_static_cast<Data *>(other);
|
||||
|
||||
for (std::map<Anope::string, std::stringstream *>::const_iterator it = o->data.begin(), it_end = o->data.end(); it != it_end; ++it)
|
||||
if (!this->data.count(it->first) || it->second->str() != this->data[it->first]->str())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const CoreException &ex)
|
||||
{
|
||||
Log(LOG_DEBUG) << ex.GetReason();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const Anope::string Get(size_t index, const Anope::string &col) const
|
||||
std::map<Anope::string, std::iostream *> GetData() const
|
||||
{
|
||||
std::map<Anope::string, std::iostream *> d;
|
||||
for (std::map<Anope::string, std::stringstream *>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
|
||||
d[it->first] = it->second;
|
||||
return d;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
for (std::map<Anope::string, std::stringstream *>::iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
|
||||
delete it->second;
|
||||
this->data.clear();
|
||||
}
|
||||
|
||||
void SetType(const Anope::string &key, Type t) anope_override
|
||||
{
|
||||
this->types[key] = t;
|
||||
}
|
||||
|
||||
Type GetType(const Anope::string &key) const anope_override
|
||||
{
|
||||
std::map<Anope::string, Type>::const_iterator it = this->types.find(key);
|
||||
if (it != this->types.end())
|
||||
return it->second;
|
||||
return DT_TEXT;
|
||||
}
|
||||
};
|
||||
|
||||
/** A SQL exception, can be thrown at various points
|
||||
*/
|
||||
class Exception : public ModuleException
|
||||
{
|
||||
const std::map<Anope::string, Anope::string> rows = this->Row(index);
|
||||
public:
|
||||
Exception(const Anope::string &reason) : ModuleException(reason) { }
|
||||
|
||||
std::map<Anope::string, Anope::string>::const_iterator it = rows.find(col);
|
||||
if (it == rows.end())
|
||||
throw SQLException("Unknown column name in SQLResult: " + col);
|
||||
virtual ~Exception() throw() { }
|
||||
};
|
||||
|
||||
return it->second;
|
||||
}
|
||||
};
|
||||
/** A SQL query
|
||||
*/
|
||||
|
||||
/* An interface used by modules to retrieve the results
|
||||
*/
|
||||
class SQLInterface
|
||||
{
|
||||
public:
|
||||
Module *owner;
|
||||
struct QueryData
|
||||
{
|
||||
Anope::string data;
|
||||
bool escape;
|
||||
};
|
||||
|
||||
SQLInterface(Module *m) : owner(m) { }
|
||||
virtual ~SQLInterface() { }
|
||||
struct Query
|
||||
{
|
||||
Anope::string query;
|
||||
std::map<Anope::string, QueryData> parameters;
|
||||
|
||||
virtual void OnResult(const SQLResult &r) = 0;
|
||||
virtual void OnError(const SQLResult &r) = 0;
|
||||
};
|
||||
Query() { }
|
||||
Query(const Anope::string &q) : query(q) { }
|
||||
|
||||
/** Class providing the SQL service, modules call this to execute queries
|
||||
*/
|
||||
class SQLProvider : public Service
|
||||
{
|
||||
public:
|
||||
SQLProvider(Module *c, const Anope::string &n) : Service(c, "SQLProvider", n) { }
|
||||
Query& operator=(const Anope::string &q)
|
||||
{
|
||||
this->query = q;
|
||||
this->parameters.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual void Run(SQLInterface *i, const SQLQuery &query) = 0;
|
||||
bool operator==(const Query &other) const
|
||||
{
|
||||
return this->query == other.query;
|
||||
}
|
||||
|
||||
virtual SQLResult RunQuery(const SQLQuery &query) = 0;
|
||||
inline bool operator!=(const Query &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
virtual std::vector<SQLQuery> CreateTable(const Anope::string &table, const Serialize::Data &data) = 0;
|
||||
template<typename T> void SetValue(const Anope::string &key, const T& value, bool escape = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
Anope::string string_value = stringify(value);
|
||||
this->parameters[key].data = string_value;
|
||||
this->parameters[key].escape = escape;
|
||||
}
|
||||
catch (const ConvertException &ex) { }
|
||||
}
|
||||
};
|
||||
|
||||
virtual SQLQuery BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data) = 0;
|
||||
/** A result from a SQL query
|
||||
*/
|
||||
class Result
|
||||
{
|
||||
protected:
|
||||
/* Rows, column, item */
|
||||
std::vector<std::map<Anope::string, Anope::string> > entries;
|
||||
Query query;
|
||||
Anope::string error;
|
||||
public:
|
||||
unsigned int id;
|
||||
Anope::string finished_query;
|
||||
|
||||
virtual SQLQuery GetTables(const Anope::string &prefix) = 0;
|
||||
Result() : id(0) { }
|
||||
Result(unsigned int i, const Query &q, const Anope::string &fq, const Anope::string &err = "") : query(q), error(err), id(i), finished_query(fq) { }
|
||||
|
||||
virtual Anope::string FromUnixtime(time_t) = 0;
|
||||
};
|
||||
inline operator bool() const { return this->error.empty(); }
|
||||
|
||||
inline const unsigned int GetID() const { return this->id; }
|
||||
inline const Query &GetQuery() const { return this->query; }
|
||||
inline const Anope::string &GetError() const { return this->error; }
|
||||
|
||||
int Rows() const { return this->entries.size(); }
|
||||
|
||||
const std::map<Anope::string, Anope::string> &Row(size_t index) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return this->entries.at(index);
|
||||
}
|
||||
catch (const std::out_of_range &)
|
||||
{
|
||||
throw Exception("Out of bounds access to SQLResult");
|
||||
}
|
||||
}
|
||||
|
||||
const Anope::string Get(size_t index, const Anope::string &col) const
|
||||
{
|
||||
const std::map<Anope::string, Anope::string> rows = this->Row(index);
|
||||
|
||||
std::map<Anope::string, Anope::string>::const_iterator it = rows.find(col);
|
||||
if (it == rows.end())
|
||||
throw Exception("Unknown column name in SQLResult: " + col);
|
||||
|
||||
return it->second;
|
||||
}
|
||||
};
|
||||
|
||||
/* An interface used by modules to retrieve the results
|
||||
*/
|
||||
class Interface
|
||||
{
|
||||
public:
|
||||
Module *owner;
|
||||
|
||||
Interface(Module *m) : owner(m) { }
|
||||
virtual ~Interface() { }
|
||||
|
||||
virtual void OnResult(const Result &r) = 0;
|
||||
virtual void OnError(const Result &r) = 0;
|
||||
};
|
||||
|
||||
/** Class providing the SQL service, modules call this to execute queries
|
||||
*/
|
||||
class Provider : public Service
|
||||
{
|
||||
public:
|
||||
Provider(Module *c, const Anope::string &n) : Service(c, "SQL::Provider", n) { }
|
||||
|
||||
virtual void Run(Interface *i, const Query &query) = 0;
|
||||
|
||||
virtual Result RunQuery(const Query &query) = 0;
|
||||
|
||||
virtual std::vector<Query> CreateTable(const Anope::string &table, const Data &data) = 0;
|
||||
|
||||
virtual Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) = 0;
|
||||
|
||||
virtual Query GetTables(const Anope::string &prefix) = 0;
|
||||
|
||||
virtual Anope::string FromUnixtime(time_t) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
|
||||
|
||||
if ((!highest || *highest <= *new_acc) && !u_access.founder && !has_priv)
|
||||
delete new_acc;
|
||||
else if (new_acc->Serialize().empty())
|
||||
else if (new_acc->AccessSerialize().empty())
|
||||
{
|
||||
replacements["MESSAGES"] = "Invalid access expression for the given type";
|
||||
delete new_acc;
|
||||
|
||||
@@ -11,14 +11,6 @@ if(WIN32)
|
||||
append_to_list(SRC_SRCS win32/sigaction/sigaction.cpp)
|
||||
endif(WIN32)
|
||||
|
||||
# If we have eventfd, use it
|
||||
if(HAVE_EVENTFD)
|
||||
append_to_list(SRC_SRCS socketengines/pipeengine_pipe.cpp)
|
||||
# Else fall back to pipe
|
||||
else(HAVE_EVENTFD)
|
||||
append_to_list(SRC_SRCS socketengines/pipeengine_pipe.cpp)
|
||||
endif(HAVE_EVENTFD)
|
||||
|
||||
if(HAVE_EPOLL)
|
||||
append_to_list(SRC_SRCS socketengines/socketengine_epoll.cpp)
|
||||
else(HAVE_EPOLL)
|
||||
|
||||
+14
-10
@@ -99,25 +99,26 @@ ChanAccess::~ChanAccess()
|
||||
{
|
||||
}
|
||||
|
||||
Serialize::Data ChanAccess::Serialize() const
|
||||
void ChanAccess::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["provider"] << this->provider->name;
|
||||
data["ci"] << this->ci->name;
|
||||
data["mask"] << this->mask;
|
||||
data["creator"] << this->creator;
|
||||
data["last_seen"].SetType(Serialize::DT_INT) << this->last_seen;
|
||||
data["created"].SetType(Serialize::DT_INT) << this->created;
|
||||
data.SetType("last_seen", Serialize::Data::DT_INT); data["last_seen"] << this->last_seen;
|
||||
data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
|
||||
data["data"] << this->AccessSerialize();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
ServiceReference<AccessProvider> aprovider("AccessProvider", data["provider"].astr());
|
||||
ChannelInfo *ci = ChannelInfo::Find(data["ci"].astr());
|
||||
Anope::string provider, chan;
|
||||
|
||||
data["provider"] >> provider;
|
||||
data["ci"] >>chan;
|
||||
|
||||
ServiceReference<AccessProvider> aprovider("AccessProvider", provider);
|
||||
ChannelInfo *ci = ChannelInfo::Find(chan);
|
||||
if (!aprovider || !ci)
|
||||
return NULL;
|
||||
|
||||
@@ -131,7 +132,10 @@ Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
data["creator"] >> access->creator;
|
||||
data["last_seen"] >> access->last_seen;
|
||||
data["created"] >> access->created;
|
||||
access->AccessUnserialize(data["data"].astr());
|
||||
|
||||
Anope::string adata;
|
||||
data["data"] >> adata;
|
||||
access->AccessUnserialize(adata);
|
||||
|
||||
if (!obj)
|
||||
ci->AddAccess(access);
|
||||
|
||||
+17
-5
@@ -14,25 +14,37 @@
|
||||
std::map<Anope::string, std::map<Anope::string, Service *> > Service::Services;
|
||||
std::map<Anope::string, std::map<Anope::string, Anope::string> > Service::Aliases;
|
||||
|
||||
Base::Base()
|
||||
Base::Base() : references(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Base::~Base()
|
||||
{
|
||||
for (std::set<ReferenceBase *>::iterator it = this->references.begin(), it_end = this->references.end(); it != it_end; ++it)
|
||||
if (this->references != NULL)
|
||||
{
|
||||
(*it)->Invalidate();
|
||||
for (std::set<ReferenceBase *>::iterator it = this->references->begin(), it_end = this->references->end(); it != it_end; ++it)
|
||||
(*it)->Invalidate();
|
||||
delete this->references;
|
||||
}
|
||||
}
|
||||
|
||||
void Base::AddReference(ReferenceBase *r)
|
||||
{
|
||||
this->references.insert(r);
|
||||
if (this->references == NULL)
|
||||
this->references = new std::set<ReferenceBase *>();
|
||||
this->references->insert(r);
|
||||
}
|
||||
|
||||
void Base::DelReference(ReferenceBase *r)
|
||||
{
|
||||
this->references.erase(r);
|
||||
if (this->references != NULL)
|
||||
{
|
||||
this->references->erase(r);
|
||||
if (this->references->empty())
|
||||
{
|
||||
delete this->references;
|
||||
this->references = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-9
@@ -82,29 +82,33 @@ BotInfo::~BotInfo()
|
||||
BotListByUID->erase(this->uid);
|
||||
}
|
||||
|
||||
Serialize::Data BotInfo::Serialize() const
|
||||
void BotInfo::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["nick"].SetMax(64)/*XXX*/ << this->nick;
|
||||
data["nick"] << this->nick;
|
||||
data["user"] << this->ident;
|
||||
data["host"] << this->host;
|
||||
data["realname"] << this->realname;
|
||||
data["created"] << this->created;
|
||||
data["flags"] << this->ToString();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* BotInfo::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
Anope::string nick, user, host, realname, flags;
|
||||
|
||||
data["nick"] >> nick;
|
||||
data["user"] >> user;
|
||||
data["host"] >> host;
|
||||
data["realname"] >> realname;
|
||||
data["flags"] >> flags;
|
||||
|
||||
BotInfo *bi;
|
||||
if (obj)
|
||||
bi = anope_dynamic_static_cast<BotInfo *>(obj);
|
||||
else if (!(bi = BotInfo::Find(data["nick"].astr())))
|
||||
bi = new BotInfo(data["nick"].astr(), data["user"].astr(), data["host"].astr(), data["realname"].astr());
|
||||
else if (!(bi = BotInfo::Find(nick)))
|
||||
bi = new BotInfo(nick, user, host, realname);
|
||||
data["created"] >> bi->created;
|
||||
bi->FromString(data["flags"].astr());
|
||||
bi->FromString(flags);
|
||||
return bi;
|
||||
}
|
||||
|
||||
|
||||
+91
-90
@@ -16,7 +16,6 @@
|
||||
#include "protocol.h"
|
||||
#include "bots.h"
|
||||
#include "xline.h"
|
||||
#include "signals.h"
|
||||
#include "socketengine.h"
|
||||
#include "servers.h"
|
||||
#include "language.h"
|
||||
@@ -91,91 +90,6 @@ static bool GetCommandLineArgument(const Anope::string &name, char shortname = 0
|
||||
return GetCommandLineArgument(name, shortname, Unused);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Remove our PID file. Done at exit. */
|
||||
|
||||
static void remove_pidfile()
|
||||
{
|
||||
remove(Config->PIDFilename.c_str());
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Create our PID file and write the PID to it. */
|
||||
|
||||
static void write_pidfile()
|
||||
{
|
||||
FILE *pidfile = fopen(Config->PIDFilename.c_str(), "w");
|
||||
if (pidfile)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fprintf(pidfile, "%d\n", static_cast<int>(GetCurrentProcessId()));
|
||||
#else
|
||||
fprintf(pidfile, "%d\n", static_cast<int>(getpid()));
|
||||
#endif
|
||||
fclose(pidfile);
|
||||
atexit(remove_pidfile);
|
||||
}
|
||||
else
|
||||
throw CoreException("Can not write to PID file " + Config->PIDFilename);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class SignalReload : public Signal
|
||||
{
|
||||
public:
|
||||
SignalReload(int sig) : Signal(sig) { }
|
||||
|
||||
void OnNotify()
|
||||
{
|
||||
Log() << "Received SIGHUP: Saving databases & rehashing configuration";
|
||||
|
||||
Anope::SaveDatabases();
|
||||
|
||||
ServerConfig *old_config = Config;
|
||||
try
|
||||
{
|
||||
Config = new ServerConfig();
|
||||
FOREACH_MOD(I_OnReload, OnReload());
|
||||
delete old_config;
|
||||
}
|
||||
catch (const ConfigException &ex)
|
||||
{
|
||||
Config = old_config;
|
||||
Log() << "Error reloading configuration file: " << ex.GetReason();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SignalExit : public Signal
|
||||
{
|
||||
public:
|
||||
SignalExit(int sig) : Signal(sig) { }
|
||||
|
||||
void OnNotify()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
Log() << "Received " << strsignal(this->signal) << " signal (" << this->signal << "), exiting.";
|
||||
Anope::QuitReason = Anope::string("Services terminating via signal ") + strsignal(this->signal) + " (" + stringify(this->signal) + ")";
|
||||
#else
|
||||
Log() << "Received signal " << this->signal << ", exiting.";
|
||||
Anope::QuitReason = Anope::string("Services terminating via signal ") + stringify(this->signal);
|
||||
#endif
|
||||
Anope::SaveDatabases();
|
||||
Anope::Quitting = true;
|
||||
}
|
||||
};
|
||||
|
||||
class SignalNothing : public Signal
|
||||
{
|
||||
public:
|
||||
SignalNothing(int sig) : Signal(sig) { }
|
||||
|
||||
void OnNotify() { }
|
||||
};
|
||||
|
||||
bool Anope::AtTerm()
|
||||
{
|
||||
return isatty(fileno(stdout)) && isatty(fileno(stdin)) && isatty(fileno(stderr));
|
||||
@@ -196,6 +110,45 @@ void Anope::Fork()
|
||||
#endif
|
||||
}
|
||||
|
||||
void Anope::HandleSignal()
|
||||
{
|
||||
switch (Signal)
|
||||
{
|
||||
case SIGHUP:
|
||||
{
|
||||
Anope::SaveDatabases();
|
||||
|
||||
ServerConfig *old_config = Config;
|
||||
try
|
||||
{
|
||||
Config = new ServerConfig();
|
||||
FOREACH_MOD(I_OnReload, OnReload());
|
||||
delete old_config;
|
||||
}
|
||||
catch (const ConfigException &ex)
|
||||
{
|
||||
Config = old_config;
|
||||
Log() << "Error reloading configuration file: " << ex.GetReason();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
#ifndef _WIN32
|
||||
Log() << "Received " << strsignal(Signal) << " signal (" << Signal << "), exiting.";
|
||||
Anope::QuitReason = Anope::string("Services terminating via signal ") + strsignal(Signal) + " (" + stringify(Signal) + ")";
|
||||
#else
|
||||
Log() << "Received signal " << Signal << ", exiting.";
|
||||
Anope::QuitReason = Anope::string("Services terminating via signal ") + stringify(Signal);
|
||||
#endif
|
||||
Anope::SaveDatabases();
|
||||
Anope::Quitting = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Signal = 0;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static void parent_signal_handler(int signal)
|
||||
{
|
||||
@@ -215,6 +168,57 @@ static void parent_signal_handler(int signal)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SignalHandler(int sig)
|
||||
{
|
||||
Anope::Signal = sig;
|
||||
}
|
||||
|
||||
static void InitSignals()
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
sa.sa_handler = SignalHandler;
|
||||
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
}
|
||||
|
||||
/* Remove our PID file. Done at exit. */
|
||||
|
||||
static void remove_pidfile()
|
||||
{
|
||||
remove(Config->PIDFilename.c_str());
|
||||
}
|
||||
|
||||
/* Create our PID file and write the PID to it. */
|
||||
|
||||
static void write_pidfile()
|
||||
{
|
||||
FILE *pidfile = fopen(Config->PIDFilename.c_str(), "w");
|
||||
if (pidfile)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fprintf(pidfile, "%d\n", static_cast<int>(GetCurrentProcessId()));
|
||||
#else
|
||||
fprintf(pidfile, "%d\n", static_cast<int>(getpid()));
|
||||
#endif
|
||||
fclose(pidfile);
|
||||
atexit(remove_pidfile);
|
||||
}
|
||||
else
|
||||
throw CoreException("Can not write to PID file " + Config->PIDFilename);
|
||||
}
|
||||
|
||||
void Anope::Init(int ac, char **av)
|
||||
{
|
||||
/* Set file creation mask and group ID. */
|
||||
@@ -432,10 +436,7 @@ void Anope::Init(int ac, char **av)
|
||||
/* Announce ourselves to the logfile. */
|
||||
Log() << "Anope " << Anope::Version() << " starting up" << (Anope::Debug || Anope::ReadOnly ? " (options:" : "") << (Anope::Debug ? " debug" : "") << (Anope::ReadOnly ? " readonly" : "") << (Anope::Debug || Anope::ReadOnly ? ")" : "");
|
||||
|
||||
new SignalReload(SIGHUP);
|
||||
new SignalExit(SIGTERM);
|
||||
new SignalExit(SIGINT);
|
||||
new SignalNothing(SIGPIPE);
|
||||
InitSignals();
|
||||
|
||||
/* Initialize multi-language support */
|
||||
Language::InitLanguages();
|
||||
|
||||
+4
-35
@@ -14,7 +14,6 @@
|
||||
#include "timers.h"
|
||||
#include "config.h"
|
||||
#include "bots.h"
|
||||
#include "signals.h"
|
||||
#include "socketengine.h"
|
||||
#include "uplink.h"
|
||||
|
||||
@@ -31,6 +30,7 @@ Anope::string Anope::ServicesDir;
|
||||
Anope::string Anope::ServicesBin;
|
||||
|
||||
int Anope::ReturnValue = 0;
|
||||
sig_atomic_t Anope::Signal = 0;
|
||||
bool Anope::Quitting = false;
|
||||
bool Anope::Restarting = false;
|
||||
Anope::string Anope::QuitReason;
|
||||
@@ -63,40 +63,6 @@ void Anope::SaveDatabases()
|
||||
Log(LOG_DEBUG) << "Saving databases";
|
||||
}
|
||||
|
||||
std::vector<Signal *> Signal::SignalHandlers;
|
||||
|
||||
void Signal::SignalHandler(int signal)
|
||||
{
|
||||
for (unsigned i = 0, j = SignalHandlers.size(); i < j; ++i)
|
||||
if (SignalHandlers[i]->signal == signal)
|
||||
SignalHandlers[i]->Notify();
|
||||
}
|
||||
|
||||
Signal::Signal(int s) : Pipe(), signal(s)
|
||||
{
|
||||
memset(&this->old, 0, sizeof(this->old));
|
||||
|
||||
this->action.sa_flags = 0;
|
||||
sigemptyset(&this->action.sa_mask);
|
||||
this->action.sa_handler = SignalHandler;
|
||||
|
||||
if (sigaction(s, &this->action, &this->old) == -1)
|
||||
throw CoreException("Unable to install signal " + stringify(s) + ": " + Anope::LastError());
|
||||
|
||||
SignalHandlers.push_back(this);
|
||||
}
|
||||
|
||||
Signal::~Signal()
|
||||
{
|
||||
std::vector<Signal *>::iterator it = std::find(SignalHandlers.begin(), SignalHandlers.end(), this);
|
||||
if (it != SignalHandlers.end())
|
||||
SignalHandlers.erase(it);
|
||||
|
||||
sigaction(this->signal, &this->old, NULL);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/** The following comes from InspIRCd to get the full path of the Anope executable
|
||||
*/
|
||||
static Anope::string GetFullProgDir(const Anope::string &argv0)
|
||||
@@ -196,6 +162,9 @@ int main(int ac, char **av, char **envp)
|
||||
|
||||
/* Process the socket engine */
|
||||
SocketEngine::Process();
|
||||
|
||||
if (Anope::Signal)
|
||||
Anope::HandleSignal();
|
||||
}
|
||||
|
||||
if (Anope::Restarting)
|
||||
|
||||
+9
-8
@@ -24,17 +24,13 @@ template<> const Anope::string* Flags<MemoFlag>::flags_strings = MemoFlagString;
|
||||
|
||||
Memo::Memo() : Serializable("Memo") { }
|
||||
|
||||
Serialize::Data Memo::Serialize() const
|
||||
void Memo::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["owner"] << this->owner;
|
||||
data["time"].SetType(Serialize::DT_INT) << this->time;
|
||||
data.SetType("time", Serialize::Data::DT_INT); data["time"] << this->time;
|
||||
data["sender"] << this->sender;
|
||||
data["text"] << this->text;
|
||||
data["flags"] << this->ToString();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* Memo::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
@@ -42,8 +38,13 @@ Serializable* Memo::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
if (!MemoServService)
|
||||
return NULL;
|
||||
|
||||
Anope::string owner, flags;
|
||||
|
||||
data["owner"] >> owner;
|
||||
data["flags"] >> flags;
|
||||
|
||||
bool ischan;
|
||||
MemoInfo *mi = MemoServService->GetMemoInfo(data["owner"].astr(), ischan);
|
||||
MemoInfo *mi = MemoServService->GetMemoInfo(owner, ischan);
|
||||
if (!mi)
|
||||
return NULL;
|
||||
|
||||
@@ -56,7 +57,7 @@ Serializable* Memo::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
data["time"] >> m->time;
|
||||
data["sender"] >> m->sender;
|
||||
data["text"] >> m->text;
|
||||
m->FromString(data["flags"].astr());
|
||||
m->FromString(flags);
|
||||
|
||||
if (obj == NULL)
|
||||
mi->memos->push_back(m);
|
||||
|
||||
@@ -93,16 +93,15 @@ static ModuleReturn moduleCopyFile(const Anope::string &name, Anope::string &out
|
||||
}
|
||||
|
||||
int want = s.st_size;
|
||||
char *buffer = new char[s.st_size];
|
||||
char buffer[1024];
|
||||
while (want > 0 && !source.fail() && !target.fail())
|
||||
{
|
||||
source.read(buffer, want);
|
||||
source.read(buffer, std::min(want, static_cast<int>(sizeof(buffer))));
|
||||
int read_len = source.gcount();
|
||||
|
||||
target.write(buffer, read_len);
|
||||
want -= read_len;
|
||||
}
|
||||
delete [] buffer;
|
||||
|
||||
source.close();
|
||||
target.close();
|
||||
|
||||
+22
-12
@@ -238,17 +238,15 @@ NickAlias *NickAlias::Find(const Anope::string &nick)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Serialize::Data NickAlias::Serialize() const
|
||||
void NickAlias::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["nick"].SetMax(Config->NickLen) << this->nick;
|
||||
data["nick"] << this->nick;
|
||||
data["last_quit"] << this->last_quit;
|
||||
data["last_realname"] << this->last_realname;
|
||||
data["last_usermask"] << this->last_usermask;
|
||||
data["last_realhost"] << this->last_realhost;
|
||||
data["time_registered"].SetType(Serialize::DT_INT) << this->time_registered;
|
||||
data["last_seen"].SetType(Serialize::DT_INT) << this->last_seen;
|
||||
data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered;
|
||||
data.SetType("time_registered", Serialize::Data::DT_INT); data["last_seen"] << this->last_seen;
|
||||
data["nc"] << this->nc->display;
|
||||
data["flags"] << this->ToString();
|
||||
|
||||
@@ -259,13 +257,16 @@ Serialize::Data NickAlias::Serialize() const
|
||||
data["vhost_creator"] << this->GetVhostCreator();
|
||||
data["vhost_time"] << this->GetVhostCreated();
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
NickCore *core = NickCore::Find(data["nc"].astr());
|
||||
Anope::string snc, snick;
|
||||
|
||||
data["nc"] >> snc;
|
||||
data["nick"] >> snick;
|
||||
|
||||
NickCore *core = NickCore::Find(snc);
|
||||
if (core == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -273,7 +274,7 @@ Serializable* NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
if (obj)
|
||||
na = anope_dynamic_static_cast<NickAlias *>(obj);
|
||||
else
|
||||
na = new NickAlias(data["nick"].astr(), core);
|
||||
na = new NickAlias(snick, core);
|
||||
|
||||
if (na->nc != core)
|
||||
{
|
||||
@@ -296,11 +297,20 @@ Serializable* NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
data["last_realhost"] >> na->last_realhost;
|
||||
data["time_registered"] >> na->time_registered;
|
||||
data["last_seen"] >> na->last_seen;
|
||||
na->FromString(data["flags"].astr());
|
||||
|
||||
Anope::string flags;
|
||||
data["flags"] >> flags;
|
||||
na->FromString(flags);
|
||||
|
||||
Anope::string vhost_ident, vhost_host, vhost_creator;
|
||||
time_t vhost_time;
|
||||
|
||||
data["vhost_ident"] >> vhost_ident;
|
||||
data["vhost_host"] >> vhost_host;
|
||||
data["vhost_creator"] >> vhost_creator;
|
||||
data["vhost_time"] >> vhost_time;
|
||||
na->SetVhost(data["vhost_ident"].astr(), data["vhost_host"].astr(), data["vhost_creator"].astr(), vhost_time);
|
||||
|
||||
na->SetVhost(vhost_ident, vhost_host, vhost_creator, vhost_time);
|
||||
return na;
|
||||
}
|
||||
|
||||
|
||||
+9
-8
@@ -78,11 +78,9 @@ NickCore::~NickCore()
|
||||
}
|
||||
}
|
||||
|
||||
Serialize::Data NickCore::Serialize() const
|
||||
void NickCore::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["display"].SetMax(Config->NickLen) << this->display;
|
||||
data["display"] << this->display;
|
||||
data["pass"] << this->pass;
|
||||
data["email"] << this->email;
|
||||
data["greet"] << this->greet;
|
||||
@@ -95,24 +93,27 @@ Serialize::Data NickCore::Serialize() const
|
||||
data["memomax"] << this->memos.memomax;
|
||||
for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
|
||||
data["memoignores"] << this->memos.ignores[i] << " ";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
NickCore *nc;
|
||||
|
||||
Anope::string sdisplay, sflags;
|
||||
|
||||
data["display"] >> sdisplay;
|
||||
data["flags"] >> sflags;
|
||||
|
||||
if (obj)
|
||||
nc = anope_dynamic_static_cast<NickCore *>(obj);
|
||||
else
|
||||
nc = new NickCore(data["display"].astr());
|
||||
nc = new NickCore(sdisplay);
|
||||
|
||||
data["pass"] >> nc->pass;
|
||||
data["email"] >> nc->email;
|
||||
data["greet"] >> nc->greet;
|
||||
data["language"] >> nc->language;
|
||||
nc->FromString(data["flags"].astr());
|
||||
nc->FromString(sflags);
|
||||
{
|
||||
Anope::string buf;
|
||||
data["access"] >> buf;
|
||||
|
||||
@@ -48,15 +48,34 @@ Pipe::~Pipe()
|
||||
|
||||
bool Pipe::ProcessRead()
|
||||
{
|
||||
this->OnNotify();
|
||||
|
||||
char dummy[512];
|
||||
while (read(this->GetFD(), dummy, 512) == 512);
|
||||
this->OnNotify();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Pipe::Write(const char *data, size_t sz)
|
||||
{
|
||||
write(this->write_pipe, data, sz);
|
||||
}
|
||||
|
||||
int Pipe::Read(char *data, size_t sz)
|
||||
{
|
||||
return read(this->GetFD(), data, sz);
|
||||
}
|
||||
|
||||
bool Pipe::SetWriteBlocking(bool state)
|
||||
{
|
||||
int flags = fcntl(this->write_pipe, F_GETFL, 0);
|
||||
if (state)
|
||||
return !fcntl(this->write_pipe, F_SETFL, flags & ~O_NONBLOCK);
|
||||
else
|
||||
return !fcntl(this->write_pipe, F_SETFL, flags | O_NONBLOCK);
|
||||
}
|
||||
|
||||
void Pipe::Notify()
|
||||
{
|
||||
const char dummy = '*';
|
||||
write(this->write_pipe, &dummy, 1);
|
||||
this->Write("\0", 1);
|
||||
}
|
||||
|
||||
+99
-81
@@ -34,20 +34,21 @@ template<> const Anope::string* Flags<ChannelInfoFlag>::flags_strings = ChannelI
|
||||
static const Anope::string AutoKickFlagString[] = { "AK_ISNICK", "" };
|
||||
template<> const Anope::string* Flags<AutoKickFlag>::flags_strings = AutoKickFlagString;
|
||||
|
||||
Serialize::Data BadWord::Serialize() const
|
||||
void BadWord::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["ci"].SetMax(64)/*XXX*/ << this->ci->name;
|
||||
data["word"].SetMax(512) << this->word;
|
||||
data["type"].SetType(Serialize::DT_INT) << this->type;
|
||||
|
||||
return data;
|
||||
data["ci"] << this->ci->name;
|
||||
data["word"] << this->word;
|
||||
data.SetType("type", Serialize::Data::DT_INT); data["type"] << this->type;
|
||||
}
|
||||
|
||||
Serializable* BadWord::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
ChannelInfo *ci = ChannelInfo::Find(data["ci"].astr());
|
||||
Anope::string sci, sword;
|
||||
|
||||
data["ci"] >> sci;
|
||||
data["word"] >> sword;
|
||||
|
||||
ChannelInfo *ci = ChannelInfo::Find(sci);
|
||||
if (!ci)
|
||||
return NULL;
|
||||
|
||||
@@ -62,7 +63,7 @@ Serializable* BadWord::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
bw->type = static_cast<BadWordType>(n);
|
||||
}
|
||||
else
|
||||
bw = ci->AddBadWord(data["word"].astr(), static_cast<BadWordType>(n));
|
||||
bw = ci->AddBadWord(sword, static_cast<BadWordType>(n));
|
||||
|
||||
return bw;
|
||||
}
|
||||
@@ -71,38 +72,39 @@ AutoKick::AutoKick() : Serializable("AutoKick")
|
||||
{
|
||||
}
|
||||
|
||||
Serialize::Data AutoKick::Serialize() const
|
||||
void AutoKick::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["ci"].SetMax(64)/*XXX*/ << this->ci->name;
|
||||
data["ci"] << this->ci->name;
|
||||
if (this->HasFlag(AK_ISNICK) && this->nc)
|
||||
data["nc"].SetMax(Config->NickLen) << this->nc->display;
|
||||
data["nc"] << this->nc->display;
|
||||
else
|
||||
data["mask"].SetMax(Config->NickLen) << this->mask;
|
||||
data["mask"] << this->mask;
|
||||
data["reason"] << this->reason;
|
||||
data["creator"] << this->creator;
|
||||
data["addtime"].SetType(Serialize::DT_INT) << this->addtime;
|
||||
data["last_used"].SetType(Serialize::DT_INT) << this->last_used;
|
||||
data.SetType("addtime", Serialize::Data::DT_INT); data["addtime"] << this->addtime;
|
||||
data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used;
|
||||
data["flags"] << this->ToString();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* AutoKick::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
ChannelInfo *ci = ChannelInfo::Find(data["ci"].astr());
|
||||
Anope::string sci, snc;
|
||||
|
||||
data["ci"] >> sci;
|
||||
data["nc"] >> snc;
|
||||
|
||||
ChannelInfo *ci = ChannelInfo::Find(sci);
|
||||
if (!ci)
|
||||
return NULL;
|
||||
|
||||
AutoKick *ak;
|
||||
NickCore *nc = NickCore::Find(data["nc"].astr());
|
||||
NickCore *nc = NickCore::Find(snc);
|
||||
if (obj)
|
||||
{
|
||||
ak = anope_dynamic_static_cast<AutoKick *>(obj);
|
||||
data["creator"] >> ak->creator;
|
||||
data["reason"] >> ak->reason;
|
||||
ak->nc = NickCore::Find(data["nc"].astr());
|
||||
ak->nc = NickCore::Find(snc);
|
||||
data["mask"] >> ak->mask;
|
||||
data["addtime"] >> ak->addtime;
|
||||
data["last_used"] >> ak->last_used;
|
||||
@@ -113,12 +115,22 @@ Serializable* AutoKick::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
data["addtime"] >> addtime;
|
||||
data["last_used"] >> lastused;
|
||||
|
||||
Anope::string screator, sreason, smask;
|
||||
|
||||
data["creator"] >> screator;
|
||||
data["reason"] >> sreason;
|
||||
data["mask"] >> smask;
|
||||
|
||||
if (nc)
|
||||
ak = ci->AddAkick(data["creator"].astr(), nc, data["reason"].astr(), addtime, lastused);
|
||||
ak = ci->AddAkick(screator, nc, sreason, addtime, lastused);
|
||||
else
|
||||
ak = ci->AddAkick(data["creator"].astr(), data["mask"].astr(), data["reason"].astr(), addtime, lastused);
|
||||
ak = ci->AddAkick(screator, smask, sreason, addtime, lastused);
|
||||
}
|
||||
|
||||
Anope::string sflags;
|
||||
data["flags"] >> sflags;
|
||||
ak->FromString(sflags);
|
||||
|
||||
return ak;
|
||||
}
|
||||
|
||||
@@ -126,27 +138,28 @@ ModeLock::ModeLock(ChannelInfo *ch, bool s, ChannelModeName n, const Anope::stri
|
||||
{
|
||||
}
|
||||
|
||||
Serialize::Data ModeLock::Serialize() const
|
||||
void ModeLock::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
if (!this->ci)
|
||||
return data;
|
||||
return;
|
||||
|
||||
const Anope::string* ChannelModeNameStrings = Flags<ChannelModeName>::GetFlagStrings();
|
||||
data["ci"].SetMax(64)/*XXX*/ << this->ci->name;
|
||||
data["set"].SetMax(5) << this->set;
|
||||
data["name"].SetMax(64) << ChannelModeNameStrings[this->name];
|
||||
data["param"].SetMax(512) << this->param;
|
||||
data["ci"] << this->ci->name;
|
||||
data["set"] << this->set;
|
||||
data["name"] << ChannelModeNameStrings[this->name];
|
||||
data["param"] << this->param;
|
||||
data["setter"] << this->setter;
|
||||
data["created"].SetType(Serialize::DT_INT) << this->created;
|
||||
|
||||
return data;
|
||||
data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
|
||||
}
|
||||
|
||||
Serializable* ModeLock::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
ChannelInfo *ci = ChannelInfo::Find(data["ci"].astr());
|
||||
Anope::string sci, sname;
|
||||
|
||||
data["ci"] >> sci;
|
||||
data["name"] >> sname;
|
||||
|
||||
ChannelInfo *ci = ChannelInfo::Find(sci);
|
||||
if (!ci)
|
||||
return NULL;
|
||||
|
||||
@@ -154,7 +167,7 @@ Serializable* ModeLock::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
|
||||
const Anope::string* ChannelModeNameStrings = Flags<ChannelModeName>::GetFlagStrings();
|
||||
for (unsigned i = 0; !ChannelModeNameStrings[i].empty(); ++i)
|
||||
if (ChannelModeNameStrings[i] == data["name"].astr())
|
||||
if (ChannelModeNameStrings[i] == sname)
|
||||
{
|
||||
name = static_cast<ChannelModeName>(i);
|
||||
break;
|
||||
@@ -182,7 +195,10 @@ Serializable* ModeLock::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
time_t created;
|
||||
data["created"] >> created;
|
||||
|
||||
ml = new ModeLock(ci, set, name, "", data["setter"].astr(), created);
|
||||
Anope::string setter;
|
||||
data["setter"] >> setter;
|
||||
|
||||
ml = new ModeLock(ci, set, name, "", setter, created);
|
||||
data["param"] >> ml->param;
|
||||
|
||||
ci->mode_locks->insert(std::make_pair(ml->name, ml));
|
||||
@@ -190,12 +206,10 @@ Serializable* ModeLock::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
}
|
||||
}
|
||||
|
||||
Serialize::Data LogSetting::Serialize() const
|
||||
void LogSetting::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
if (!ci)
|
||||
return data;
|
||||
return;
|
||||
|
||||
data["ci"] << ci->name;
|
||||
data["service_name"] << service_name;
|
||||
@@ -204,14 +218,16 @@ Serialize::Data LogSetting::Serialize() const
|
||||
data["method"] << method;
|
||||
data["extra"] << extra;
|
||||
data["creator"] << creator;
|
||||
data["created"].SetType(Serialize::DT_INT) << created;
|
||||
|
||||
return data;
|
||||
data.SetType("created", Serialize::Data::DT_INT); data["created"] << created;
|
||||
}
|
||||
|
||||
Serializable* LogSetting::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
ChannelInfo *ci = ChannelInfo::Find(data["ci"].astr());
|
||||
Anope::string sci;
|
||||
|
||||
data["ci"] >> sci;
|
||||
|
||||
ChannelInfo *ci = ChannelInfo::Find(sci);
|
||||
if (ci == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -376,22 +392,20 @@ ChannelInfo::~ChannelInfo()
|
||||
--this->founder->channelcount;
|
||||
}
|
||||
|
||||
Serialize::Data ChannelInfo::Serialize() const
|
||||
void ChannelInfo::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["name"].SetMax(255) << this->name;
|
||||
data["name"] << this->name;
|
||||
if (this->founder)
|
||||
data["founder"] << this->founder->display;
|
||||
if (this->successor)
|
||||
data["successor"] << this->successor->display;
|
||||
data["description"] << this->desc;
|
||||
data["time_registered"].SetType(Serialize::DT_INT) << this->time_registered;
|
||||
data["last_used"].SetType(Serialize::DT_INT) << this->last_used;
|
||||
data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered;
|
||||
data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used;
|
||||
data["last_topic"] << this->last_topic;
|
||||
data["last_topic_setter"] << this->last_topic_setter;
|
||||
data["last_topic_time"].SetType(Serialize::DT_INT) << this->last_topic_time;
|
||||
data["bantype"].SetType(Serialize::DT_INT) << this->bantype;
|
||||
data.SetType("last_topic_time", Serialize::Data::DT_INT); data["last_topic_time"] << this->last_topic_time;
|
||||
data.SetType("bantype", Serialize::Data::DT_INT); data["bantype"] << this->bantype;
|
||||
data["flags"] << this->ToString();
|
||||
data["botflags"] << this->botflags.ToString();
|
||||
{
|
||||
@@ -404,40 +418,44 @@ Serialize::Data ChannelInfo::Serialize() const
|
||||
data["bi"] << this->bi->nick;
|
||||
for (int i = 0; i < TTB_SIZE; ++i)
|
||||
data["ttb"] << this->ttb[i] << " ";
|
||||
data["capsmin"].SetType(Serialize::DT_INT) << this->capsmin;
|
||||
data["capspercent"].SetType(Serialize::DT_INT) << this->capspercent;
|
||||
data["floodlines"].SetType(Serialize::DT_INT) << this->floodlines;
|
||||
data["floodsecs"].SetType(Serialize::DT_INT) << this->floodsecs;
|
||||
data["repeattimes"].SetType(Serialize::DT_INT) << this->repeattimes;
|
||||
data.SetType("capsmin", Serialize::Data::DT_INT); data["capsmin"] << this->capsmin;
|
||||
data.SetType("capspercent", Serialize::Data::DT_INT); data["capspercent"] << this->capspercent;
|
||||
data.SetType("floodlines", Serialize::Data::DT_INT); data["floodlines"] << this->floodlines;
|
||||
data.SetType("floodsecs", Serialize::Data::DT_INT); data["floodsecs"] << this->floodsecs;
|
||||
data.SetType("repeattimes", Serialize::Data::DT_INT); data["repeattimes"] << this->repeattimes;
|
||||
data["memomax"] << this->memos.memomax;
|
||||
for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
|
||||
data["memoignores"] << this->memos.ignores[i] << " ";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
Anope::string sname, sfounder, ssuccessor, sflags, sbotflags, slevels, sbi;
|
||||
|
||||
data["name"] >> sname;
|
||||
data["founder"] >> sfounder;
|
||||
data["successor"] >> ssuccessor;
|
||||
data["flags"] >> sflags;
|
||||
data["botflags"] >> sbotflags;
|
||||
data["levels"] >> slevels;
|
||||
data["bi"] >> sbi;
|
||||
|
||||
ChannelInfo *ci;
|
||||
if (obj)
|
||||
ci = anope_dynamic_static_cast<ChannelInfo *>(obj);
|
||||
else
|
||||
ci = new ChannelInfo(data["name"].astr());
|
||||
ci = new ChannelInfo(sname);
|
||||
|
||||
if (data.count("founder") > 0)
|
||||
{
|
||||
if (ci->founder)
|
||||
--ci->founder->channelcount;
|
||||
ci->founder = NickCore::Find(data["founder"].astr());
|
||||
if (ci->founder)
|
||||
++ci->founder->channelcount;
|
||||
}
|
||||
if (data.count("successor") > 0)
|
||||
{
|
||||
ci->successor = NickCore::Find(data["successor"].astr());
|
||||
if (ci->founder && *ci->founder == *ci->successor)
|
||||
ci->successor = NULL;
|
||||
}
|
||||
if (ci->founder)
|
||||
--ci->founder->channelcount;
|
||||
ci->founder = NickCore::Find(sfounder);
|
||||
if (ci->founder)
|
||||
++ci->founder->channelcount;
|
||||
|
||||
ci->successor = NickCore::Find(ssuccessor);
|
||||
if (ci->founder && *ci->founder == *ci->successor)
|
||||
ci->successor = NULL;
|
||||
|
||||
data["description"] >> ci->desc;
|
||||
data["time_registered"] >> ci->time_registered;
|
||||
data["last_used"] >> ci->last_used;
|
||||
@@ -445,15 +463,15 @@ Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
data["last_topic_setter"] >> ci->last_topic_setter;
|
||||
data["last_topic_time"] >> ci->last_topic_time;
|
||||
data["bantype"] >> ci->bantype;
|
||||
ci->FromString(data["flags"].astr());
|
||||
ci->botflags.FromString(data["botflags"].astr());
|
||||
ci->FromString(sflags);
|
||||
ci->botflags.FromString(sbotflags);
|
||||
{
|
||||
std::vector<Anope::string> v;
|
||||
spacesepstream(data["levels"].astr()).GetTokens(v);
|
||||
spacesepstream(slevels).GetTokens(v);
|
||||
for (unsigned i = 0; i + 1 < v.size(); i += 2)
|
||||
ci->levels[v[i]] = convertTo<int16_t>(v[i + 1]);
|
||||
}
|
||||
BotInfo *bi = BotInfo::Find(data["bi"].astr());
|
||||
BotInfo *bi = BotInfo::Find(sbi);
|
||||
if (*ci->bi != bi)
|
||||
{
|
||||
if (ci->bi)
|
||||
|
||||
+11
-24
@@ -35,7 +35,7 @@ void Serialize::RegisterTypes()
|
||||
memo("Memo", Memo::Unserialize), xline("XLine", XLine::Unserialize);
|
||||
}
|
||||
|
||||
stringstream::stringstream() : std::stringstream(), type(Serialize::DT_TEXT), _max(0)
|
||||
/*stringstream::stringstream() : std::stringstream(), type(Serialize::DT_TEXT), _max(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -84,14 +84,14 @@ stringstream &stringstream::SetMax(unsigned m)
|
||||
unsigned stringstream::GetMax() const
|
||||
{
|
||||
return this->_max;
|
||||
}
|
||||
}*/
|
||||
|
||||
Serializable::Serializable() : last_commit_time(0), id(0)
|
||||
Serializable::Serializable() : last_commit(NULL), last_commit_time(0), id(0)
|
||||
{
|
||||
throw CoreException("Default Serializable constructor?");
|
||||
}
|
||||
|
||||
Serializable::Serializable(const Anope::string &serialize_type) : last_commit_time(0), id(0)
|
||||
Serializable::Serializable(const Anope::string &serialize_type) : last_commit(NULL), last_commit_time(0), id(0)
|
||||
{
|
||||
if (SerializableItems == NULL)
|
||||
SerializableItems = new std::list<Serializable *>();
|
||||
@@ -105,7 +105,7 @@ Serializable::Serializable(const Anope::string &serialize_type) : last_commit_ti
|
||||
FOREACH_MOD(I_OnSerializableConstruct, OnSerializableConstruct(this));
|
||||
}
|
||||
|
||||
Serializable::Serializable(const Serializable &other) : last_commit_time(0), id(0)
|
||||
Serializable::Serializable(const Serializable &other) : last_commit(NULL), last_commit_time(0), id(0)
|
||||
{
|
||||
SerializableItems->push_back(this);
|
||||
this->s_iter = SerializableItems->end();
|
||||
@@ -119,6 +119,7 @@ Serializable::Serializable(const Serializable &other) : last_commit_time(0), id(
|
||||
Serializable::~Serializable()
|
||||
{
|
||||
SerializableItems->erase(this->s_iter);
|
||||
delete last_commit;
|
||||
}
|
||||
|
||||
Serializable &Serializable::operator=(const Serializable &)
|
||||
@@ -144,14 +145,15 @@ void Serializable::QueueUpdate()
|
||||
FOREACH_MOD(I_OnSerializableUpdate, OnSerializableUpdate(this));
|
||||
}
|
||||
|
||||
bool Serializable::IsCached()
|
||||
bool Serializable::IsCached(Serialize::Data *data)
|
||||
{
|
||||
return this->last_commit == this->Serialize();
|
||||
return this->last_commit && this->last_commit->IsEqual(data);
|
||||
}
|
||||
|
||||
void Serializable::UpdateCache()
|
||||
void Serializable::UpdateCache(Serialize::Data *data)
|
||||
{
|
||||
this->last_commit = this->Serialize();
|
||||
delete this->last_commit;
|
||||
this->last_commit = data;
|
||||
}
|
||||
|
||||
bool Serializable::IsTSCached()
|
||||
@@ -164,11 +166,6 @@ void Serializable::UpdateTS()
|
||||
this->last_commit_time = Anope::CurTime;
|
||||
}
|
||||
|
||||
Type* Serializable::GetSerializableType() const
|
||||
{
|
||||
return this->s_type;
|
||||
}
|
||||
|
||||
const std::list<Serializable *> &Serializable::GetItems()
|
||||
{
|
||||
return *SerializableItems;
|
||||
@@ -188,11 +185,6 @@ Type::~Type()
|
||||
Types.erase(this->name);
|
||||
}
|
||||
|
||||
const Anope::string &Type::GetName()
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
Serializable *Type::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
return this->unserialize(obj, data);
|
||||
@@ -213,11 +205,6 @@ void Type::UpdateTimestamp()
|
||||
this->timestamp = Anope::CurTime;
|
||||
}
|
||||
|
||||
Module* Type::GetOwner() const
|
||||
{
|
||||
return this->owner;
|
||||
}
|
||||
|
||||
Type *Serialize::Type::Find(const Anope::string &name)
|
||||
{
|
||||
std::map<Anope::string, Type *>::iterator it = Types.find(name);
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2003-2012 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "sockets.h"
|
||||
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
Pipe::Pipe() : Socket(eventfd(0, EFD_NONBLOCK))
|
||||
{
|
||||
if (this->sock < 0)
|
||||
throw CoreException("Could not create pipe: " + Anope::LastError());
|
||||
}
|
||||
|
||||
Pipe::~Pipe()
|
||||
{
|
||||
}
|
||||
|
||||
bool Pipe::ProcessRead()
|
||||
{
|
||||
eventfd_t dummy;
|
||||
eventfd_read(this->GetFD(), &dummy);
|
||||
this->OnNotify();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Pipe::Notify()
|
||||
{
|
||||
eventfd_write(this->GetFD(), 1);
|
||||
}
|
||||
|
||||
+7
-10
@@ -419,7 +419,7 @@ Socket::Socket(int s, bool i, int type)
|
||||
this->sock = socket(this->ipv6 ? AF_INET6 : AF_INET, type, 0);
|
||||
else
|
||||
this->sock = s;
|
||||
this->SetNonBlocking();
|
||||
this->SetBlocking(false);
|
||||
SocketEngine::Sockets[this->sock] = this;
|
||||
SocketEngine::Change(this, true, SF_READABLE);
|
||||
}
|
||||
@@ -443,16 +443,13 @@ bool Socket::IsIPv6() const
|
||||
return ipv6;
|
||||
}
|
||||
|
||||
bool Socket::SetBlocking()
|
||||
bool Socket::SetBlocking(bool state)
|
||||
{
|
||||
int flags = fcntl(this->GetFD(), F_GETFL, 0);
|
||||
return !fcntl(this->GetFD(), F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
bool Socket::SetNonBlocking()
|
||||
{
|
||||
int flags = fcntl(this->GetFD(), F_GETFL, 0);
|
||||
return !fcntl(this->GetFD(), F_SETFL, flags | O_NONBLOCK);
|
||||
if (state)
|
||||
return !fcntl(this->GetFD(), F_SETFL, flags & ~O_NONBLOCK);
|
||||
else
|
||||
return !fcntl(this->GetFD(), F_SETFL, flags | O_NONBLOCK);
|
||||
}
|
||||
|
||||
void Socket::Bind(const Anope::string &ip, int port)
|
||||
@@ -481,7 +478,7 @@ void Socket::ProcessError()
|
||||
|
||||
ListenSocket::ListenSocket(const Anope::string &bindip, int port, bool i)
|
||||
{
|
||||
this->SetNonBlocking();
|
||||
this->SetBlocking(false);
|
||||
|
||||
const char op = 1;
|
||||
setsockopt(this->GetFD(), SOL_SOCKET, SO_REUSEADDR, &op, sizeof(op));
|
||||
|
||||
+14
-7
@@ -137,10 +137,8 @@ bool XLine::IsRegex() const
|
||||
return !this->mask.empty() && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/';
|
||||
}
|
||||
|
||||
Serialize::Data XLine::Serialize() const
|
||||
void XLine::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
Serialize::Data data;
|
||||
|
||||
data["mask"] << this->mask;
|
||||
data["by"] << this->by;
|
||||
data["created"] << this->created;
|
||||
@@ -149,13 +147,15 @@ Serialize::Data XLine::Serialize() const
|
||||
data["uid"] << this->id;
|
||||
if (this->manager)
|
||||
data["manager"] << this->manager->name;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Serializable* XLine::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
ServiceReference<XLineManager> xlm("XLineManager", data["manager"].astr());
|
||||
Anope::string smanager;
|
||||
|
||||
data["manager"] >> smanager;
|
||||
|
||||
ServiceReference<XLineManager> xlm("XLineManager", smanager);
|
||||
if (!xlm)
|
||||
return NULL;
|
||||
|
||||
@@ -176,9 +176,16 @@ Serializable* XLine::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
}
|
||||
else
|
||||
{
|
||||
Anope::string smask, sby, sreason, suid;
|
||||
time_t expires;
|
||||
|
||||
data["mask"] >> smask;
|
||||
data["by"] >> sby;
|
||||
data["reason"] >> sreason;
|
||||
data["uid"] >> suid;
|
||||
data["expires"] >> expires;
|
||||
xl = new XLine(data["mask"].astr(), data["by"].astr(), expires, data["reason"].astr(), data["uid"].astr());
|
||||
|
||||
xl = new XLine(smask, sby, expires, sreason, suid);
|
||||
xlm->AddXLine(xl);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user