[#777] Added NetworkSettingManager

- This manager updates config in database if a server config file is
  updated on proxy server, and updates the config in database if the
  file is modified.
- Added a setting for the update check delay
This commit is contained in:
Rsl1122 2018-12-23 22:52:26 +02:00
parent cfc7f25a07
commit 0acf54eed5
7 changed files with 203 additions and 6 deletions

View File

@ -0,0 +1,177 @@
package com.djrapitops.plan.system.settings.network;
import com.djrapitops.plan.api.exceptions.EnableException;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.database.databases.Database;
import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.Config;
import com.djrapitops.plan.system.settings.config.ConfigReader;
import com.djrapitops.plan.system.settings.config.ConfigWriter;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.TimeSettings;
import com.djrapitops.plan.system.tasks.TaskSystem;
import com.djrapitops.plan.utilities.file.FileWatcher;
import com.djrapitops.plan.utilities.file.WatchedFile;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.logging.error.ErrorHandler;
import com.djrapitops.plugin.task.AbsRunnable;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* In charge of all configs on the network.
* <p>
* Performs the following tasks related to network configs:
* - File modification watching related to server configs
* - Database update operations related to server configs
* - File update operations from database related to server configs
*
* @author Rsl1122
*/
@Singleton
public class NetworkSettingManager {
private final PlanFiles files;
private final DBSystem dbSystem;
private final ServerInfo serverInfo;
private final TaskSystem taskSystem;
private PlanConfig config;
private ErrorHandler errorHandler;
private File serverSettingsFolder;
private FileWatcher watcher;
@Inject
public NetworkSettingManager(
PlanFiles files,
PlanConfig config,
DBSystem dbSystem,
ServerInfo serverInfo,
TaskSystem taskSystem,
ErrorHandler errorHandler
) {
this.files = files;
this.config = config;
this.dbSystem = dbSystem;
this.serverInfo = serverInfo;
this.taskSystem = taskSystem;
this.errorHandler = errorHandler;
}
public void enable() throws EnableException {
serverSettingsFolder = createServerSettingsFolder();
watcher = prepareFileWatcher();
watcher.start();
scheduleDBCheckTask();
}
public void disable() {
if (watcher != null) {
watcher.interrupt();
}
}
private FileWatcher prepareFileWatcher() {
FileWatcher fileWatcher = new FileWatcher(serverSettingsFolder, errorHandler);
File[] files = serverSettingsFolder.listFiles((dir, name) -> name.endsWith(".yml"));
if (files != null) {
for (File file : files) {
addFileToWatchList(fileWatcher, file);
}
}
return fileWatcher;
}
private void addFileToWatchList(FileWatcher fileWatcher, File file) {
try {
String fileName = file.getName();
String uuidString = fileName.substring(0, fileName.length() - 4);
UUID serverUUID = UUID.fromString(uuidString);
fileWatcher.addToWatchlist(new WatchedFile(file, () -> updateConfigInDB(file, serverUUID)));
} catch (IndexOutOfBoundsException | IllegalArgumentException ignore) {
/* Invalid file-name, ignored */
}
}
private void scheduleDBCheckTask() {
long checkPeriod = TimeAmount.toTicks(config.get(TimeSettings.CONFIG_UPDATE_INTERVAL), TimeUnit.MINUTES);
taskSystem.registerTask("Config Update DB Checker", new AbsRunnable() {
@Override
public void run() {
checkDBForNewConfigSettings();
}
}).runTaskTimerAsynchronously(checkPeriod, checkPeriod);
}
private File createServerSettingsFolder() throws EnableException {
try {
File serverConfigFolder = files.getFileFromPluginFolder("serverConfiguration");
Files.createDirectories(serverConfigFolder.toPath());
return serverConfigFolder;
} catch (IOException e) {
throw new EnableException("Could not initialize NetworkSettingManager: " + e.getMessage(), e);
}
}
private File getServerConfigFile(UUID serverUUID) {
return new File(serverSettingsFolder, serverUUID + ".yml");
}
private void checkDBForNewConfigSettings() {
Database database = dbSystem.getDatabase();
List<UUID> serverUUIDs = database.fetch().getServerUUIDs();
serverUUIDs.remove(serverInfo.getServerUUID());
for (UUID serverUUID : serverUUIDs) {
checkDBForNewConfigSettings(database, serverUUID);
}
}
private void checkDBForNewConfigSettings(Database database, UUID serverUUID) {
File configFile = getServerConfigFile(serverUUID);
long lastModified = configFile.exists() ? configFile.lastModified() : -1;
Optional<Config> foundConfig = database.fetch().getNewConfig(lastModified, serverUUID);
if (foundConfig.isPresent()) {
try {
new ConfigWriter(configFile.toPath()).write(foundConfig.get());
addFileToWatchList(watcher, configFile);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
private void updateConfigInDB(File file, UUID serverUUID) {
if (!file.exists()) {
return;
}
Database database = dbSystem.getDatabase();
try {
Config config = new ConfigReader(file.toPath()).read();
database.save().saveConfig(serverUUID, config);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}

View File

@ -22,6 +22,7 @@ public class TimeSettings {
public static final Setting<Long> ANALYSIS_REFRESH_PERIOD = new TimeSetting("Time.Periodic_tasks.Analysis_refresh_every"); public static final Setting<Long> ANALYSIS_REFRESH_PERIOD = new TimeSetting("Time.Periodic_tasks.Analysis_refresh_every");
public static final Setting<Long> CLEAN_CACHE_PERIOD = new TimeSetting("Time.Periodic_tasks.Clean_caches_every"); public static final Setting<Long> CLEAN_CACHE_PERIOD = new TimeSetting("Time.Periodic_tasks.Clean_caches_every");
public static final Setting<Long> CLEAN_DATABASE_PERIOD = new TimeSetting("Time.Periodic_tasks.Clean_Database_every"); public static final Setting<Long> CLEAN_DATABASE_PERIOD = new TimeSetting("Time.Periodic_tasks.Clean_Database_every");
public static final Setting<Long> CONFIG_UPDATE_INTERVAL = new TimeSetting("Time.Periodic_tasks.Check_DB_for_server_config_files_every");
private TimeSettings() { private TimeSettings() {
/* static variable class */ /* static variable class */

View File

@ -43,7 +43,7 @@ public abstract class TaskSystem implements SubSystem {
return registerTask(taskName, runnable); return registerTask(taskName, runnable);
} }
protected PluginRunnable registerTask(String name, AbsRunnable runnable) { public PluginRunnable registerTask(String name, AbsRunnable runnable) {
return runnableFactory.create(name, runnable); return runnableFactory.create(name, runnable);
} }

View File

@ -23,8 +23,8 @@ import com.djrapitops.plugin.utilities.Verify;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.*; import java.nio.file.*;
import java.util.ArrayList; import java.util.HashSet;
import java.util.List; import java.util.Set;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
@ -40,16 +40,16 @@ public class FileWatcher extends Thread {
private volatile boolean running; private volatile boolean running;
private Path watchedPath; private Path watchedPath;
private List<WatchedFile> watchedFiles; private Set<WatchedFile> watchedFiles;
public FileWatcher(File folder, ErrorHandler errorHandler) { public FileWatcher(File folder, ErrorHandler errorHandler) {
this(folder, errorHandler, new ArrayList<>()); this(folder, errorHandler, new HashSet<>());
} }
public FileWatcher( public FileWatcher(
File folder, File folder,
ErrorHandler errorHandler, ErrorHandler errorHandler,
List<WatchedFile> watchedFiles Set<WatchedFile> watchedFiles
) { ) {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.running = false; this.running = false;
@ -61,6 +61,7 @@ public class FileWatcher extends Thread {
} }
public void addToWatchlist(WatchedFile watchedFile) { public void addToWatchlist(WatchedFile watchedFile) {
watchedFiles.remove(watchedFile);
watchedFiles.add(watchedFile); watchedFiles.add(watchedFile);
} }

View File

@ -20,6 +20,7 @@ import com.djrapitops.plan.utilities.java.VoidFunction;
import java.io.File; import java.io.File;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Objects;
/** /**
* File with a consumer that is called if the file is modified. * File with a consumer that is called if the file is modified.
@ -41,4 +42,17 @@ public class WatchedFile {
onChange.apply(); onChange.apply();
} }
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WatchedFile that = (WatchedFile) o;
return Objects.equals(file, that.file);
}
@Override
public int hashCode() {
return Objects.hash(file);
}
} }

View File

@ -84,6 +84,8 @@ Time:
Remove_inactive_player_data_after: 180 Remove_inactive_player_data_after: 180
Unit: DAYS Unit: DAYS
Periodic_tasks: Periodic_tasks:
Check_DB_for_server_config_files_every: 1
Unit: MINUTES
Clean_caches_every: 10 Clean_caches_every: 10
Unit: MINUTES Unit: MINUTES
Clean_Database_every: 1 Clean_Database_every: 1

View File

@ -91,6 +91,8 @@ Time:
Periodic_tasks: Periodic_tasks:
Analysis_refresh_every: 60 Analysis_refresh_every: 60
Unit: MINUTES Unit: MINUTES
Check_DB_for_server_config_files_every: 1
Unit: MINUTES
Clean_caches_every: 10 Clean_caches_every: 10
Unit: MINUTES Unit: MINUTES
Clean_Database_every: 1 Clean_Database_every: 1