diff options
author | Adam <Adam@anope.org> | 2012-04-27 15:38:50 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2012-04-27 15:38:50 -0400 |
commit | 5068483cb917ba1c8ed3a0d20f7bfcb996f0aa3e (patch) | |
tree | cf2bf4096b72f68b595a3bbe9d0e75d34ad2641d /modules/database/db_sql.cpp | |
parent | 83ee20fc2910e9ea0cac250e767d20f17576d98a (diff) |
Add db_sql:prefix allow prefixing all anope tables similarly, and changed db_sql to update the databases incrementally instead of one big flush
Diffstat (limited to 'modules/database/db_sql.cpp')
-rw-r--r-- | modules/database/db_sql.cpp | 144 |
1 files changed, 93 insertions, 51 deletions
diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp index c2ba84a5f..b7d32c17c 100644 --- a/modules/database/db_sql.cpp +++ b/modules/database/db_sql.cpp @@ -30,38 +30,66 @@ class SQLSQLInterface : public SQLInterface } }; -class DBSQL : public Module +class ResultSQLSQLInterface : public SQLSQLInterface { - service_reference<SQLProvider> sql; - SQLSQLInterface sqlinterface; + dynamic_reference<Serializable> obj; - void RunBackground(const SQLQuery &q) +public: + ResultSQLSQLInterface(Module *o, Serializable *ob) : SQLSQLInterface(o), obj(ob) { } + + void OnResult(const SQLResult &r) anope_override { - if (!quitting) - this->sql->Run(&sqlinterface, q); - else - this->sql->RunQuery(q); + SQLSQLInterface::OnResult(r); + if (r.GetID() > 0 && this->obj) + this->obj->id = r.GetID(); + delete this; } - void DropTable(const Anope::string &table) + void OnError(const SQLResult &r) anope_override { - SQLQuery query("DROP TABLE `" + table + "`"); - this->RunBackground(query); + SQLSQLInterface::OnError(r); + delete this; } +}; - void DropAll() +class DBSQL : public Module, public Pipe +{ + service_reference<SQLProvider> sql; + SQLSQLInterface sqlinterface; + Anope::string prefix; + std::set<dynamic_reference<Serializable> > updated_items; + bool quitting; + + void RunBackground(const SQLQuery &q, SQLInterface *iface = NULL) { - SQLResult r = this->sql->RunQuery(this->sql->GetTables()); - for (int i = 0; i < r.Rows(); ++i) + if (!this->sql) { - const std::map<Anope::string, Anope::string> &map = r.Row(i); - for (std::map<Anope::string, Anope::string>::const_iterator it = map.begin(); it != map.end(); ++it) - this->DropTable(it->second); + static time_t last_warn = 0; + if (last_warn + 300 < Anope::CurTime) + { + last_warn = Anope::CurTime; + Log() << "db_sql: Unable to execute query, is SQL configured correctly?"; + } } + else if (!this->quitting) + { + if (iface == NULL) + iface = &this->sqlinterface; + this->sql->Run(iface, q); + } + else + this->sql->RunQuery(q); } - void Insert(const Anope::string &table, const Serialize::Data &data) + SQLQuery BuildInsert(const Anope::string &table, const Serialize::Data &data) { + if (this->sql) + { + std::vector<SQLQuery> create_queries = this->sql->CreateTable(table, data); + for (unsigned i = 0; i < create_queries.size(); ++i) + this->RunBackground(create_queries[i]); + } + Anope::string query_text = "INSERT INTO `" + table + "` ("; for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it) query_text += "`" + it->first + "`,"; @@ -76,57 +104,52 @@ class DBSQL : public Module for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it) query.setValue(it->first, it->second.astr()); - this->RunBackground(query); + return query; } public: - DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sql("", ""), sqlinterface(this) + DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sql("", ""), sqlinterface(this), quitting(false) { this->SetAuthor("Anope"); - Implementation i[] = { I_OnReload, I_OnSaveDatabase, I_OnLoadDatabase }; + Implementation i[] = { I_OnReload, I_OnLoadDatabase, I_OnSerializableConstruct, I_OnSerializableDestruct, I_OnSerializableUpdate }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); this->OnReload(); } - - void OnReload() anope_override + + ~DBSQL() { - ConfigReader config; - Anope::string engine = config.ReadValue("db_sql", "engine", "", 0); - this->sql = service_reference<SQLProvider>("SQLProvider", engine); + this->quitting = true; + this->OnNotify(); } - EventReturn OnSaveDatabase() anope_override + void OnNotify() anope_override { - if (!this->sql) + for (std::set<dynamic_reference<Serializable> >::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it) { - Log() << "db_sql: Unable to save databases, is SQL configured correctly?"; - return EVENT_CONTINUE; - } - - const std::list<Serializable *> &items = Serializable::GetItems(); - if (items.empty()) - return EVENT_CONTINUE; - - this->DropAll(); - - for (std::list<Serializable *>::const_iterator it = items.begin(), it_end = items.end(); it != it_end; ++it) - { - Serializable *base = *it; - Serialize::Data data = base->serialize(); - - if (data.empty()) - continue; + dynamic_reference<Serializable> obj = *it; - std::vector<SQLQuery> create_queries = this->sql->CreateTable(base->serialize_name(), data); - for (unsigned i = 0; i < create_queries.size(); ++i) - this->RunBackground(create_queries[i]); + if (obj) + { + if (obj->IsCached()) + continue; + obj->UpdateCache(); - this->Insert(base->serialize_name(), data); + SQLQuery insert = this->BuildInsert(this->prefix + obj->serialize_name(), obj->serialize()); + this->RunBackground(insert, new ResultSQLSQLInterface(this, obj)); + } } - return EVENT_CONTINUE; + this->updated_items.clear(); + } + + void OnReload() anope_override + { + ConfigReader config; + Anope::string engine = config.ReadValue("db_sql", "engine", "", 0); + this->sql = service_reference<SQLProvider>("SQLProvider", engine); + this->prefix = config.ReadValue("db_sql", "prefix", "anope_db_", 0); } EventReturn OnLoadDatabase() anope_override @@ -142,11 +165,13 @@ class DBSQL : public Module { SerializeType *sb = SerializeType::Find(type_order[i]); - SQLQuery query("SELECT * FROM `" + sb->GetName() + "`"); + SQLQuery query("SELECT * FROM `" + this->prefix + sb->GetName() + "`"); SQLResult res = this->sql->RunQuery(query); + for (int j = 0; j < res.Rows(); ++j) { Serialize::Data 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; @@ -157,6 +182,23 @@ class DBSQL : public Module return EVENT_STOP; } + + void OnSerializableConstruct(Serializable *obj) anope_override + { + this->updated_items.insert(obj); + this->Notify(); + } + + void OnSerializableDestruct(Serializable *obj) anope_override + { + this->RunBackground("DELETE FROM `" + this->prefix + obj->serialize_name() + "` WHERE `id` = " + stringify(obj->id)); + } + + void OnSerializableUpdate(Serializable *obj) anope_override + { + this->updated_items.insert(obj); + this->Notify(); + } }; MODULE_INIT(DBSQL) |