Beispiel #1
0
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;
}
Beispiel #2
0
	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();
				}
			}
		}
	}
Beispiel #3
0
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;
}
Beispiel #4
0
	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;
	}
Beispiel #5
0
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;
}