Skip to content
This repository has been archived by the owner on Dec 5, 2021. It is now read-only.

Commit

Permalink
Revert new DatabaseManager
Browse files Browse the repository at this point in the history
Revert "Always do release"

This reverts commit a049eb6

Revert "Change visibility in signal and await method"

This reverts commit b496cd4

Revert "Fix missing code by merge"

This reverts commit edb375e

Revert "Fix IllegalMonitorStateException"

This reverts commit 8f4d83c

Revert "Optimize getConnection logic to await-and-signal mode"

This reverts commit a9eff9d

Revert "#575 Handle ALL SQL operation in DatabaseManager to prevent connection competing issue"

This reverts commit 37a2e90
  • Loading branch information
Ghost-chu committed Oct 1, 2020
1 parent f4041d7 commit 93c4d1d
Show file tree
Hide file tree
Showing 17 changed files with 585 additions and 483 deletions.
42 changes: 25 additions & 17 deletions src/main/java/org/maxgamer/quickshop/QuickShop.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ public class QuickShop extends JavaPlugin {
private BootError bootError;
@Getter
private CommandManager commandManager;
/**
* The database for storing all our data for persistence
*/
@Getter
private Database database;
/**
* Contains all SQL tasks
*/
Expand Down Expand Up @@ -559,6 +564,16 @@ public void onDisable() {
// ignore, we didn't care that
}

Util.debugLog("Unregistering tasks...");
// if (itemWatcherTask != null)
// itemWatcherTask.cancel();
if (logWatcher != null) {
logWatcher.close(); // Closes the file
}
/* Unload UpdateWatcher */
if (this.updateWatcher != null) {
this.updateWatcher.uninit();
}
Util.debugLog("Cleaning up resources and unloading all shops...");
/* Remove all display items, and any dupes we can find */
if (shopManager != null) {
Expand All @@ -569,24 +584,16 @@ public void onDisable() {
if (this.getDatabaseManager() != null) {
this.getDatabaseManager().unInit();
}

/* Close Database */
if (database != null) {
this.database.close();
}
// this.reloadConfig();
Util.debugLog("Calling integrations...");
this.integrationHelper.callIntegrationsUnload(IntegrateStage.onUnloadAfter);
this.compatibilityTool.clear();
new HashSet<>(this.integrationHelper.getIntegrations()).forEach(integratedPlugin -> this.integrationHelper.unregister(integratedPlugin));

Util.debugLog("Unregistering tasks...");
// if (itemWatcherTask != null)
// itemWatcherTask.cancel();
if (logWatcher != null) {
logWatcher.close(); // Closes the file
}
/* Unload UpdateWatcher */
if (this.updateWatcher != null) {
this.updateWatcher.uninit();
}

Util.debugLog("Cleanup tasks...");
try {
Bukkit.getScheduler().cancelTasks(this);
Expand Down Expand Up @@ -852,7 +859,7 @@ private void registerIntegrations() {
private boolean setupDatabase() {
try {
ConfigurationSection dbCfg = getConfig().getConfigurationSection("database");
AbstractDatabaseCore dbCore;
DatabaseCore dbCore;
if (Objects.requireNonNull(dbCfg).getBoolean("mysql")) {
// MySQL database - Required database be created first.
dbPrefix = dbCfg.getString("prefix");
Expand All @@ -870,10 +877,11 @@ private boolean setupDatabase() {
// SQLite database - Doing this handles file creation
dbCore = new SQLiteCore(this, new File(this.getDataFolder(), "shops.db"));
}
this.databaseManager = new DatabaseManager(this, ServiceInjector.getDatabaseCore(dbCore));
this.database = new Database(ServiceInjector.getDatabaseCore(dbCore));
this.databaseManager = new DatabaseManager(this, this.database);
// Make the database up to date
this.databaseHelper = new DatabaseHelper(this, this.databaseManager);
} catch (DatabaseManager.ConnectionException e) {
this.databaseHelper = new DatabaseHelper(this, this.database, this.databaseManager);
} catch (Database.ConnectionException e) {
e.printStackTrace();
if (setupDBonEnableding) {
bootError = BuiltInSolution.databaseError();
Expand Down Expand Up @@ -937,7 +945,7 @@ private void submitMeritcs() {
String useEnhanceShopProtect = String.valueOf(getConfig().getBoolean("shop.enchance-shop-protect"));
String useOngoingFee = String.valueOf(getConfig().getBoolean("shop.ongoing-fee.enable"));
String disableDebugLogger = String.valueOf(getConfig().getBoolean("disable-debuglogger"));
String databaseType = this.getDatabaseManager().getDatabase().getName();
String databaseType = this.getDatabase().getCore().getName();
String displayType = DisplayItem.getNowUsing().name();
String itemMatcherType = this.getItemMatcher().getName();
String useStackItem = String.valueOf(this.isAllowStack());
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/org/maxgamer/quickshop/ServiceInjector.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*
* This file is a part of project QuickShop, the name is ServiceInjector.java
* Copyright (C) Ghost_chu <https://github.com/Ghost-chu>
* Copyright (C) PotatoCraft Studio and contributors
*
* This program is free software: you can redistribute it and/or modify it
Expand All @@ -24,7 +23,7 @@
import org.bukkit.plugin.RegisteredServiceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.maxgamer.quickshop.database.AbstractDatabaseCore;
import org.maxgamer.quickshop.database.DatabaseCore;
import org.maxgamer.quickshop.economy.EconomyCore;
import org.maxgamer.quickshop.util.language.game.GameLanguage;
import org.maxgamer.quickshop.util.matcher.item.ItemMatcher;
Expand Down Expand Up @@ -60,9 +59,9 @@ public class ServiceInjector {
}
}

public static @NotNull AbstractDatabaseCore getDatabaseCore(@NotNull AbstractDatabaseCore def) {
@Nullable RegisteredServiceProvider<? extends AbstractDatabaseCore> registeredServiceProvider =
Bukkit.getServicesManager().getRegistration(AbstractDatabaseCore.class);
public static @NotNull DatabaseCore getDatabaseCore(@NotNull DatabaseCore def) {
@Nullable RegisteredServiceProvider<? extends DatabaseCore> registeredServiceProvider =
Bukkit.getServicesManager().getRegistration(DatabaseCore.class);
if (registeredServiceProvider == null) {
return def;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*
* This file is a part of project QuickShop, the name is SubCommand_Convert.java
* Copyright (C) Ghost_chu <https://github.com/Ghost-chu>
* Copyright (C) PotatoCraft Studio and contributors
*
* This program is free software: you can redistribute it and/or modify it
Expand Down Expand Up @@ -65,7 +64,7 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String commandLabe
return;
}
if (cmdArg[0].equalsIgnoreCase("mysql")) {
if (plugin.getDatabaseManager().getDatabase() instanceof MySQLCore) {
if (plugin.getDatabase().getCore() instanceof MySQLCore) {
sender.sendMessage(ChatColor.RED + "Please switch to SQLite before converting to MySQL.");
return;
}
Expand All @@ -76,22 +75,24 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String commandLabe
String port = dbCfg.getString("port");
String databaseStr = dbCfg.getString("database");
boolean useSSL = dbCfg.getBoolean("usessl");
AbstractDatabaseCore dbCore = new MySQLCore(plugin, Objects.requireNonNull(host, "MySQL host can't be null"), Objects.requireNonNull(user, "MySQL username can't be null"), Objects.requireNonNull(pass, "MySQL password can't be null"), Objects.requireNonNull(databaseStr, "MySQL database name can't be null"), Objects.requireNonNull(port, "MySQL port can't be null"), useSSL);
DatabaseManager databaseManager = new DatabaseManager(QuickShop.getInstance(), dbCore);
DatabaseCore dbCore = new MySQLCore(plugin, Objects.requireNonNull(host, "MySQL host can't be null"), Objects.requireNonNull(user, "MySQL username can't be null"), Objects.requireNonNull(pass, "MySQL password can't be null"), Objects.requireNonNull(databaseStr, "MySQL database name can't be null"), Objects.requireNonNull(port, "MySQL port can't be null"), useSSL);
Database database = new Database(dbCore);
DatabaseManager databaseManager = new DatabaseManager(QuickShop.getInstance(), database);
sender.sendMessage(ChatColor.GREEN + "Converting...");
this.transferShops(new DatabaseHelper(plugin, databaseManager), sender);
this.transferShops(new DatabaseHelper(plugin, database, databaseManager), sender);
databaseManager.unInit();
sender.sendMessage(ChatColor.GREEN + "All done, please edit config.yml to mysql to apply changes.");

} else if (cmdArg[0].equalsIgnoreCase("sqlite")) {
if (plugin.getDatabaseManager().getDatabase() instanceof SQLiteCore) {
if (plugin.getDatabase().getCore() instanceof SQLiteCore) {
sender.sendMessage(ChatColor.GREEN + "Please switch to MySQL before converting to SQLite.");
return;
}
AbstractDatabaseCore core = new SQLiteCore(plugin, new File(plugin.getDataFolder(), "shops.db"));
DatabaseManager databaseManager = new DatabaseManager(QuickShop.getInstance(), core);
DatabaseCore core = new SQLiteCore(plugin, new File(plugin.getDataFolder(), "shops.db"));
Database database = new Database(core);
DatabaseManager databaseManager = new DatabaseManager(QuickShop.getInstance(), database);
sender.sendMessage(ChatColor.GREEN + "Converting...");
this.transferShops(new DatabaseHelper(plugin, databaseManager), sender);
this.transferShops(new DatabaseHelper(plugin, database, databaseManager), sender);
databaseManager.unInit();
sender.sendMessage(ChatColor.GREEN + "All done, please edit config.yml to sqlite to apply changes.");

Expand Down
76 changes: 76 additions & 0 deletions src/main/java/org/maxgamer/quickshop/database/BufferStatement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* This file is a part of project QuickShop, the name is BufferStatement.java
* Copyright (C) PotatoCraft Studio and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package org.maxgamer.quickshop.database;

import org.jetbrains.annotations.NotNull;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;

public class BufferStatement {

@NotNull
private final String query;

@NotNull
private final Object[] values;

/**
* Represents a PreparedStatement in a state before preparing it (E.g. No file I/O Required)
*
* @param query The query to execute. E.g. INSERT INTO accounts (user, passwd) VALUES (?, ?)
* @param values The values to replace ? with in query. These are in order.
*/
public BufferStatement(@NotNull String query, @NotNull Object... values) {
this.query = query;
this.values = values;
}

/**
* @return A string representation of this statement. Returns "Query: " + query + ", values: " +
* Arrays.toString(values).
*/
@Override
public String toString() {
return "Query: " + query + ", values: " + Arrays.toString(values);
}

/**
* Returns a prepared statement using the given connection. Will try to return an empty statement
* if something went wrong. If that fails, returns null.
*
* <p>This method escapes everything automatically.
*
* @param con The connection to prepare this on using con.prepareStatement(..)
* @return The prepared statement, ready for execution.
* @throws SQLException Throw exception when failed to execute something in SQL
*/
PreparedStatement prepareStatement(@NotNull Connection con) throws SQLException {
PreparedStatement ps;
ps = con.prepareStatement(query);
for (int i = 1; i <= values.length; i++) {
ps.setObject(i, values[i - 1]);
}
return ps;
}

}
153 changes: 153 additions & 0 deletions src/main/java/org/maxgamer/quickshop/database/Database.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* This file is a part of project QuickShop, the name is Database.java
* Copyright (C) PotatoCraft Studio and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package org.maxgamer.quickshop.database;

import org.jetbrains.annotations.NotNull;

import java.sql.*;

public class Database {

@NotNull
private final DatabaseCore core;

/**
* Creates a new database and validates its connection.
*
* <p>If the connection is invalid, this will throw a ConnectionException.
*
* @param core The core for the database, either MySQL or SQLite.
* @throws ConnectionException If the connection was invalid
*/
public Database(@NotNull DatabaseCore core) throws ConnectionException {
try {
try {
if (!core.getConnection().isValid(30)) {
throw new ConnectionException("The database does not appear to be valid!");
}
} catch (AbstractMethodError ignored) {
// You don't need to validate this core.
}
} catch (SQLException e) {
throw new ConnectionException(e.getMessage());
}
this.core = core;
}

/**
* Closes the database
*/
public void close() {
this.core.close();
}

/**
* Executes the given statement either immediately, or soon.
*
* @param query The query
* @param objs The string values for each ? in the given query.
*/
public void execute(@NotNull String query, @NotNull Object... objs) {
BufferStatement bs = new BufferStatement(query, objs);
core.queue(bs);
}

/**
* Returns true if the given table has the given column
*
* @param table The table
* @param column The column
* @return True if the given table has the given column
* @throws SQLException If the database isn't connected
*/
public boolean hasColumn(@NotNull String table, @NotNull String column) throws SQLException {
if (!hasTable(table)) {
return false;
}
String query = "SELECT * FROM " + table + " LIMIT 1";
try {
PreparedStatement ps = this.getConnection().prepareStatement(query);
ResultSet rs = ps.executeQuery();
ResultSetMetaData metaData = rs.getMetaData();
for (int i = 1; i <= metaData.getColumnCount(); i++) {
if (metaData.getColumnLabel(i).equals(column)) {
return true;
}
}
rs.close();
} catch (SQLException e) {
return false;
}
return false; // Uh, wtf.
}

/**
* Returns true if the table exists
*
* @param table The table to check for
* @return True if the table is found
* @throws SQLException Throw exception when failed execute somethins on SQL
*/
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
boolean hasTable(@NotNull String table) throws SQLException {
ResultSet rs = getConnection().getMetaData().getTables(null, null, "%", null);
while (rs.next()) {
if (table.equalsIgnoreCase(rs.getString("TABLE_NAME"))) {
rs.close();
return true;
}
}
rs.close();
return false;
}

/**
* Fetches the connection to this database for querying. Try to avoid doing this in the main
* thread.
*
* @return Fetches the connection to this database for querying.
*/
public Connection getConnection() {
return core.getConnection();
}

/**
* Returns the database core object, that this database runs on.
*
* @return the database core object, that this database runs on.
*/
@NotNull
public DatabaseCore getCore() {
return core;
}

/**
* Represents a connection error, generally when the server can't connect to MySQL or something.
*/
public static final class ConnectionException extends Exception {
private static final long serialVersionUID = 8348749992936357317L;

private ConnectionException(String msg) {
super(msg);
}

}

}
Loading

0 comments on commit 93c4d1d

Please sign in to comment.