diff options
Diffstat (limited to 'modules/database')
| -rw-r--r-- | modules/database/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | modules/database/db_flatfile.cpp | 415 | ||||
| -rw-r--r-- | modules/database/db_redis.cpp | 644 | ||||
| -rw-r--r-- | modules/database/db_sql.cpp | 263 | ||||
| -rw-r--r-- | modules/database/db_sql_live.cpp | 265 | ||||
| -rw-r--r-- | modules/database/flatfile.cpp | 807 | ||||
| -rw-r--r-- | modules/database/old.cpp (renamed from modules/database/db_old.cpp) | 652 | ||||
| -rw-r--r-- | modules/database/sql.cpp | 380 |
8 files changed, 1574 insertions, 1854 deletions
diff --git a/modules/database/CMakeLists.txt b/modules/database/CMakeLists.txt new file mode 100644 index 000000000..9a236d6d0 --- /dev/null +++ b/modules/database/CMakeLists.txt @@ -0,0 +1,2 @@ +build_modules(${CMAKE_CURRENT_SOURCE_DIR}) +build_modules_dependencies(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/modules/database/db_flatfile.cpp b/modules/database/db_flatfile.cpp deleted file mode 100644 index 171573d1c..000000000 --- a/modules/database/db_flatfile.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -#ifndef _WIN32 -#include <sys/wait.h> -#endif - -class SaveData : public Serialize::Data -{ - public: - Anope::string last; - std::fstream *fs; - - SaveData() : fs(NULL) { } - - std::iostream& operator[](const Anope::string &key) anope_override - { - if (key != last) - { - *fs << "\nDATA " << key << " "; - last = key; - } - - return *fs; - } -}; - -class LoadData : public Serialize::Data -{ - public: - std::fstream *fs; - unsigned int id; - std::map<Anope::string, Anope::string> data; - std::stringstream ss; - bool read; - - LoadData() : fs(NULL), id(0), read(false) { } - - std::iostream& operator[](const Anope::string &key) anope_override - { - if (!read) - { - for (Anope::string token; std::getline(*this->fs, token.str());) - { - if (token.find("ID ") == 0) - { - try - { - this->id = convertTo<unsigned int>(token.substr(3)); - } - catch (const ConvertException &) { } - - continue; - } - else if (token.find("DATA ") != 0) - break; - - size_t sp = token.find(' ', 5); // Skip DATA - if (sp != Anope::string::npos) - data[token.substr(5, sp - 5)] = token.substr(sp + 1); - } - - read = true; - } - - ss.clear(); - this->ss << this->data[key]; - return this->ss; - } - - std::set<Anope::string> KeySet() const anope_override - { - std::set<Anope::string> keys; - for (std::map<Anope::string, Anope::string>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it) - keys.insert(it->first); - return keys; - } - - size_t Hash() const anope_override - { - size_t hash = 0; - for (std::map<Anope::string, Anope::string>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it) - if (!it->second.empty()) - hash ^= Anope::hash_cs()(it->second); - return hash; - } - - void Reset() - { - id = 0; - read = false; - data.clear(); - } -}; - -class DBFlatFile : public Module, public Pipe -{ - /* Day the last backup was on */ - int last_day; - /* Backup file names */ - std::map<Anope::string, std::list<Anope::string> > backups; - bool loaded; - - int child_pid; - - void BackupDatabase() - { - tm *tm = localtime(&Anope::CurTime); - - if (tm->tm_mday != last_day) - { - last_day = tm->tm_mday; - - const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder(); - - std::set<Anope::string> dbs; - dbs.insert(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db")); - - for (unsigned i = 0; i < type_order.size(); ++i) - { - Serialize::Type *stype = Serialize::Type::Find(type_order[i]); - - if (stype && stype->GetOwner()) - dbs.insert("module_" + stype->GetOwner()->name + ".db"); - } - - - for (std::set<Anope::string>::const_iterator it = dbs.begin(), it_end = dbs.end(); it != it_end; ++it) - { - const Anope::string &oldname = Anope::DataDir + "/" + *it; - Anope::string newname = Anope::DataDir + "/backups/" + *it + "-" + stringify(tm->tm_year + 1900) + Anope::printf("-%02i-", tm->tm_mon + 1) + Anope::printf("%02i", tm->tm_mday); - - /* Backup already exists or no database to backup */ - if (Anope::IsFile(newname) || !Anope::IsFile(oldname)) - continue; - - Log(LOG_DEBUG) << "db_flatfile: Attempting to rename " << *it << " to " << newname; - if (rename(oldname.c_str(), newname.c_str())) - { - Anope::string err = Anope::LastError(); - Log(this) << "Unable to back up database " << *it << " (" << err << ")!"; - - if (!Config->GetModule(this)->Get<bool>("nobackupokay")) - { - Anope::Quitting = true; - Anope::QuitReason = "Unable to back up database " + *it + " (" + err + ")"; - } - - continue; - } - - backups[*it].push_back(newname); - - unsigned keepbackups = Config->GetModule(this)->Get<unsigned>("keepbackups"); - if (keepbackups > 0 && backups[*it].size() > keepbackups) - { - unlink(backups[*it].front().c_str()); - backups[*it].pop_front(); - } - } - } - } - - public: - DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), last_day(0), loaded(false), child_pid(-1) - { - - } - -#ifndef _WIN32 - void OnRestart() anope_override - { - OnShutdown(); - } - - void OnShutdown() anope_override - { - if (child_pid > -1) - { - Log(this) << "Waiting for child to exit..."; - - int status; - waitpid(child_pid, &status, 0); - - Log(this) << "Done"; - } - } -#endif - - void OnNotify() anope_override - { - char buf[512]; - int i = this->Read(buf, sizeof(buf) - 1); - if (i <= 0) - return; - buf[i] = 0; - - child_pid = -1; - - if (!*buf) - { - Log(this) << "Finished saving databases"; - return; - } - - Log(this) << "Error saving databases: " << buf; - - if (!Config->GetModule(this)->Get<bool>("nobackupokay")) - Anope::Quitting = true; - } - - EventReturn OnLoadDatabase() anope_override - { - const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder(); - std::set<Anope::string> tried_dbs; - - const Anope::string &db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"); - - std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary); - if (!fd.is_open()) - { - Log(this) << "Unable to open " << db_name << " for reading!"; - return EVENT_STOP; - } - - std::map<Anope::string, std::vector<std::streampos> > positions; - - for (Anope::string buf; std::getline(fd, buf.str());) - if (buf.find("OBJECT ") == 0) - positions[buf.substr(7)].push_back(fd.tellg()); - - LoadData ld; - ld.fs = &fd; - - for (unsigned i = 0; i < type_order.size(); ++i) - { - Serialize::Type *stype = Serialize::Type::Find(type_order[i]); - if (!stype || stype->GetOwner()) - continue; - - std::vector<std::streampos> &pos = positions[stype->GetName()]; - - for (unsigned j = 0; j < pos.size(); ++j) - { - fd.clear(); - fd.seekg(pos[j]); - - Serializable *obj = stype->Unserialize(NULL, ld); - if (obj != NULL) - obj->id = ld.id; - ld.Reset(); - } - } - - fd.close(); - - loaded = true; - return EVENT_STOP; - } - - - void OnSaveDatabase() anope_override - { - if (child_pid > -1) - { - Log(this) << "Database save is already in progress!"; - return; - } - - BackupDatabase(); - - int i = -1; -#ifndef _WIN32 - if (!Anope::Quitting && Config->GetModule(this)->Get<bool>("fork")) - { - i = fork(); - if (i > 0) - { - child_pid = i; - return; - } - else if (i < 0) - Log(this) << "Unable to fork for database save"; - } -#endif - - try - { - std::map<Module *, std::fstream *> databases; - - /* First open the databases of all of the registered types. This way, if we have a type with 0 objects, that database will be properly cleared */ - for (std::map<Anope::string, Serialize::Type *>::const_iterator it = Serialize::Type::GetTypes().begin(), it_end = Serialize::Type::GetTypes().end(); it != it_end; ++it) - { - Serialize::Type *s_type = it->second; - - if (databases[s_type->GetOwner()]) - continue; - - Anope::string db_name; - if (s_type->GetOwner()) - db_name = Anope::DataDir + "/module_" + s_type->GetOwner()->name + ".db"; - else - db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"); - - if (Anope::IsFile(db_name)) - rename(db_name.c_str(), (db_name + ".tmp").c_str()); - - std::fstream *fs = databases[s_type->GetOwner()] = new std::fstream(db_name.c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary); - - if (!fs->is_open()) - Log(this) << "Unable to open " << db_name << " for writing"; - } - - SaveData data; - const std::list<Serializable *> &items = Serializable::GetItems(); - for (std::list<Serializable *>::const_iterator it = items.begin(), it_end = items.end(); it != it_end; ++it) - { - Serializable *base = *it; - Serialize::Type *s_type = base->GetSerializableType(); - - data.fs = databases[s_type->GetOwner()]; - if (!data.fs || !data.fs->is_open()) - continue; - - *data.fs << "OBJECT " << s_type->GetName(); - if (base->id) - *data.fs << "\nID " << base->id; - base->Serialize(data); - *data.fs << "\nEND\n"; - } - - for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it) - { - std::fstream *f = it->second; - const Anope::string &db_name = Anope::DataDir + "/" + (it->first ? (it->first->name + ".db") : Config->GetModule(this)->Get<const Anope::string>("database", "anope.db")); - - if (!f->is_open() || !f->good()) - { - this->Write("Unable to write database " + db_name); - - f->close(); - - if (Anope::IsFile((db_name + ".tmp").c_str())) - rename((db_name + ".tmp").c_str(), db_name.c_str()); - } - else - { - f->close(); - unlink((db_name + ".tmp").c_str()); - } - - delete f; - } - } - catch (...) - { - if (i) - throw; - } - - if (!i) - { - this->Notify(); - exit(0); - } - } - - /* 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 + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"); - - std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary); - 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_redis.cpp b/modules/database/db_redis.cpp deleted file mode 100644 index db12a2c5f..000000000 --- a/modules/database/db_redis.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/* - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - */ - -#include "module.h" -#include "modules/redis.h" - -using namespace Redis; - -class DatabaseRedis; -static DatabaseRedis *me; - -class Data : public Serialize::Data -{ - public: - std::map<Anope::string, std::stringstream *> data; - - ~Data() - { - for (std::map<Anope::string, std::stringstream *>::iterator it = data.begin(), it_end = data.end(); it != it_end; ++it) - delete it->second; - } - - std::iostream& operator[](const Anope::string &key) anope_override - { - std::stringstream* &stream = data[key]; - if (!stream) - stream = new std::stringstream(); - return *stream; - } - - std::set<Anope::string> KeySet() const anope_override - { - std::set<Anope::string> keys; - for (std::map<Anope::string, std::stringstream *>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it) - keys.insert(it->first); - return keys; - } - - size_t Hash() const anope_override - { - size_t hash = 0; - for (std::map<Anope::string, std::stringstream *>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it) - if (!it->second->str().empty()) - hash ^= Anope::hash_cs()(it->second->str()); - return hash; - } -}; - -class TypeLoader : public Interface -{ - Anope::string type; - public: - TypeLoader(Module *creator, const Anope::string &t) : Interface(creator), type(t) { } - - void OnResult(const Reply &r) anope_override; -}; - -class ObjectLoader : public Interface -{ - Anope::string type; - int64_t id; - - public: - ObjectLoader(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { } - - void OnResult(const Reply &r) anope_override; -}; - -class IDInterface : public Interface -{ - Reference<Serializable> o; - public: - IDInterface(Module *creator, Serializable *obj) : Interface(creator), o(obj) { } - - void OnResult(const Reply &r) anope_override; -}; - -class Deleter : public Interface -{ - Anope::string type; - int64_t id; - public: - Deleter(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { } - - void OnResult(const Reply &r) anope_override; -}; - -class Updater : public Interface -{ - Anope::string type; - int64_t id; - public: - Updater(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { } - - void OnResult(const Reply &r) anope_override; -}; - -class ModifiedObject : public Interface -{ - Anope::string type; - int64_t id; - public: - ModifiedObject(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { } - - void OnResult(const Reply &r) anope_override; -}; - -class SubscriptionListener : public Interface -{ - public: - SubscriptionListener(Module *creator) : Interface(creator) { } - - void OnResult(const Reply &r) anope_override; -}; - -class DatabaseRedis : public Module, public Pipe -{ - SubscriptionListener sl; - std::set<Serializable *> updated_items; - - public: - ServiceReference<Provider> redis; - - DatabaseRedis(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), sl(this) - { - me = this; - - } - - /* Insert or update an object */ - void InsertObject(Serializable *obj) - { - Serialize::Type *t = obj->GetSerializableType(); - - /* If there is no id yet for this object, get one */ - if (!obj->id) - redis->SendCommand(new IDInterface(this, obj), "INCR id:" + t->GetName()); - else - { - Data data; - obj->Serialize(data); - - if (obj->IsCached(data)) - return; - - obj->UpdateCache(data); - - std::vector<Anope::string> args; - args.push_back("HGETALL"); - args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id)); - - /* Get object attrs to clear before updating */ - redis->SendCommand(new Updater(this, t->GetName(), obj->id), args); - } - } - - void OnNotify() anope_override - { - for (std::set<Serializable *>::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it) - { - Serializable *s = *it; - - this->InsertObject(s); - } - - this->updated_items.clear(); - } - - void OnReload(Configuration::Conf *conf) anope_override - { - Configuration::Block *block = conf->GetModule(this); - this->redis = ServiceReference<Provider>("Redis::Provider", block->Get<const Anope::string>("engine", "redis/main")); - } - - EventReturn OnLoadDatabase() anope_override - { - const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder(); - for (unsigned i = 0; i < type_order.size(); ++i) - { - Serialize::Type *sb = Serialize::Type::Find(type_order[i]); - this->OnSerializeTypeCreate(sb); - } - - while (redis->BlockAndProcess()); - - redis->Subscribe(&this->sl, "__keyspace@*__:hash:*"); - - return EVENT_STOP; - } - - void OnSerializeTypeCreate(Serialize::Type *sb) anope_override - { - if (!redis) - return; - - std::vector<Anope::string> args; - args.push_back("SMEMBERS"); - args.push_back("ids:" + sb->GetName()); - - redis->SendCommand(new TypeLoader(this, sb->GetName()), args); - } - - void OnSerializableConstruct(Serializable *obj) anope_override - { - this->updated_items.insert(obj); - this->Notify(); - } - - void OnSerializableDestruct(Serializable *obj) anope_override - { - Serialize::Type *t = obj->GetSerializableType(); - - std::vector<Anope::string> args; - args.push_back("HGETALL"); - args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id)); - - /* Get all of the attributes for this object */ - redis->SendCommand(new Deleter(this, t->GetName(), obj->id), args); - - this->updated_items.erase(obj); - t->objects.erase(obj->id); - this->Notify(); - } - - void OnSerializableUpdate(Serializable *obj) anope_override - { - this->updated_items.insert(obj); - this->Notify(); - } -}; - -void TypeLoader::OnResult(const Reply &r) -{ - if (r.type != Reply::MULTI_BULK || !me->redis) - { - delete this; - return; - } - - for (unsigned i = 0; i < r.multi_bulk.size(); ++i) - { - const Reply *reply = r.multi_bulk[i]; - - if (reply->type != Reply::BULK) - continue; - - int64_t id; - try - { - id = convertTo<int64_t>(reply->bulk); - } - catch (const ConvertException &) - { - continue; - } - - std::vector<Anope::string> args; - args.push_back("HGETALL"); - args.push_back("hash:" + this->type + ":" + stringify(id)); - - me->redis->SendCommand(new ObjectLoader(me, this->type, id), args); - } - - delete this; -} - -void ObjectLoader::OnResult(const Reply &r) -{ - Serialize::Type *st = Serialize::Type::Find(this->type); - - if (r.type != Reply::MULTI_BULK || r.multi_bulk.empty() || !me->redis || !st) - { - delete this; - return; - } - - Data data; - - for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2) - { - const Reply *key = r.multi_bulk[i], - *value = r.multi_bulk[i + 1]; - - data[key->bulk] << value->bulk; - } - - Serializable* &obj = st->objects[this->id]; - obj = st->Unserialize(obj, data); - if (obj) - { - obj->id = this->id; - obj->UpdateCache(data); - } - - delete this; -} - -void IDInterface::OnResult(const Reply &r) -{ - if (!o || r.type != Reply::INT || !r.i) - { - delete this; - return; - } - - Serializable* &obj = o->GetSerializableType()->objects[r.i]; - if (obj) - /* This shouldn't be possible */ - obj->id = 0; - - o->id = r.i; - obj = o; - - /* Now that we have the id, insert this object for real */ - anope_dynamic_static_cast<DatabaseRedis *>(this->owner)->InsertObject(o); - - delete this; -} - -void Deleter::OnResult(const Reply &r) -{ - if (r.type != Reply::MULTI_BULK || !me->redis || r.multi_bulk.empty()) - { - delete this; - return; - } - - /* Transaction start */ - me->redis->StartTransaction(); - - std::vector<Anope::string> args; - args.push_back("DEL"); - args.push_back("hash:" + this->type + ":" + stringify(this->id)); - - /* Delete hash object */ - me->redis->SendCommand(NULL, args); - - args.clear(); - args.push_back("SREM"); - args.push_back("ids:" + this->type); - args.push_back(stringify(this->id)); - - /* Delete id from ids set */ - me->redis->SendCommand(NULL, args); - - for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2) - { - const Reply *key = r.multi_bulk[i], - *value = r.multi_bulk[i + 1]; - - args.clear(); - args.push_back("SREM"); - args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk); - args.push_back(stringify(this->id)); - - /* Delete value -> object id */ - me->redis->SendCommand(NULL, args); - } - - /* Transaction end */ - me->redis->CommitTransaction(); - - delete this; -} - -void Updater::OnResult(const Reply &r) -{ - Serialize::Type *st = Serialize::Type::Find(this->type); - - if (!st) - { - delete this; - return; - } - - Serializable *obj = st->objects[this->id]; - if (!obj) - { - delete this; - return; - } - - Data data; - obj->Serialize(data); - - /* Transaction start */ - me->redis->StartTransaction(); - - for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2) - { - const Reply *key = r.multi_bulk[i], - *value = r.multi_bulk[i + 1]; - - std::vector<Anope::string> args; - args.push_back("SREM"); - args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk); - args.push_back(stringify(this->id)); - - /* Delete value -> object id */ - me->redis->SendCommand(NULL, args); - } - - /* Add object id to id set for this type */ - std::vector<Anope::string> args; - args.push_back("SADD"); - args.push_back("ids:" + this->type); - args.push_back(stringify(obj->id)); - me->redis->SendCommand(NULL, args); - - args.clear(); - args.push_back("HMSET"); - args.push_back("hash:" + this->type + ":" + stringify(obj->id)); - - typedef std::map<Anope::string, std::stringstream *> items; - for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it) - { - const Anope::string &key = it->first; - std::stringstream *value = it->second; - - args.push_back(key); - args.push_back(value->str()); - - std::vector<Anope::string> args2; - - args2.push_back("SADD"); - args2.push_back("value:" + this->type + ":" + key + ":" + value->str()); - args2.push_back(stringify(obj->id)); - - /* Add to value -> object id set */ - me->redis->SendCommand(NULL, args2); - } - - ++obj->redis_ignore; - - /* Add object */ - me->redis->SendCommand(NULL, args); - - /* Transaction end */ - me->redis->CommitTransaction(); - - delete this; -} - -void SubscriptionListener::OnResult(const Reply &r) -{ - /* - * [May 15 13:59:35.645839 2013] Debug: pmessage - * [May 15 13:59:35.645866 2013] Debug: __keyspace@*__:anope:hash:* - * [May 15 13:59:35.645880 2013] Debug: __keyspace@0__:anope:hash:type:id - * [May 15 13:59:35.645893 2013] Debug: hset - */ - if (r.multi_bulk.size() != 4) - return; - - size_t sz = r.multi_bulk[2]->bulk.find(':'); - if (sz == Anope::string::npos) - return; - - const Anope::string &key = r.multi_bulk[2]->bulk.substr(sz + 1), - &op = r.multi_bulk[3]->bulk; - - sz = key.rfind(':'); - if (sz == Anope::string::npos) - return; - - const Anope::string &id = key.substr(sz + 1); - - size_t sz2 = key.rfind(':', sz - 1); - if (sz2 == Anope::string::npos) - return; - const Anope::string &type = key.substr(sz2 + 1, sz - sz2 - 1); - - Serialize::Type *s_type = Serialize::Type::Find(type); - - if (s_type == NULL) - return; - - uint64_t obj_id; - try - { - obj_id = convertTo<uint64_t>(id); - } - catch (const ConvertException &) - { - return; - } - - if (op == "hset" || op == "hdel") - { - Serializable *s = s_type->objects[obj_id]; - - if (s && s->redis_ignore) - { - --s->redis_ignore; - Log(LOG_DEBUG) << "redis: notify: got modify for object id " << obj_id << " of type " << type << ", but I am ignoring it"; - } - else - { - Log(LOG_DEBUG) << "redis: notify: got modify for object id " << obj_id << " of type " << type; - - std::vector<Anope::string> args; - args.push_back("HGETALL"); - args.push_back("hash:" + type + ":" + id); - - me->redis->SendCommand(new ModifiedObject(me, type, obj_id), args); - } - } - else if (op == "del") - { - Serializable* &s = s_type->objects[obj_id]; - if (s == NULL) - return; - - Log(LOG_DEBUG) << "redis: notify: deleting object id " << obj_id << " of type " << type; - - Data data; - - s->Serialize(data); - - /* Transaction start */ - me->redis->StartTransaction(); - - typedef std::map<Anope::string, std::stringstream *> items; - for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it) - { - const Anope::string &k = it->first; - std::stringstream *value = it->second; - - std::vector<Anope::string> args; - args.push_back("SREM"); - args.push_back("value:" + type + ":" + k + ":" + value->str()); - args.push_back(id); - - /* Delete value -> object id */ - me->redis->SendCommand(NULL, args); - } - - std::vector<Anope::string> args; - args.push_back("SREM"); - args.push_back("ids:" + type); - args.push_back(stringify(s->id)); - - /* Delete object from id set */ - me->redis->SendCommand(NULL, args); - - /* Transaction end */ - me->redis->CommitTransaction(); - - delete s; - s = NULL; - } -} - -void ModifiedObject::OnResult(const Reply &r) -{ - Serialize::Type *st = Serialize::Type::Find(this->type); - - if (!st) - { - delete this; - return; - } - - Serializable* &obj = st->objects[this->id]; - - /* Transaction start */ - me->redis->StartTransaction(); - - /* Erase old object values */ - if (obj) - { - Data data; - - obj->Serialize(data); - - typedef std::map<Anope::string, std::stringstream *> items; - for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it) - { - const Anope::string &key = it->first; - std::stringstream *value = it->second; - - std::vector<Anope::string> args; - args.push_back("SREM"); - args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str()); - args.push_back(stringify(this->id)); - - /* Delete value -> object id */ - me->redis->SendCommand(NULL, args); - } - } - - Data data; - - for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2) - { - const Reply *key = r.multi_bulk[i], - *value = r.multi_bulk[i + 1]; - - data[key->bulk] << value->bulk; - } - - obj = st->Unserialize(obj, data); - if (obj) - { - obj->id = this->id; - obj->UpdateCache(data); - - /* Insert new object values */ - typedef std::map<Anope::string, std::stringstream *> items; - for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it) - { - const Anope::string &key = it->first; - std::stringstream *value = it->second; - - std::vector<Anope::string> args; - args.push_back("SADD"); - args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str()); - args.push_back(stringify(obj->id)); - - /* Add to value -> object id set */ - me->redis->SendCommand(NULL, args); - } - - std::vector<Anope::string> args; - args.push_back("SADD"); - args.push_back("ids:" + st->GetName()); - args.push_back(stringify(obj->id)); - - /* Add to type -> id set */ - me->redis->SendCommand(NULL, args); - } - - /* Transaction end */ - me->redis->CommitTransaction(); - - delete this; -} - -MODULE_INIT(DatabaseRedis) diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp deleted file mode 100644 index 12fc8512f..000000000 --- a/modules/database/db_sql.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/sql.h" - -using namespace SQL; - -class SQLSQLInterface : public Interface -{ - public: - SQLSQLInterface(Module *o) : Interface(o) { } - - void OnResult(const Result &r) anope_override - { - Log(LOG_DEBUG) << "SQL successfully executed query: " << r.finished_query; - } - - void OnError(const Result &r) anope_override - { - if (!r.GetQuery().query.empty()) - Log(LOG_DEBUG) << "Error executing query " << r.finished_query << ": " << r.GetError(); - else - Log(LOG_DEBUG) << "Error executing query: " << r.GetError(); - } -}; - -class ResultSQLSQLInterface : public SQLSQLInterface -{ - Reference<Serializable> obj; - -public: - ResultSQLSQLInterface(Module *o, Serializable *ob) : SQLSQLInterface(o), obj(ob) { } - - void OnResult(const Result &r) anope_override - { - SQLSQLInterface::OnResult(r); - if (r.GetID() > 0 && this->obj) - this->obj->id = r.GetID(); - delete this; - } - - void OnError(const Result &r) anope_override - { - SQLSQLInterface::OnError(r); - delete this; - } -}; - -class DBSQL : public Module, public Pipe -{ - ServiceReference<Provider> sql; - SQLSQLInterface sqlinterface; - Anope::string prefix; - bool import; - - std::set<Serializable *> updated_items; - bool shutting_down; - bool loading_databases; - bool loaded; - bool imported; - - void RunBackground(const Query &q, Interface *iface = NULL) - { - if (!this->sql) - { - static time_t last_warn = 0; - if (last_warn + 300 < Anope::CurTime) - { - last_warn = Anope::CurTime; - Log(this) << "db_sql: Unable to execute query, is SQL configured correctly?"; - } - } - else if (!Anope::Quitting) - { - if (iface == NULL) - iface = &this->sqlinterface; - this->sql->Run(iface, q); - } - else - this->sql->RunQuery(q); - } - - public: |
