Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIconTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.StorePluginTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.StoreTabInformationTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreProviderTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreTableProviderTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.*;
import com.djrapitops.plan.extension.table.Table;
import com.djrapitops.plan.identification.ServerInfo;
Expand Down Expand Up @@ -70,6 +68,7 @@ public class DataValueGatherer {
private final ErrorLogger errorLogger;

private final Set<ExtensionMethod> brokenMethods;
private final ExtensionMetadataStorage metadataStorage;

public DataValueGatherer(
ExtensionWrapper extension,
Expand All @@ -86,6 +85,7 @@ public DataValueGatherer(
this.errorLogger = errorLogger;

this.brokenMethods = new HashSet<>();
this.metadataStorage = new ExtensionMetadataStorage();
}

public boolean shouldSkipEvent(CallEvents event) {
Expand Down Expand Up @@ -477,8 +477,7 @@ private void storeBoolean(Parameters parameters, Conditions conditions, BooleanD
}

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StoreServerBooleanResultTransaction(information, parameters, value));
}

Expand All @@ -488,8 +487,7 @@ private void storeNumber(Parameters parameters, Conditions conditions, NumberDat
if (value == null) return;

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StoreServerNumberResultTransaction(information, parameters, value));
}

Expand All @@ -500,8 +498,7 @@ private void storeDouble(Parameters parameters, Conditions conditions, DoubleDat
if (value == null) return;

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StoreServerDoubleResultTransaction(information, parameters, value));
}

Expand All @@ -511,8 +508,7 @@ private void storeString(Parameters parameters, Conditions conditions, StringDat
if (value == null) return;

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StoreServerStringResultTransaction(information, parameters, value));
}

Expand All @@ -522,8 +518,7 @@ private void storeComponent(Parameters parameters, Conditions conditions, Compon
if (value == null) return;

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StoreServerStringResultTransaction(information, parameters, value));
}

Expand All @@ -533,10 +528,7 @@ private void storeTable(Parameters parameters, Conditions conditions, TableDataV
if (value == null) return;

Database db = dbSystem.getDatabase();
for (Icon icon : value.getIcons()) {
if (icon != null) db.executeTransaction(new StoreIconTransaction(icon));
}
db.executeTransaction(new StoreTableProviderTransaction(information, parameters, value));
metadataStorage.storeTableProvider(db, information, parameters, value);
db.executeTransaction(new StoreServerTableResultTransaction(information, parameters, value));
}

Expand All @@ -551,8 +543,7 @@ private void storePlayerBoolean(Parameters parameters, Conditions conditions, Bo
}

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StorePlayerBooleanResultTransaction(information, parameters, value));
}

Expand All @@ -562,8 +553,7 @@ private void storePlayerNumber(Parameters parameters, Conditions conditions, Num
if (value == null) return;

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StorePlayerNumberResultTransaction(information, parameters, value));
}

Expand All @@ -573,8 +563,7 @@ private void storePlayerDouble(Parameters parameters, Conditions conditions, Dou
if (value == null) return;

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StorePlayerDoubleResultTransaction(information, parameters, value));
}

Expand All @@ -584,8 +573,7 @@ private void storePlayerString(Parameters parameters, Conditions conditions, Str
if (value == null) return;

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StorePlayerStringResultTransaction(information, parameters, value));
}

Expand All @@ -595,8 +583,7 @@ private void storePlayerComponent(Parameters parameters, Conditions conditions,
if (value == null) return;

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StorePlayerStringResultTransaction(information, parameters, value));
}

Expand All @@ -606,8 +593,7 @@ private void storePlayerGroups(Parameters parameters, Conditions conditions, Gro
if (value == null) return;

Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
metadataStorage.storeProvider(db, information, parameters);
db.executeTransaction(new StorePlayerGroupsResultTransaction(information, parameters, value));
}

Expand All @@ -617,10 +603,7 @@ private void storePlayerTable(Parameters parameters, Conditions conditions, Tabl
if (value == null) return;

Database db = dbSystem.getDatabase();
for (Icon icon : value.getIcons()) {
if (icon != null) db.executeTransaction(new StoreIconTransaction(icon));
}
db.executeTransaction(new StoreTableProviderTransaction(information, parameters, value));
metadataStorage.storeTableProvider(db, information, parameters, value);
db.executeTransaction(new StorePlayerTableResultTransaction(information, parameters, value));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan 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 Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.extension.implementation.providers.gathering;

import com.djrapitops.plan.extension.icon.Icon;
import com.djrapitops.plan.extension.implementation.ProviderInformation;
import com.djrapitops.plan.extension.implementation.providers.Parameters;
import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIconTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreProviderTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreTableProviderTransaction;
import com.djrapitops.plan.extension.table.Table;
import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.transactions.Transaction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
* Avoids writing unchanged extension metadata for every gathered value.
*/
class ExtensionMetadataStorage {

private final Map<MetadataKey, MetadataFingerprint> storedMetadata = new HashMap<>();

public synchronized void storeProvider(
Database database,
ProviderInformation information,
Parameters parameters
) {
MetadataKey key = new MetadataKey(false, parameters.getServerUUID(), information.getPluginName(), information.getName());
MetadataFingerprint fingerprint = MetadataFingerprint.forProvider(information);
if (fingerprint.equals(storedMetadata.get(key))) return;

storedMetadata.put(key, fingerprint);
StoreProviderTransaction providerTransaction = new StoreProviderTransaction(information, parameters);
try {
database.executeTransaction(new StoreIconTransaction(information.getIcon()));
invalidateIfNotStored(database.executeTransaction(providerTransaction), providerTransaction, key, fingerprint);
} catch (RuntimeException executionFailure) {
storedMetadata.remove(key, fingerprint);
throw executionFailure;
}
}

public synchronized void storeTableProvider(
Database database,
ProviderInformation information,
Parameters parameters,
Table table
) {
MetadataKey key = new MetadataKey(true, parameters.getServerUUID(), information.getPluginName(), information.getName());
MetadataFingerprint fingerprint = MetadataFingerprint.forTableProvider(information, parameters, table);
if (fingerprint.equals(storedMetadata.get(key))) return;

storedMetadata.put(key, fingerprint);
StoreTableProviderTransaction providerTransaction = new StoreTableProviderTransaction(information, parameters, table);
try {
Icon[] icons = table.getIcons();
for (int i = 0; i < table.getMaxColumnSize(); i++) {
database.executeTransaction(new StoreIconTransaction(icons[i]));
}
invalidateIfNotStored(database.executeTransaction(providerTransaction), providerTransaction, key, fingerprint);
} catch (RuntimeException executionFailure) {
storedMetadata.remove(key, fingerprint);
throw executionFailure;
}
}

private void invalidateIfNotStored(
CompletableFuture<?> completion,
Transaction transaction,
MetadataKey key,
MetadataFingerprint fingerprint
) {
completion.whenComplete((result, failure) -> {
if (failure != null || !transaction.wasExecuted()) {
synchronized (ExtensionMetadataStorage.this) {
storedMetadata.remove(key, fingerprint);
}
}
});
}

private static final class MetadataKey {
private final boolean tableProvider;
private final ServerUUID serverUUID;
private final String pluginName;
private final String providerName;

private MetadataKey(boolean tableProvider, ServerUUID serverUUID, String pluginName, String providerName) {
this.tableProvider = tableProvider;
this.serverUUID = serverUUID;
this.pluginName = pluginName;
this.providerName = providerName;
}

@Override
public boolean equals(Object other) {
if (this == other) return true;
if (!(other instanceof MetadataKey)) return false;
MetadataKey that = (MetadataKey) other;
return tableProvider == that.tableProvider &&
Objects.equals(serverUUID, that.serverUUID) &&
Objects.equals(pluginName, that.pluginName) &&
Objects.equals(providerName, that.providerName);
}

@Override
public int hashCode() {
return Objects.hash(tableProvider, serverUUID, pluginName, providerName);
}
}

private static final class MetadataFingerprint {
private final List<Object> values;

private MetadataFingerprint(List<Object> values) {
this.values = values;
}

private static MetadataFingerprint forProvider(ProviderInformation information) {
return new MetadataFingerprint(providerInformation(information));
}

private static MetadataFingerprint forTableProvider(
ProviderInformation information,
Parameters parameters,
Table table
) {
List<Object> values = providerInformation(information);
values.add(parameters.getMethodType());
values.addAll(Arrays.asList(table.getColumns().clone()));
Icon[] icons = table.getIcons();
for (int i = 0; i < table.getMaxColumnSize(); i++) {
addIcon(values, icons[i]);
}
values.addAll(Arrays.asList(table.getTableColumnFormats().clone()));
return new MetadataFingerprint(values);
}

private static List<Object> providerInformation(ProviderInformation information) {
List<Object> values = new ArrayList<>();
values.add(information.getPluginName());
values.add(information.getName());
values.add(information.getText());
values.add(information.getDescription().orElse(null));
values.add(information.getPriority());
addIcon(values, information.getIcon());
values.add(information.isShownInPlayersTable());
values.add(information.getTab().orElse(null));
values.add(information.getCondition().orElse(null));
values.add(information.isHidden());
values.add(information.getProvidedCondition());
values.add(information.getFormatType().orElse(null));
values.add(information.isPlayerName());
values.add(information.getTableColor());
values.add(information.isPercentage());
values.add(information.isComponent());
return values;
}

private static void addIcon(List<Object> values, Icon icon) {
values.add(icon.getFamily());
values.add(icon.getName());
values.add(icon.getColor());
}

@Override
public boolean equals(Object other) {
if (this == other) return true;
if (!(other instanceof MetadataFingerprint)) return false;
MetadataFingerprint that = (MetadataFingerprint) other;
return values.equals(that.values);
}

@Override
public int hashCode() {
return values.hashCode();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public abstract class Transaction {
protected DBType dbType;
protected boolean success;
protected int attempts;
private boolean executed;
private SQLDB db;
private Connection connection;
private Savepoint savepoint;
Expand Down Expand Up @@ -85,6 +86,7 @@ public void executeTransaction(SQLDB db) {
}
performOperations();
if (connection != null) connection.commit();
executed = true;
}
success = true;
} catch (SQLException statementFail) {
Expand Down Expand Up @@ -287,6 +289,10 @@ public boolean wasSuccessful() {
return success;
}

public boolean wasExecuted() {
return executed;
}

public boolean dbIsNotUnderHeavyLoad() {
return !db.isUnderHeavyLoad() && !db.shouldDropUnimportantTransactions();
}
Expand Down Expand Up @@ -317,4 +323,4 @@ public enum IsolationLevel {
UNCHANGED,
READ_COMMITTED
}
}
}
Loading