Merge pull request #173 from GravitLauncher/threadPool

Thread pool
This commit is contained in:
Gravit 2019-02-15 00:08:45 +07:00 committed by GitHub
commit ef3544f268
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 5 additions and 314 deletions

View file

@ -41,9 +41,6 @@ public static void registerHandlers() {
if (!registredHandl) { if (!registredHandl) {
registerHandler("null", NullAuthHandler.class); registerHandler("null", NullAuthHandler.class);
registerHandler("memory", MemoryAuthHandler.class); registerHandler("memory", MemoryAuthHandler.class);
// Auth handler that doesn't do nothing :D
registerHandler("binaryFile", BinaryFileAuthHandler.class);
registerHandler("mysql", MySQLAuthHandler.class); registerHandler("mysql", MySQLAuthHandler.class);
registredHandl = true; registredHandl = true;
} }

View file

@ -1,37 +0,0 @@
package ru.gravit.launchserver.auth.handler;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.utils.helper.IOHelper;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public final class BinaryFileAuthHandler extends FileAuthHandler {
@Override
protected void readAuthFile() throws IOException {
try (HInput input = new HInput(IOHelper.newInput(file))) {
int count = input.readLength(0);
for (int i = 0; i < count; i++) {
UUID uuid = input.readUUID();
Entry entry = new Entry(input);
addAuth(uuid, entry);
}
}
}
@Override
protected void writeAuthFileTmp() throws IOException {
Set<Map.Entry<UUID, Entry>> entrySet = entrySet();
try (HOutput output = new HOutput(IOHelper.newOutput(fileTmp))) {
output.writeLength(entrySet.size(), 0);
for (Map.Entry<UUID, Entry> entry : entrySet) {
output.writeUUID(entry.getKey());
entry.getValue().write(output);
}
}
}
}

View file

@ -1,233 +0,0 @@
package ru.gravit.launchserver.auth.handler;
import ru.gravit.launcher.profiles.PlayerProfile;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launcher.serialize.stream.StreamObject;
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
import ru.gravit.utils.helper.*;
import java.io.IOException;
import java.nio.file.Path;
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public abstract class FileAuthHandler extends AuthHandler {
public static final class Entry extends StreamObject {
private String username;
private String accessToken;
private String serverID;
public Entry(HInput input) throws IOException {
username = VerifyHelper.verifyUsername(input.readString(64));
if (input.readBoolean()) {
accessToken = SecurityHelper.verifyToken(input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH));
if (input.readBoolean())
serverID = VerifyHelper.verifyServerID(input.readASCII(41));
}
}
public Entry(String username) {
this.username = VerifyHelper.verifyUsername(username);
}
public Entry(String username, String accessToken, String serverID) {
this(username);
if (accessToken == null && serverID != null)
throw new IllegalArgumentException("Can't set access token while server ID is null");
// Set and verify access token
this.accessToken = accessToken == null ? null : SecurityHelper.verifyToken(accessToken);
this.serverID = serverID == null ? null : VerifyHelper.verifyServerID(serverID);
}
private void auth(String username, String accessToken) {
this.username = username; // Update username case
this.accessToken = accessToken;
serverID = null;
}
private boolean checkServer(String username, String serverID) {
return username.equals(this.username) && serverID.equals(this.serverID);
}
public String getAccessToken() {
return accessToken;
}
public String getServerID() {
return serverID;
}
public String getUsername() {
return username;
}
private boolean joinServer(String username, String accessToken, String serverID) {
if (!username.equals(this.username) || !accessToken.equals(this.accessToken))
return false; // Username or access token mismatch
// Update server ID
this.serverID = serverID;
return true;
}
@Override
public void write(HOutput output) throws IOException {
output.writeString(username, 64);
output.writeBoolean(accessToken != null);
if (accessToken != null) {
output.writeASCII(accessToken, -SecurityHelper.TOKEN_STRING_LENGTH);
output.writeBoolean(serverID != null);
if (serverID != null)
output.writeASCII(serverID, 41);
}
}
}
public Path file;
public Path fileTmp;
public boolean offlineUUIDs;
// Instance
private final SecureRandom random = SecurityHelper.newRandom();
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
// Storage
private final Map<UUID, Entry> entryMap = new HashMap<>(256);
private final Map<String, UUID> usernamesMap = new HashMap<>(256);
protected final void addAuth(UUID uuid, Entry entry) {
lock.writeLock().lock();
try {
Entry previous = entryMap.put(uuid, entry);
if (previous != null)
usernamesMap.remove(CommonHelper.low(previous.username));
usernamesMap.put(CommonHelper.low(entry.username), uuid);
} finally {
lock.writeLock().unlock();
}
}
@Override
public final UUID auth(AuthProviderResult authResult) {
lock.writeLock().lock();
try {
UUID uuid = usernameToUUID(authResult.username);
Entry entry = entryMap.get(uuid);
// Not registered? Fix it!
if (entry == null) {
entry = new Entry(authResult.username);
// Generate UUID
uuid = genUUIDFor(authResult.username);
entryMap.put(uuid, entry);
usernamesMap.put(CommonHelper.low(authResult.username), uuid);
}
// Authenticate
entry.auth(authResult.username, authResult.accessToken);
return uuid;
} finally {
lock.writeLock().unlock();
}
}
@Override
public final UUID checkServer(String username, String serverID) {
lock.readLock().lock();
try {
UUID uuid = usernameToUUID(username);
Entry entry = entryMap.get(uuid);
// Check server (if has such account of course)
return entry != null && entry.checkServer(username, serverID) ? uuid : null;
} finally {
lock.readLock().unlock();
}
}
@Override
public final void close() throws IOException {
lock.readLock().lock();
try {
LogHelper.info("Writing auth handler file (%d entries)", entryMap.size());
writeAuthFileTmp();
IOHelper.move(fileTmp, file);
} finally {
lock.readLock().unlock();
}
}
protected final Set<Map.Entry<UUID, Entry>> entrySet() {
return Collections.unmodifiableMap(entryMap).entrySet();
}
private UUID genUUIDFor(String username) {
if (offlineUUIDs) {
UUID md5UUID = PlayerProfile.offlineUUID(username);
if (!entryMap.containsKey(md5UUID))
return md5UUID;
LogHelper.warning("Offline UUID collision, using random: '%s'", username);
}
// Pick random UUID
UUID uuid;
do
uuid = new UUID(random.nextLong(), random.nextLong());
while (entryMap.containsKey(uuid));
return uuid;
}
@Override
public final boolean joinServer(String username, String accessToken, String serverID) {
lock.writeLock().lock();
try {
Entry entry = entryMap.get(usernameToUUID(username));
return entry != null && entry.joinServer(username, accessToken, serverID);
} finally {
lock.writeLock().unlock();
}
}
protected abstract void readAuthFile() throws IOException;
@Override
public final UUID usernameToUUID(String username) {
lock.readLock().lock();
try {
return usernamesMap.get(CommonHelper.low(username));
} finally {
lock.readLock().unlock();
}
}
@Override
public final String uuidToUsername(UUID uuid) {
lock.readLock().lock();
try {
Entry entry = entryMap.get(uuid);
return entry == null ? null : entry.username;
} finally {
lock.readLock().unlock();
}
}
protected abstract void writeAuthFileTmp() throws IOException;
}

View file

@ -71,8 +71,6 @@ public void start(String... args) throws Throwable {
throw new IllegalStateException("Launcher has been already started"); throw new IllegalStateException("Launcher has been already started");
Launcher.modulesManager.initModules(); Launcher.modulesManager.initModules();
runtimeProvider.preLoad(); runtimeProvider.preLoad();
FunctionalBridge.worker = new RequestWorker();
CommonHelper.newThread("Task Worker", true, FunctionalBridge.worker).start();
FunctionalBridge.getHWID = CommonHelper.newThread("GetHWID Thread", true, FunctionalBridge::getHWID); FunctionalBridge.getHWID = CommonHelper.newThread("GetHWID Thread", true, FunctionalBridge::getHWID);
FunctionalBridge.getHWID.start(); FunctionalBridge.getHWID.start();
LogHelper.debug("Dir: %s", DirBridge.dir); LogHelper.debug("Dir: %s", DirBridge.dir);

View file

@ -1,30 +0,0 @@
package ru.gravit.launcher;
import ru.gravit.utils.helper.LogHelper;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class RequestWorker implements Runnable {
public RequestWorker() {
queue = new LinkedBlockingQueue<>(64);
}
public BlockingQueue<Runnable> queue;
@Override
public void run() {
LogHelper.debug("FX Task Thread start");
while (!Thread.interrupted()) {
try {
Runnable task;
task = queue.take();
task.run();
} catch (InterruptedException e) {
LogHelper.error(e);
return;
}
}
LogHelper.debug("FX Task Thread done");
}
}

View file

@ -3,7 +3,6 @@
import javafx.concurrent.Task; import javafx.concurrent.Task;
import ru.gravit.launcher.HWID; import ru.gravit.launcher.HWID;
import ru.gravit.launcher.LauncherAPI; import ru.gravit.launcher.LauncherAPI;
import ru.gravit.launcher.RequestWorker;
import ru.gravit.launcher.hasher.FileNameMatcher; import ru.gravit.launcher.hasher.FileNameMatcher;
import ru.gravit.launcher.hasher.HashedDir; import ru.gravit.launcher.hasher.HashedDir;
import ru.gravit.launcher.hwid.OshiHWIDProvider; import ru.gravit.launcher.hwid.OshiHWIDProvider;
@ -13,17 +12,18 @@
import ru.gravit.launcher.request.update.LegacyLauncherRequest; import ru.gravit.launcher.request.update.LegacyLauncherRequest;
import ru.gravit.launcher.request.websockets.RequestInterface; import ru.gravit.launcher.request.websockets.RequestInterface;
import ru.gravit.launcher.serialize.signed.SignedObjectHolder; import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
import ru.gravit.utils.helper.LogHelper;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
public class FunctionalBridge { public class FunctionalBridge {
@LauncherAPI @LauncherAPI
public static LauncherSettings settings; public static LauncherSettings settings;
@LauncherAPI @LauncherAPI
public static RequestWorker worker; public static ExecutorService worker = Executors.newWorkStealingPool();
@LauncherAPI @LauncherAPI
public static OshiHWIDProvider hwidProvider = new OshiHWIDProvider(); public static OshiHWIDProvider hwidProvider = new OshiHWIDProvider();
@LauncherAPI @LauncherAPI
@ -64,11 +64,7 @@ public static void makeJsonRequest(RequestInterface request, Runnable callback)
@LauncherAPI @LauncherAPI
public static void startTask(@SuppressWarnings("rawtypes") Task task) { public static void startTask(@SuppressWarnings("rawtypes") Task task) {
try { worker.execute(task);
worker.queue.put(task);
} catch (InterruptedException e) {
LogHelper.error(e);
}
} }
@LauncherAPI @LauncherAPI

@ -1 +1 @@
Subproject commit 9a7e59fb8df543305a2b708822a398dcabcac4b9 Subproject commit 14d93a04d551ae36f68bd74d61445d8c7d7bd076