diff options
-rw-r--r-- | include/modules.h | 3 | ||||
-rw-r--r-- | include/serialize.h | 35 | ||||
-rw-r--r-- | modules/commands/os_dns.cpp | 83 | ||||
-rw-r--r-- | modules/database/db_flatfile.cpp | 40 | ||||
-rw-r--r-- | modules/database/db_sql.cpp | 69 | ||||
-rw-r--r-- | src/serialize.cpp | 53 |
6 files changed, 146 insertions, 137 deletions
diff --git a/include/modules.h b/include/modules.h index 09df6617e..eba0138b8 100644 --- a/include/modules.h +++ b/include/modules.h @@ -935,6 +935,7 @@ class CoreExport Module : public Extensible virtual void OnSerializableConstruct(Serializable *) { } virtual void OnSerializableDestruct(Serializable *) { } virtual void OnSerializableUpdate(Serializable *) { } + virtual void OnSerializeTypeCreate(Serialize::Type *) { } /** Called when a chanserv/set command is used * @param source The source of the command @@ -1013,7 +1014,7 @@ enum Implementation I_OnMLock, I_OnUnMLock, I_OnServerSync, I_OnUplinkSync, I_OnBotPrivmsg, I_OnPrivmsg, I_OnLog, I_OnDnsRequest, I_OnMessage, - I_OnSerializeCheck, I_OnSerializableConstruct, I_OnSerializableDestruct, I_OnSerializableUpdate, + I_OnSerializeCheck, I_OnSerializableConstruct, I_OnSerializableDestruct, I_OnSerializableUpdate, I_OnSerializeTypeCreate, I_END }; diff --git a/include/serialize.h b/include/serialize.h index 1a16e5b35..edbf1facf 100644 --- a/include/serialize.h +++ b/include/serialize.h @@ -188,52 +188,49 @@ class Serialize::Checker { Anope::string name; T obj; + mutable Serialize::Type *type; + + inline void Check() const + { + if (!type) + type = Serialize::Type::Find(this->name); + if (type) + type->Check(); + } public: - Checker(const Anope::string &n) : name(n) { } + Checker(const Anope::string &n) : name(n), type(NULL) { } inline const T* operator->() const { - static Serialize::Type *type = Serialize::Type::Find(this->name); - if (type) - type->Check(); + this->Check(); return &this->obj; } inline T* operator->() { - static Serialize::Type *type = Serialize::Type::Find(this->name); - if (type) - type->Check(); + this->Check(); return &this->obj; } inline const T& operator*() const { - static Serialize::Type *type = Serialize::Type::Find(this->name); - if (type) - type->Check(); + this->Check(); return this->obj; } inline T& operator*() { - static Serialize::Type *type = Serialize::Type::Find(this->name); - if (type) - type->Check(); + this->Check(); return this->obj; } inline operator const T&() const { - static Serialize::Type *type = Serialize::Type::Find(this->name); - if (type) - type->Check(); + this->Check(); return this->obj; } inline operator T&() { - static Serialize::Type *type = Serialize::Type::Find(this->name); - if (type) - type->Check(); + this->Check(); return this->obj; } }; diff --git a/modules/commands/os_dns.cpp b/modules/commands/os_dns.cpp index d825851f3..ab8e412be 100644 --- a/modules/commands/os_dns.cpp +++ b/modules/commands/os_dns.cpp @@ -13,8 +13,8 @@ static ServiceReference<DNS::Manager> dnsmanager("DNS::Manager", "dns/manager"); class DNSZone; class DNSServer; -static std::vector<DNSZone *> zones; -static std::vector<DNSServer *> dns_servers; +static Serialize::Checker<std::vector<DNSZone *> > zones("DNSZone"); +static Serialize::Checker<std::vector<DNSServer *> > dns_servers("DNSServer"); static std::map<Anope::string, std::list<time_t> > server_quit_times; @@ -25,14 +25,14 @@ struct DNSZone : Serializable DNSZone(const Anope::string &n) : Serializable("DNSZone"), name(n) { - zones.push_back(this); + zones->push_back(this); } ~DNSZone() { - std::vector<DNSZone *>::iterator it = std::find(zones.begin(), zones.end(), this); - if (it != zones.end()) - zones.erase(it); + std::vector<DNSZone *>::iterator it = std::find(zones->begin(), zones->end(), this); + if (it != zones->end()) + zones->erase(it); } void Serialize(Serialize::Data &data) const anope_override @@ -73,9 +73,13 @@ struct DNSZone : Serializable static DNSZone *Find(const Anope::string &name) { - for (unsigned i = 0; i < zones.size(); ++i) - if (zones[i]->name.equals_ci(name)) - return zones[i]; + for (unsigned i = 0; i < zones->size(); ++i) + if (zones->at(i)->name.equals_ci(name)) + { + DNSZone *z = zones->at(i); + z->QueueUpdate(); + return z; + } return NULL; } }; @@ -96,14 +100,14 @@ class DNSServer : public Serializable DNSServer(const Anope::string &sn) : Serializable("DNSServer"), server_name(sn), limit(0), pooled(false), active(false), repool(0) { - dns_servers.push_back(this); + dns_servers->push_back(this); } ~DNSServer() { - std::vector<DNSServer *>::iterator it = std::find(dns_servers.begin(), dns_servers.end(), this); - if (it != dns_servers.end()) - dns_servers.erase(it); + std::vector<DNSServer *>::iterator it = std::find(dns_servers->begin(), dns_servers->end(), this); + if (it != dns_servers->end()) + dns_servers->erase(it); } const Anope::string &GetName() const { return server_name; } @@ -177,9 +181,13 @@ class DNSServer : public Serializable static DNSServer *Find(const Anope::string &s) { - for (unsigned i = 0; i < dns_servers.size(); ++i) - if (dns_servers[i]->GetName() == s) - return dns_servers[i]; + for (unsigned i = 0; i < dns_servers->size(); ++i) + if (dns_servers->at(i)->GetName() == s) + { + DNSServer *serv = dns_servers->at(i); + serv->QueueUpdate(); + return serv; + } return NULL; } }; @@ -188,7 +196,7 @@ class CommandOSDNS : public Command { void DisplayPoolState(CommandSource &source) { - if (dns_servers.empty()) + if (dns_servers->empty()) { source.Reply(_("There are no configured servers.")); return; @@ -196,9 +204,9 @@ class CommandOSDNS : public Command ListFormatter lf; lf.AddColumn("Server").AddColumn("IP").AddColumn("Limit").AddColumn("State"); - for (unsigned i = 0; i < dns_servers.size(); ++i) + for (unsigned i = 0; i < dns_servers->size(); ++i) { - DNSServer *s = dns_servers[i]; + DNSServer *s = dns_servers->at(i); Server *srv = Server::Find(s->GetName()); ListFormatter::ListEntry entry; @@ -228,14 +236,14 @@ class CommandOSDNS : public Command std::vector<Anope::string> replies; lf.Process(replies); - if (!zones.empty()) + if (!zones->empty()) { ListFormatter lf2; lf2.AddColumn("Zone").AddColumn("Servers"); - for (unsigned i = 0; i < zones.size(); ++i) + for (unsigned i = 0; i < zones->size(); ++i) { - DNSZone *z = zones[i]; + const DNSZone *z = zones->at(i); ListFormatter::ListEntry entry; entry["Zone"] = z->name; @@ -297,7 +305,7 @@ class CommandOSDNS : public Command } source.Reply(_("Zone %s removed."), z->name.c_str()); - delete z; + z->Destroy(); } void AddServer(CommandSource &source, const std::vector<Anope::string> ¶ms) @@ -355,7 +363,7 @@ class CommandOSDNS : public Command if (!z) { source.Reply(_("Zone %s does not exist."), zone.c_str()); - delete s; + s->Destroy(); return; } @@ -411,7 +419,7 @@ class CommandOSDNS : public Command Log(LOG_ADMIN, source, this) << "to delete server " << s->GetName(); source.Reply(_("Removed server %s."), s->GetName().c_str()); - delete s; + s->Destroy(); } void AddIP(CommandSource &source, const std::vector<Anope::string> ¶ms) @@ -630,7 +638,7 @@ class CommandOSDNS : public Command " \n" "The \2ADDIP\2 command associates an IP with a server.\n" " \n" - "The \2POOL\2 and \2DEPOOL\2 commands actually add and remove servers to their given zones.\b")); + "The \2POOL\2 and \2DEPOOL\2 commands actually add and remove servers to their given zones.")); return true; } }; @@ -657,14 +665,21 @@ class ModuleDNS : public Module ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); this->OnReload(); + + for (unsigned j = 0; j < dns_servers->size(); ++j) + { + DNSServer *s = dns_servers->at(j); + if (s->Pooled() && Server::Find(s->GetName())) + s->SetActive(true); + } } ~ModuleDNS() { - for (unsigned i = 0; i < zones.size(); ++i) - delete zones[i]; - for (unsigned i = 0; i < dns_servers.size(); ++i) - delete dns_servers[i]; + for (unsigned i = zones->size(); i > 0; --i) + delete zones->at(i - 1); + for (unsigned i = dns_servers->size(); i > 0; --i) + delete dns_servers->at(i - 1); } void OnReload() anope_override @@ -800,9 +815,9 @@ class ModuleDNS : public Module if (packet->answers.size() == answer_size) { /* Default zone */ - for (unsigned i = 0; i < dns_servers.size(); ++i) + for (unsigned i = 0; i < dns_servers->size(); ++i) { - DNSServer *s = dns_servers[i]; + DNSServer *s = dns_servers->at(i); if (!s->Active()) continue; @@ -831,9 +846,9 @@ class ModuleDNS : public Module } /* Something messed up, just return them all and hope one is available */ - for (unsigned i = 0; i < dns_servers.size(); ++i) + for (unsigned i = 0; i < dns_servers->size(); ++i) { - DNSServer *s = dns_servers[i]; + DNSServer *s = dns_servers->at(i); for (unsigned j = 0; j < s->GetIPs().size(); ++j) { diff --git a/modules/database/db_flatfile.cpp b/modules/database/db_flatfile.cpp index 66715b9f8..3aaadd7c0 100644 --- a/modules/database/db_flatfile.cpp +++ b/modules/database/db_flatfile.cpp @@ -73,6 +73,7 @@ class DBFlatFile : public Module, public Pipe /* Backup file names */ std::map<Anope::string, std::list<Anope::string> > backups; bool use_fork; + bool loaded; void BackupDatabase() { @@ -128,11 +129,11 @@ class DBFlatFile : public Module, public Pipe } public: - DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), last_day(0), use_fork(false) + DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), last_day(0), use_fork(false), loaded(false) { this->SetAuthor("Anope"); - Implementation i[] = { I_OnReload, I_OnLoadDatabase, I_OnSaveDatabase }; + Implementation i[] = { I_OnReload, I_OnLoadDatabase, I_OnSaveDatabase, I_OnSerializeTypeCreate }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); OnReload(); @@ -208,6 +209,7 @@ class DBFlatFile : public Module, public Pipe fd.close(); + loaded = true; return EVENT_STOP; } @@ -306,6 +308,40 @@ class DBFlatFile : public Module, public Pipe return EVENT_CONTINUE; } + + /* Load just one type. Done if a module is reloaded during runtime */ + void OnSerializeTypeCreate(Serialize::Type *stype) anope_override + { + if (!loaded) + return; + + Anope::string db_name; + if (stype->GetOwner()) + db_name = Anope::DataDir + "/module_" + stype->GetOwner()->name + ".db"; + else + db_name = Anope::DataDir + "/" + database_file; + + std::fstream fd(db_name.c_str(), std::ios_base::in); + if (!fd.is_open()) + { + Log(this) << "Unable to open " << db_name << " for reading!"; + return; + } + + LoadData ld; + ld.fs = &fd; + + for (Anope::string buf; std::getline(fd, buf.str());) + { + if (buf == "OBJECT " + stype->GetName()) + { + stype->Unserialize(NULL, ld); + ld.Reset(); + } + } + + fd.close(); + } }; MODULE_INIT(DBFlatFile) diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp index 56db7b8a0..457c6b304 100644 --- a/modules/database/db_sql.cpp +++ b/modules/database/db_sql.cpp @@ -62,6 +62,7 @@ class DBSQL : public Module, public Pipe std::set<Reference<Serializable> > updated_items; bool shutting_down; bool loading_databases; + bool loaded; void RunBackground(const Query &q, Interface *iface = NULL) { @@ -85,11 +86,11 @@ 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), loading_databases(false) + DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sql("", ""), sqlinterface(this), shutting_down(false), loading_databases(false), loaded(false) { this->SetAuthor("Anope"); - Implementation i[] = { I_OnReload, I_OnShutdown, I_OnRestart, I_OnLoadDatabase, I_OnSerializableConstruct, I_OnSerializableDestruct, I_OnSerializableUpdate }; + Implementation i[] = { I_OnReload, I_OnShutdown, I_OnRestart, I_OnLoadDatabase, I_OnSerializableConstruct, I_OnSerializableDestruct, I_OnSerializableUpdate, I_OnSerializeTypeCreate }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); this->OnReload(); @@ -163,37 +164,11 @@ class DBSQL : public Module, public Pipe for (unsigned i = 0; i < type_order.size(); ++i) { Serialize::Type *sb = Serialize::Type::Find(type_order[i]); - - Query query("SELECT * FROM `" + this->prefix + sb->GetName() + "`"); - Result res = this->sql->RunQuery(query); - - for (int j = 0; j < res.Rows(); ++j) - { - 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; - - Serializable *obj = sb->Unserialize(NULL, *data); - try - { - if (obj) - obj->id = convertTo<unsigned int>(res.Get(j, "id")); - } - catch (const ConvertException &) - { - 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->OnSerializeTypeCreate(sb); } this->loading_databases = false; + this->loaded = true; return EVENT_STOP; } @@ -221,6 +196,40 @@ class DBSQL : public Module, public Pipe this->updated_items.insert(obj); this->Notify(); } + + void OnSerializeTypeCreate(Serialize::Type *sb) anope_override + { + if (!this->loading_databases && !this->loaded) + return; + + Query query("SELECT * FROM `" + this->prefix + sb->GetName() + "`"); + Result res = this->sql->RunQuery(query); + + for (int j = 0; j < res.Rows(); ++j) + { + 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; + + Serializable *obj = sb->Unserialize(NULL, *data); + try + { + if (obj) + obj->id = convertTo<unsigned int>(res.Get(j, "id")); + } + catch (const ConvertException &) + { + 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; + } + } }; MODULE_INIT(DBSQL) diff --git a/src/serialize.cpp b/src/serialize.cpp index 0f3e6c7a6..0fff92fab 100644 --- a/src/serialize.cpp +++ b/src/serialize.cpp @@ -35,57 +35,6 @@ void Serialize::RegisterTypes() memo("Memo", Memo::Unserialize), xline("XLine", XLine::Unserialize); } -/*stringstream::stringstream() : std::stringstream(), type(Serialize::DT_TEXT), _max(0) -{ -} - -stringstream::stringstream(const stringstream &ss) : std::stringstream(ss.str()), type(Serialize::DT_TEXT), _max(0) -{ -} - -Anope::string stringstream::astr() const -{ - return this->str(); -} - -std::istream &stringstream::operator>>(Anope::string &val) -{ - val = this->str(); - return *this; -} - -bool stringstream::operator==(const stringstream &other) const -{ - return this->astr() == other.astr(); -} - -bool stringstream::operator!=(const stringstream &other) const -{ - return !(*this == other); -} - -stringstream &stringstream::SetType(Serialize::DataType t) -{ - this->type = t; - return *this; -} - -DataType Serialize::stringstream::GetType() const -{ - return this->type; -} - -stringstream &stringstream::SetMax(unsigned m) -{ - this->_max = m; - return *this; -} - -unsigned stringstream::GetMax() const -{ - return this->_max; -}*/ - Serializable::Serializable() : last_commit(NULL), last_commit_time(0), id(0) { throw CoreException("Default Serializable constructor?"); @@ -175,6 +124,8 @@ Type::Type(const Anope::string &n, unserialize_func f, Module *o) : name(n), un { TypeOrder.push_back(this->name); Types[this->name] = this; + + FOREACH_MOD(I_OnSerializeTypeCreate, OnSerializeTypeCreate(this)); } Type::~Type() |