From c0868b24ba3176c2323b797001853d505747b9d8 Mon Sep 17 00:00:00 2001 From: riking Date: Sat, 5 Oct 2013 14:55:34 -0700 Subject: [PATCH] Potential fix for loss of data due to SQL connection dropping The idea behind this change is to send a ping every hour, which is shorter than the driver's 'dead connection' threshold of 8 hours. As a side effect, this also will fix a subset of the situations where the MySQL server is restarted. --- .../nossr50/database/SQLDatabaseManager.java | 3 ++ .../database/SQLDatabaseKeepaliveTask.java | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/main/java/com/gmail/nossr50/runnables/database/SQLDatabaseKeepaliveTask.java diff --git a/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java b/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java index fa9352356..46e589aa5 100644 --- a/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java +++ b/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java @@ -24,6 +24,7 @@ import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.datatypes.skills.AbilityType; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.runnables.database.SQLReconnectTask; +import com.gmail.nossr50.runnables.database.SQLDatabaseKeepaliveTask; import com.gmail.nossr50.util.Misc; public final class SQLDatabaseManager implements DatabaseManager { @@ -51,6 +52,8 @@ public final class SQLDatabaseManager implements DatabaseManager { protected SQLDatabaseManager() { checkStructure(); + + new SQLDatabaseKeepaliveTask(this).runTaskTimerAsynchronously(mcMMO.p, 10, 60L * 60 * Misc.TICK_CONVERSION_FACTOR); } public void purgePowerlessUsers() { diff --git a/src/main/java/com/gmail/nossr50/runnables/database/SQLDatabaseKeepaliveTask.java b/src/main/java/com/gmail/nossr50/runnables/database/SQLDatabaseKeepaliveTask.java new file mode 100644 index 000000000..14ce54c11 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/runnables/database/SQLDatabaseKeepaliveTask.java @@ -0,0 +1,39 @@ +package com.gmail.nossr50.runnables.database; + +import java.lang.ref.WeakReference; + +import org.bukkit.scheduler.BukkitRunnable; + +import com.gmail.nossr50.database.SQLDatabaseManager; + +/** + * This task is in charge of sending a MySQL ping over the MySQL connection + * every hour to prevent the connection from timing out and losing players' + * data when they join. + *

+ * A WeakReference is used to keep the database instance, because + * {@link com.gmail.nossr50.commands.database.ConvertDatabaseCommand database + * conversion} may create a SQLDatabaseManager that will be thrown out. If a + * normal reference was used, the conversion would cause a combined data and + * resource leak through this task. + */ +public class SQLDatabaseKeepaliveTask extends BukkitRunnable { + WeakReference databaseInstance; + + public SQLDatabaseKeepaliveTask(SQLDatabaseManager dbman) { + databaseInstance = new WeakReference(dbman); + } + + public void run() { + SQLDatabaseManager dbman = databaseInstance.get(); + if (dbman != null) { + dbman.checkConnected(); + } + else { + // This happens when the database was started for a conversion, + // or discarded by its creator for any other reason. If this code + // was not present, we would leak the connection resources. + this.cancel(); + } + } +}