mirror of
https://github.com/anope/anope.git
synced 2026-06-29 22:46:37 +02:00
irc2sql: improved handling of netsplits
This commit is contained in:
+7
-1
@@ -62,7 +62,8 @@ class CoreExport Server : public Extensible
|
||||
bool syncing;
|
||||
/* The server is juped */
|
||||
bool juped;
|
||||
|
||||
/* The server is about to quit */
|
||||
bool quitting;
|
||||
/* Reason this server was quit */
|
||||
Anope::string quit_reason;
|
||||
|
||||
@@ -169,6 +170,11 @@ class CoreExport Server : public Extensible
|
||||
*/
|
||||
bool IsJuped() const;
|
||||
|
||||
/** Check if the server is quitting
|
||||
* @return true if this server is quitting.
|
||||
*/
|
||||
bool IsQuitting() const;
|
||||
|
||||
/** Send a message to alll users on this server
|
||||
* @param source The source of the message
|
||||
* @param message The message
|
||||
|
||||
@@ -76,9 +76,7 @@ void IRC2SQL::OnServerQuit(Server *server) anope_override
|
||||
if (quitting)
|
||||
return;
|
||||
|
||||
query = "UPDATE `" + prefix + "server` "
|
||||
"SET currentusers = 0, online = 'N', split_time = now() "
|
||||
"WHERE name = @name@";
|
||||
query = "CALL " + prefix + "ServerQuit(@name@)";
|
||||
query.SetValue("name", server->GetName());
|
||||
this->RunQuery(query);
|
||||
}
|
||||
@@ -118,7 +116,7 @@ void IRC2SQL::OnUserConnect(User *u, bool &exempt) anope_override
|
||||
|
||||
void IRC2SQL::OnUserQuit(User *u, const Anope::string &msg) anope_override
|
||||
{
|
||||
if (quitting)
|
||||
if (quitting || u->server->IsQuitting())
|
||||
return;
|
||||
|
||||
query = "CALL " + prefix + "UserQuit(@nick@)";
|
||||
@@ -238,9 +236,8 @@ void IRC2SQL::OnLeaveChannel(User *u, Channel *c) anope_override
|
||||
* user is quitting, we already received a OnUserQuit()
|
||||
* at this point the user is already removed from SQL and all channels
|
||||
*/
|
||||
if (u->Quitting());
|
||||
if (u->Quitting())
|
||||
return;
|
||||
|
||||
query = "CALL " + prefix + "PartUser(@nick@,@channel@)";
|
||||
query.SetValue("nick", u->nick);
|
||||
query.SetValue("channel", c->name);
|
||||
|
||||
@@ -7,12 +7,12 @@ void IRC2SQL::CheckTables()
|
||||
if (firstrun)
|
||||
{
|
||||
/*
|
||||
* drop/recreate some tables in case anope crashed
|
||||
* and was unable to clear the content (ison)
|
||||
* reset some tables to make sure they are really empty
|
||||
*/
|
||||
this->sql->RunQuery(SQL::Query("DROP TABLE " + prefix + "user"));
|
||||
this->sql->RunQuery(SQL::Query("DROP TABLE " + prefix + "chan"));
|
||||
this->sql->RunQuery(SQL::Query("DROP TABLE " + prefix + "ison"));
|
||||
this->sql->RunQuery("TRUNCATE TABLE " + prefix + "user");
|
||||
this->sql->RunQuery("TRUNCATE TABLE " + prefix + "chan");
|
||||
this->sql->RunQuery("TRUNCATE TABLE " + prefix + "ison");
|
||||
this->sql->RunQuery("UPDATE `" + prefix + "server` SET currentusers=0, online='N'");
|
||||
}
|
||||
|
||||
this->GetTables();
|
||||
@@ -227,8 +227,80 @@ void IRC2SQL::CheckTables()
|
||||
"END";
|
||||
this->RunQuery(query);
|
||||
|
||||
if (this->HasProcedure(prefix + "ServerQuit"))
|
||||
this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "ServerQuit"));
|
||||
query = "CREATE PROCEDURE " + prefix + "ServerQuit(sname_ varchar(255)) "
|
||||
"BEGIN "
|
||||
/* 1.
|
||||
* loop through all channels and decrease the user count
|
||||
* by the number of users that are on this channel AND
|
||||
* on the splitting server
|
||||
*
|
||||
* we dont have to care about channels that get empty, there will be
|
||||
* an extra OnChannelDelete event triggered from anope.
|
||||
*/
|
||||
"DECLARE no_more_rows BOOLEAN DEFAULT FALSE;"
|
||||
"DECLARE channel_ varchar(255);"
|
||||
"DECLARE ucount_ int;"
|
||||
"DECLARE channel_cursor CURSOR FOR "
|
||||
"SELECT c.channel "
|
||||
"FROM `" + prefix + "chan` as c, `" + prefix + "ison` as i, "
|
||||
"`" + prefix + "user` as u, `" + prefix + "server` as s "
|
||||
"WHERE c.chanid = i.chanid "
|
||||
"AND i.nickid = u.nickid "
|
||||
"AND u.servid = s.id "
|
||||
"AND s.name = sname_;"
|
||||
"DECLARE CONTINUE HANDLER FOR NOT FOUND "
|
||||
"SET no_more_rows = TRUE;"
|
||||
"OPEN channel_cursor;"
|
||||
"the_loop: LOOP "
|
||||
"FETCH channel_cursor INTO channel_;"
|
||||
"IF no_more_rows THEN "
|
||||
"CLOSE channel_cursor;"
|
||||
"LEAVE the_loop;"
|
||||
"END IF;"
|
||||
"SELECT COUNT(*) INTO ucount_ "
|
||||
"FROM `" + prefix + "ison` AS i, `" + prefix + "chan` AS c,"
|
||||
"`" + prefix + "user` AS u, `" + prefix + "server` AS s "
|
||||
"WHERE i.nickid = u.nickid "
|
||||
"AND u.servid = s.id "
|
||||
"AND i.chanid = c.chanid "
|
||||
"AND c.channel = channel_ "
|
||||
"AND s.name = sname_; "
|
||||
"UPDATE `" + prefix + "chan` "
|
||||
"SET currentusers = currentusers - ucount_ "
|
||||
"WHERE channel = channel_;"
|
||||
"END LOOP;"
|
||||
|
||||
/* 2.
|
||||
* remove all users on the splitting server from the ison table
|
||||
*/
|
||||
"DELETE i FROM `" + prefix + "ison` AS i "
|
||||
"INNER JOIN `" + prefix + "server` AS s "
|
||||
"INNER JOIN `" + prefix + "user` AS u "
|
||||
"WHERE i.nickid = u.nickid "
|
||||
"AND u.servid = s.id "
|
||||
"AND s.name = sname_;"
|
||||
|
||||
/* 3.
|
||||
* remove all users on the splitting server from the user table
|
||||
*/
|
||||
"DELETE u FROM `" + prefix + "user` AS u "
|
||||
"INNER JOIN `" + prefix + "server` AS s "
|
||||
"WHERE s.id = u.servid "
|
||||
"AND s.name = sname_;"
|
||||
|
||||
/* 4.
|
||||
* on the splitting server, set usercount = 0, split_time = now(), online = 'N'
|
||||
*/
|
||||
"UPDATE `" + prefix + "server` SET currentusers = 0, split_time = now(), online = 'N' "
|
||||
"WHERE name = sname_;"
|
||||
"END;"; // end of the procedure
|
||||
this->RunQuery(query);
|
||||
|
||||
|
||||
if (this->HasProcedure(prefix + "UserQuit"))
|
||||
this->RunQuery(SQL::Query("DROP PROCEDURE " +prefix + "UserQuit"));
|
||||
this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "UserQuit"));
|
||||
query = "CREATE PROCEDURE `" + prefix + "UserQuit`"
|
||||
"(nick_ varchar(255)) "
|
||||
"BEGIN "
|
||||
@@ -245,10 +317,8 @@ void IRC2SQL::CheckTables()
|
||||
/* remove from all channels where the user was on */
|
||||
"DELETE i FROM `" + prefix + "ison` AS i "
|
||||
"INNER JOIN `" + prefix + "user` as u "
|
||||
"INNER JOIN `" + prefix + "chan` as c "
|
||||
"WHERE u.nick = nick_ "
|
||||
"AND i.nickid = u.nickid "
|
||||
"AND i.chanid = c.chanid;"
|
||||
/* remove the user from the user table */
|
||||
"DELETE FROM `" + prefix + "user` WHERE nick = nick_; "
|
||||
"END";
|
||||
@@ -298,13 +368,13 @@ void IRC2SQL::CheckTables()
|
||||
query = "CREATE PROCEDURE `" + prefix + "PartUser`"
|
||||
"(nick_ varchar(255), channel_ varchar(255)) "
|
||||
"BEGIN "
|
||||
"DELETE FROM `" + prefix + "ison` "
|
||||
"USING `" + prefix + "ison`, `" + prefix + "user` , `"
|
||||
+ prefix + "chan` "
|
||||
"WHERE " + prefix + "ison.nickid = " + prefix + "user.nickid "
|
||||
"AND " + prefix + "user.nick = nick_ "
|
||||
"AND " + prefix + "ison.chanid = " + prefix + "chan.chanid "
|
||||
"AND " + prefix + "chan.channel = channel_; "
|
||||
"DELETE i FROM `" + prefix + "ison` AS i "
|
||||
"INNER JOIN `" + prefix + "user` AS u "
|
||||
"INNER JOIN `" + prefix + "chan` AS c "
|
||||
"WHERE i.nickid = u.nickid "
|
||||
"AND u.nick = nick_ "
|
||||
"AND i.chanid = c.chanid "
|
||||
"AND c.channel = channel_;"
|
||||
"UPDATE `" + prefix + "chan` SET currentusers=currentusers-1 "
|
||||
"WHERE channel=channel_;"
|
||||
"END";
|
||||
|
||||
@@ -32,6 +32,7 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano
|
||||
{
|
||||
syncing = true;
|
||||
juped = jupe;
|
||||
quitting = false;
|
||||
|
||||
Servers::ByName[sname] = this;
|
||||
if (!ssid.empty())
|
||||
@@ -164,6 +165,7 @@ Server::~Server()
|
||||
void Server::Delete(const Anope::string &reason)
|
||||
{
|
||||
this->quit_reason = reason;
|
||||
this->quitting = true;
|
||||
FOREACH_MOD(OnServerQuit, (this));
|
||||
delete this;
|
||||
}
|
||||
@@ -315,6 +317,11 @@ bool Server::IsJuped() const
|
||||
return juped;
|
||||
}
|
||||
|
||||
bool Server::IsQuitting() const
|
||||
{
|
||||
return quitting;
|
||||
}
|
||||
|
||||
void Server::Notice(BotInfo *source, const Anope::string &message)
|
||||
{
|
||||
if (Config->UsePrivmsg && Config->DefPrivmsg)
|
||||
|
||||
Reference in New Issue
Block a user