summaryrefslogtreecommitdiff
path: root/modules/database/db_sql.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/database/db_sql.cpp')
-rw-r--r--modules/database/db_sql.cpp107
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)