/*********************************************************************************** * Copyright (c) 2015 /// Project SWG /// www.projectswg.com * * * * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * * Our goal is to create an emulator which will provide a server for players to * * continue playing a game similar to the one they used to play. We are basing * * it on the final publish of the game prior to end-game events. * * * * This file is part of Holocore. * * * * -------------------------------------------------------------------------------- * * * * Holocore is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * Holocore 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 Affero General Public License for more details. * * * * You should have received a copy of the GNU Affero General Public License * * along with Holocore. If not, see . * * * ***********************************************************************************/ package com.projectswg.common.data; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import com.projectswg.common.info.RelationalDatabase; import com.projectswg.common.info.RelationalServerFactory; import com.projectswg.lightspeed_frontend.data.SharedBuildData; import com.projectswg.lightspeed_frontend.data.SharedDeploymentData; import com.projectswg.lightspeed_frontend.data.SharedServerData; public class BackendData { private final WeakMap serverMap; private final WeakMap buildMap; private final WeakMap deploymentMap; public BackendData() { serverMap = new WeakMap<>(); buildMap = new WeakMap<>(); deploymentMap = new WeakMap<>(); loadServers(); } public void insertServer(SharedServerData server) { synchronized (serverMap) { if (serverMap.put(server.getName(), server) != null) return; } try (ServerTable serverTable = new ServerTable()) { serverTable.insertServer(new SQLServerData(server.getName(), server.getDirectory(), server.getJvmArguments())); } } public void insertBuild(SharedBuildData build) { synchronized (buildMap) { if (buildMap.put(build.getId(), build) != null) return; } try (BuildHistoryTable buildTable = new BuildHistoryTable()) { buildTable.insertBuildHistory(new SQLBuildData(build)); } } public void insertDeployment(SharedDeploymentData deployment) { synchronized (deploymentMap) { if (deploymentMap.put(deployment.getId(), deployment) != null) return; } try (DeploymentTable deploymentTable = new DeploymentTable()) { deploymentTable.insertDeployment(new SQLDeploymentData(deployment)); } } public void removeServer(String serverId) { synchronized (serverMap) { serverMap.remove(serverId); } try (ServerTable serverTable = new ServerTable()) { serverTable.deleteServer(serverId); } } public List getServerList() { List servers = new ArrayList<>(serverMap.size()); synchronized (serverMap) { for (Entry e : serverMap.entrySet()) { servers.add(e.getValue()); } } return servers; } public SharedServerData getServer(String serverId) { synchronized (serverMap) { SharedServerData server = serverMap.get(serverId); if (server != null) return server; server = fetchServer(serverId); serverMap.put(serverId, server); return server; } } public SharedBuildData getBuild(long buildId) { synchronized (buildMap) { SharedBuildData build = buildMap.get(buildId); if (build != null) return build; build = fetchBuild(buildId); buildMap.put(buildId, build); return build; } } private void loadServers() { synchronized (serverMap) { try (RelationalDatabase db = RelationalServerFactory.getServerDatabase("lightspeed.db")) { try (ServerTable serverTable = new ServerTable(db)) { for (String serverId : serverTable.getServerStrings()) { SharedServerData server = fetchServer(serverId); serverMap.put(server.getName(), server); } } } } } private SharedServerData fetchServer(String serverId) { try (RelationalDatabase db = RelationalServerFactory.getServerDatabase("lightspeed.db")) { try (ServerTable serverTable = new ServerTable(db)) { SharedServerData server = createServerFromInfo(serverTable.getServerById(serverId)); fetchBuildHistory(db, server); return server; } } } private void fetchBuildHistory(RelationalDatabase db, SharedServerData server) { try (BuildHistoryTable buildTable = new BuildHistoryTable(db)) { for (SQLBuildData info : buildTable.getBuildHistory(server.getName())) { SharedBuildData build = createBuildFromInfo(server, info); synchronized (buildMap) { buildMap.put(build.getId(), build); } fetchDeploymentHistory(db, build); server.addBuild(build); } } } private SharedBuildData fetchBuild(long buildId) { try (RelationalDatabase db = RelationalServerFactory.getServerDatabase("lightspeed.db")) { try (BuildHistoryTable buildTable = new BuildHistoryTable(db)) { SQLBuildData info = buildTable.getBuildById(buildId); SharedServerData server = getServer(info.getServerId()); SharedBuildData build = createBuildFromInfo(server, info); fetchDeploymentHistory(db, build); return build; } } } private void fetchDeploymentHistory(RelationalDatabase db, SharedBuildData build) { try (DeploymentTable deploymentTable = new DeploymentTable(db)) { for (SQLDeploymentData info : deploymentTable.getDeployments(build.getId())) { SharedDeploymentData deployment = createDeploymentFromInfo(build, info); build.addDeployment(deployment); synchronized (deploymentMap) { deploymentMap.put(deployment.getId(), deployment); } } } } private SharedServerData createServerFromInfo(SQLServerData info) { SharedServerData server = new SharedServerData(info.getId()); server.setDirectory(info.getDir()); server.setJvmArguments(info.getJvmArgs()); return server; } private SharedBuildData createBuildFromInfo(SharedServerData server, SQLBuildData info) { SharedBuildData build = new SharedBuildData(info.getId(), server); build.setTime(info.getCompletedTime()); build.setBuildString(info.getBuildString()); build.setTestString(info.getTestString()); build.setCompileTime(info.getCompileTime()); build.setOffline(info.isOffline()); build.setBuildSuccess(info.isBuildSuccess()); build.setTestSuccess(info.isTestSuccess()); build.setCancelled(info.isCancelled()); build.setTestDetails(info.getTestDetails()); build.setJar(info.getJar()); return build; } private SharedDeploymentData createDeploymentFromInfo(SharedBuildData build, SQLDeploymentData info) { SharedDeploymentData deployment = new SharedDeploymentData(info.getId(), build); deployment.setStartTime(info.getStartTime()); deployment.setEndTime(info.getEndTime()); return deployment; } private static class WeakMap { private final Map> map; public WeakMap() { map = new HashMap<>(); } public V get(K key) { WeakReference ref = map.get(key); return (ref == null) ? null : ref.get(); } public V put(K key, V val) { WeakReference ref = map.put(key, new WeakReference<>(val)); if (ref == null) return null; return ref.get(); } public boolean remove(K key) { return map.remove(key) != null; } public Set> entrySet() { Set>> entries = map.entrySet(); Set> ret = new HashSet<>(); for (Entry> entry : entries) { if (entry.getValue() != null) { V val = entry.getValue().get(); if (val != null) ret.add(new WeakEntry<>(entry.getKey(), val)); } } return ret; } public int size() { return map.size(); } } private static class WeakEntry implements Map.Entry { private final K key; private V value; public WeakEntry(K key, V value) { this.key = key; this.value = value; } @Override public K getKey() { return key; } @Override public V getValue() { return value; } @Override public V setValue(V value) { V old = this.value; this.value = value; return old; } } }