void ObjectLoader::OnResult(const Reply &r) { if (r.type != Reply::MULTI_BULK || r.multi_bulk.empty() || !me->redis) { delete this; return; } Serialize::TypeBase *type = obj->GetSerializableType(); for (Reply *reply : r.multi_bulk) { const Anope::string &key = reply->bulk; Serialize::FieldBase *field = type->GetField(key); if (field == nullptr) continue; std::vector<Anope::string> args = { "GET", "values:" + stringify(obj->id) + ":" + key }; me->redis->SendCommand(new FieldLoader(me, obj, field), args); } delete this; }
void BackupDatabase() { tm *tm = localtime(&Anope::CurTime); if (tm->tm_mday != last_day) { last_day = tm->tm_mday; const std::map<Anope::string, Serialize::TypeBase *> &types = Serialize::TypeBase::GetTypes(); std::set<Anope::string> dbs; dbs.insert(Config->GetModule(this)->Get<Anope::string>("database", "anope.db")); for (const std::pair<Anope::string, Serialize::TypeBase *> &p : types) { Serialize::TypeBase *stype = p.second; if (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(); } } } }
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; } Serialize::Object *obj = type->Require(id); if (obj == nullptr) { Log(LOG_DEBUG) << "redis: Unable to require object #" << id << " of type " << type->GetName(); continue; } std::vector<Anope::string> args = { "SMEMBERS", "keys:" + stringify(id) }; me->redis->SendCommand(new ObjectLoader(me, obj), args); } delete this; }
EventReturn OnLoadDatabase() override { const Anope::string &db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<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; } Serialize::TypeBase *type = nullptr; Serialize::Object *obj = nullptr; for (Anope::string buf; std::getline(fd, buf.str());) { if (buf.find("OBJECT ") == 0) { Anope::string t = buf.substr(7); if (obj) Log(LOG_DEBUG) << "obj != null but got OBJECT"; if (type) Log(LOG_DEBUG) << "type != null but got OBJECT"; type = Serialize::TypeBase::Find(t); obj = nullptr; } else if (buf.find("ID ") == 0) { if (!type || obj) continue; try { Serialize::ID id = convertTo<Serialize::ID>(buf.substr(3)); obj = type->Require(id); } catch (const ConvertException &) { Log(LOG_DEBUG) << "Unable to parse object id " << buf.substr(3); } } else if (buf.find("DATA ") == 0) { if (!type) continue; if (!obj) obj = type->Create(); size_t sp = buf.find(' ', 5); // Skip DATA if (sp == Anope::string::npos) continue; Anope::string key = buf.substr(5, sp - 5), value = buf.substr(sp + 1); Serialize::FieldBase *field = type->GetField(key); if (field) field->UnserializeFromString(obj, value); } else if (buf.find("END") == 0) { type = nullptr; obj = nullptr; } } fd.close(); loaded = true; return EVENT_STOP; }
void SubscriptionListener::OnResult(const Reply &r) { /* * message * anope * message * * set 4 email [email protected] * unset 4 email * create 4 NickCore * delete 4 */ const Anope::string &message = r.multi_bulk[2]->bulk; Anope::string command; spacesepstream sep(message); sep.GetToken(command); if (command == "set" || command == "unset") { Anope::string sid, key, value; sep.GetToken(sid); sep.GetToken(key); value = sep.GetRemaining(); Serialize::ID id; try { id = convertTo<Serialize::ID>(sid); } catch (const ConvertException &ex) { Log(LOG_DEBUG) << "redis: unable to get id for SL update key " << sid; return; } Serialize::Object *obj = Serialize::GetID(id); if (obj == nullptr) { Log(LOG_DEBUG) << "redis: pmessage for unknown object #" << id; return; } Serialize::FieldBase *field = obj->GetSerializableType()->GetField(key); if (field == nullptr) { Log(LOG_DEBUG) << "redis: pmessage for unknown field of object #" << id << ": " << key; return; } Log(LOG_DEBUG_2) << "redis: Setting field " << field->serialize_name << " of object #" << obj->id << " of type " << obj->GetSerializableType()->GetName() << " to " << value; field->UnserializeFromString(obj, value); } else if (command == "create") { Anope::string sid, stype; sep.GetToken(sid); sep.GetToken(stype); Serialize::ID id; try { id = convertTo<Serialize::ID>(sid); } catch (const ConvertException &ex) { Log(LOG_DEBUG) << "redis: unable to get id for SL update key " << sid; return; } Serialize::TypeBase *type = Serialize::TypeBase::Find(stype); if (type == nullptr) { Log(LOG_DEBUG) << "redis: pmessage create for nonexistant type " << stype; return; } Serialize::Object *obj = type->Require(id); if (obj == nullptr) { Log(LOG_DEBUG) << "redis: require for pmessage create type " << type->GetName() << " id #" << id << " returned nullptr"; return; } } else if (command == "delete") { Anope::string sid; sep.GetToken(sid); Serialize::ID id; try { id = convertTo<Serialize::ID>(sid); } catch (const ConvertException &ex) { Log(LOG_DEBUG) << "redis: unable to get id for SL update key " << sid; return; } Serialize::Object *obj = Serialize::GetID(id); if (obj == nullptr) { Log(LOG_DEBUG) << "redis: message for unknown object #" << id; return; } obj->Delete(); } else Log(LOG_DEBUG) << "redis: unknown message: " << message; }