diff options
Diffstat (limited to 'modules/database/db_sql.cpp')
-rw-r--r-- | modules/database/db_sql.cpp | 107 |
1 files changed, 63 insertions, 44 deletions
diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp index 56db7b8a0..3bb0efde2 100644 --- a/modules/database/db_sql.cpp +++ b/modules/database/db_sql.cpp @@ -1,5 +1,5 @@ /* - * (C) 2003-2012 Anope Team + * (C) 2003-2013 Anope Team * Contact us at team@anope.org * * Please read COPYING and README for further details. @@ -59,9 +59,10 @@ class DBSQL : public Module, public Pipe ServiceReference<Provider> sql; SQLSQLInterface sqlinterface; Anope::string prefix; - std::set<Reference<Serializable> > updated_items; + std::set<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(); @@ -97,20 +98,17 @@ class DBSQL : public Module, public Pipe void OnNotify() anope_override { - for (std::set<Reference<Serializable> >::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it) + for (std::set<Serializable *>::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it) { - Reference<Serializable> obj = *it; + Serializable *obj = *it; - if (obj && this->sql) + if (this->sql) { - Data *data = new Data(); - obj->Serialize(*data); + Data data; + obj->Serialize(data); if (obj->IsCached(data)) - { - delete data; continue; - } obj->UpdateCache(data); @@ -118,12 +116,18 @@ class DBSQL : public Module, public Pipe if (!s_type) continue; - std::vector<Query> 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]); - Query insert = this->sql->BuildInsert(this->prefix + s_type->GetName(), obj->id, *data); - this->RunBackground(insert, new ResultSQLSQLInterface(this, obj)); + Query insert = this->sql->BuildInsert(this->prefix + s_type->GetName(), obj->id, data); + if (this->loaded) + this->RunBackground(insert, new ResultSQLSQLInterface(this, obj)); + else + /* If we aren't loading these objects then we are importing them, so don't do asynchronous + * queries in case for some reason the core has to shut down, it will cut short the import + */ + this->sql->RunQuery(insert); } } @@ -163,37 +167,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; } @@ -202,6 +180,7 @@ class DBSQL : public Module, public Pipe { if (this->shutting_down || this->loading_databases) return; + obj->UpdateTS(); this->updated_items.insert(obj); this->Notify(); } @@ -209,8 +188,9 @@ class DBSQL : public Module, public Pipe void OnSerializableDestruct(Serializable *obj) anope_override { Serialize::Type *s_type = obj->GetSerializableType(); - if (s_type) + if (s_type && obj->id > 0) this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id)); + this->updated_items.erase(obj); } void OnSerializableUpdate(Serializable *obj) anope_override @@ -221,6 +201,45 @@ 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; + + 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) + { + Data data2; + /* The Unserialize operation is destructive so rebuild the data for UpdateCache */ + for (std::map<Anope::string, Anope::string>::const_iterator rit = row.begin(), rit_end = row.end(); rit != rit_end; ++rit) + if (rit->first != "id" && rit->first != "timestamp") + data2[rit->first] << rit->second; + obj->UpdateCache(data2); /* We know this is the most up to date copy */ + } + } + } }; MODULE_INIT(DBSQL) |