diff --git a/include/serialize.h b/include/serialize.h index ee79ab8e0..2b12e8165 100644 --- a/include/serialize.h +++ b/include/serialize.h @@ -74,6 +74,8 @@ private: size_t last_commit = 0; /* The last time this object was committed to the database */ time_t last_commit_time = 0; + /** Whether this object should be committed to the database. */ + bool should_commit = false; protected: Serializable(const Anope::string &serialize_type); @@ -81,6 +83,20 @@ protected: Serializable &operator=(const Serializable &); + template + bool InsertUnique(Container &container, const Key &key) + { + auto res = container.emplace(key, static_cast(this)); + if (res.second) + return true; + + res.first->second->should_commit = false; + res.first->second = static_cast(this); + return false; + } + public: using Id = uint64_t; virtual ~Serializable(); @@ -92,6 +108,9 @@ public: */ void QueueUpdate(); + /** Determines whether the object should be committed to the database. */ + bool ShouldCommit() const { return this->should_commit; } + bool IsCached(Serialize::Data &); void UpdateCache(Serialize::Data &); diff --git a/modules/database/db_json.cpp b/modules/database/db_json.cpp index ec054fe85..de3d4e2b8 100644 --- a/modules/database/db_json.cpp +++ b/modules/database/db_json.cpp @@ -412,6 +412,9 @@ public: // Step 2: store the new data. for (auto *item : Serializable::GetItems()) { + if (!item->ShouldCommit()) + continue; // Non-committable object. + auto *s_type = item->GetSerializableType(); if (!s_type) continue; // Provider has been unloaded. diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp index 80d460e6e..bb5c2556a 100644 --- a/modules/database/db_sql.cpp +++ b/modules/database/db_sql.cpp @@ -120,6 +120,12 @@ public: { if (this->sql) { + if (!obj->ShouldCommit()) + { + OnSerializableDestruct(obj); + continue; // Non-committable object. + } + Serialize::Type *s_type = obj->GetSerializableType(); if (!s_type) continue; diff --git a/modules/database/db_sql_live.cpp b/modules/database/db_sql_live.cpp index 6dfd3e477..82d8a8cd7 100644 --- a/modules/database/db_sql_live.cpp +++ b/modules/database/db_sql_live.cpp @@ -104,6 +104,12 @@ public: { if (obj && this->SQL) { + if (!obj->ShouldCommit()) + { + OnSerializableDestruct(obj); + continue; // Non-committable object. + } + Serialize::Type *s_type = obj->GetSerializableType(); if (!s_type) continue; diff --git a/src/nickalias.cpp b/src/nickalias.cpp index 97cea59f0..1c0f509e1 100644 --- a/src/nickalias.cpp +++ b/src/nickalias.cpp @@ -37,7 +37,7 @@ NickAlias::NickAlias(const Anope::string &nickname, NickCore *nickcore) if (this->nick.equals_ci(nickcore->display)) nickcore->na = this; - if (!NickAliasList->insert_or_assign(this->nick, this).second) + if (!this->InsertUnique(*NickAliasList, this->nick)) Log(LOG_DEBUG) << "Duplicate nick " << this->nick << " in NickAlias table"; if (this->nc->o == NULL) diff --git a/src/nickcore.cpp b/src/nickcore.cpp index 386e5e243..f704de642 100644 --- a/src/nickcore.cpp +++ b/src/nickcore.cpp @@ -31,11 +31,11 @@ NickCore::NickCore(const Anope::string &coredisplay, uint64_t coreid) if (coredisplay.empty()) throw CoreException("Empty display passed to NickCore constructor"); - if (!NickCoreList->insert_or_assign(this->display, this).second) + if (!this->InsertUnique(*NickCoreList, this->display)) Log(LOG_DEBUG) << "Duplicate account " << this->display << " in NickCore table"; // Upgrading users may not have an account identifier. - if (this->uniqueid && !NickCoreIdList->insert_or_assign(this->uniqueid, this).second) + if (this->uniqueid && !this->InsertUnique(*NickCoreIdList, this->uniqueid)) Log(LOG_DEBUG) << "Duplicate account id " << this->uniqueid << " in NickCore table"; FOREACH_MOD(OnNickCoreCreate, (this)); diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 457378ccc..c3ae6e43c 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -38,7 +38,7 @@ ChannelInfo::ChannelInfo(const Anope::string &chname) if (this->c) this->c->ci = this; - if (!RegisteredChannelList->insert_or_assign(this->name, this).second) + if (!this->InsertUnique(*RegisteredChannelList, this->name)) Log(LOG_DEBUG) << "Duplicate channel " << this->name << " in registered channel table?"; FOREACH_MOD(OnCreateChan, (this));