From 0f49a73ae7816cbbb19a90f254a9311fa27efb80 Mon Sep 17 00:00:00 2001 From: "marcins78@gmail.com" Date: Sun, 4 Mar 2012 22:00:00 +0000 Subject: [PATCH] Migration of game replays to GZipped format. --- .../com/gempukku/lotro/game/GameRecorder.java | 123 +++++++++++++----- .../com/gempukku/lotro/game/LotroServer.java | 4 + .../gempukku/lotro/server/AdminResource.java | 18 ++- .../gempukku/lotro/server/ServerResource.java | 4 - 4 files changed, 107 insertions(+), 42 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java index f0664b83a..e6c2c7cdf 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java @@ -16,11 +16,11 @@ import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.*; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterInputStream; public class GameRecorder { private static String _possibleChars = "abcdefghijklmnopqrstuvwxyz0123456789"; @@ -32,6 +32,46 @@ public class GameRecorder { _gameHistoryDao = gameHistoryDao; } + public void migrateReplays() { + System.out.println("Migrating replays"); + try { + File gameReplayFolder = new File(ApplicationRoot.getRoot(), "replay"); + for (File file : gameReplayFolder.listFiles()) { + System.out.println("Migrating user: " + file.getName()); + for (File replayFile : file.listFiles()) { + if (replayFile.getName().endsWith(".xml")) { + if (replayFile.length() > 0) + zipFile(replayFile); + replayFile.delete(); + } + } + } + } catch (IOException exp) { + System.out.println("Exception: " + exp.getMessage()); + exp.printStackTrace(); + } + } + + private void zipFile(File replayFile) throws IOException { + OutputStream out = getRecordingWriteStream(replayFile.getParentFile().getName(), replayFile.getName().substring(0, replayFile.getName().length() - 4)); + try { + // Associate a file input stream for the current file + FileInputStream in = new FileInputStream(replayFile); + try { + // Transfer bytes from the current file to the ZIP file + + byte[] buffer = new byte[1024]; + int len; + while ((len = in.read(buffer)) > 0) + out.write(buffer, 0, len); + } finally { + in.close(); + } + } finally { + out.close(); + } + } + private String randomUid() { int length = 16; char[] chars = new char[length]; @@ -46,7 +86,7 @@ public class GameRecorder { final File file = getRecordingFile(playerId, gameId); if (!file.exists() || !file.isFile()) return null; - return new FileInputStream(file); + return new InflaterInputStream(new FileInputStream(file)); } public GameRecordingInProgress recordGame(LotroGameMediator lotroGame, final String formatName, final Map deckNames) { @@ -74,7 +114,15 @@ public class GameRecorder { private File getRecordingFile(String playerId, String gameId) { File gameReplayFolder = new File(ApplicationRoot.getRoot(), "replay"); File playerReplayFolder = new File(gameReplayFolder, playerId); - return new File(playerReplayFolder, gameId + ".xml"); + return new File(playerReplayFolder, gameId + ".xml.gz"); + } + + private OutputStream getRecordingWriteStream(String playerId, String gameId) throws IOException { + File recordingFile = getRecordingFile(playerId, gameId); + recordingFile.getParentFile().mkdirs(); + + Deflater deflater = new Deflater(9); + return new DeflaterOutputStream(new FileOutputStream(recordingFile), deflater); } private Map saveRecordedChannels(Map gameProgress) { @@ -82,38 +130,35 @@ public class GameRecorder { for (Map.Entry playerRecordings : gameProgress.entrySet()) { String playerId = playerRecordings.getKey(); - File replayFile; - String gameRecordingId; - do { - gameRecordingId = randomUid(); - replayFile = getRecordingFile(playerId, gameRecordingId); - } while (replayFile.exists()); - - replayFile.getParentFile().mkdirs(); - + String gameRecordingId = getRecordingId(playerId); final List gameEvents = playerRecordings.getValue().consumeGameEvents(); try { - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); - Document doc = documentBuilder.newDocument(); - Element gameReplay = doc.createElement("gameReplay"); - EventSerializer serializer = new EventSerializer(); - for (GameEvent gameEvent : gameEvents) { - gameReplay.appendChild(serializer.serializeEvent(doc, gameEvent)); + OutputStream replayStream = getRecordingWriteStream(playerId, gameRecordingId); + try { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + Document doc = documentBuilder.newDocument(); + Element gameReplay = doc.createElement("gameReplay"); + EventSerializer serializer = new EventSerializer(); + for (GameEvent gameEvent : gameEvents) { + gameReplay.appendChild(serializer.serializeEvent(doc, gameEvent)); + } + + doc.appendChild(gameReplay); + + // Prepare the DOM document for writing + Source source = new DOMSource(doc); + + // Prepare the output file + Result streamResult = new StreamResult(replayStream); + + // Write the DOM document to the file + Transformer xformer = TransformerFactory.newInstance().newTransformer(); + xformer.transform(source, streamResult); + } finally { + replayStream.close(); } - - doc.appendChild(gameReplay); - - // Prepare the DOM document for writing - Source source = new DOMSource(doc); - - // Prepare the output file - Result streamResult = new StreamResult(replayFile); - - // Write the DOM document to the file - Transformer xformer = TransformerFactory.newInstance().newTransformer(); - xformer.transform(source, streamResult); } catch (Exception exp) { } @@ -121,4 +166,14 @@ public class GameRecorder { } return result; } + + private String getRecordingId(String playerId) { + String result; + File recordingFile; + do { + result = randomUid(); + recordingFile = getRecordingFile(playerId, result); + } while (recordingFile.exists()); + return result; + } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java index 462ca0d76..a89c2aa46 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java @@ -82,6 +82,10 @@ public class LotroServer extends AbstractServer { _gameRecorder = new GameRecorder(_gameHistoryDao); } + public void migrateReplays() { + _gameRecorder.migrateReplays(); + } + public InputStream getGameRecording(String playerId, String gameId) throws IOException { return _gameRecorder.getRecordedGame(playerId, gameId); } diff --git a/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/AdminResource.java b/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/AdminResource.java index ad7394271..351ffccbb 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/AdminResource.java +++ b/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/AdminResource.java @@ -5,10 +5,7 @@ import com.gempukku.lotro.db.DeckDAO; import com.gempukku.lotro.db.LeagueDAO; import com.gempukku.lotro.db.LeagueSerieDAO; import com.gempukku.lotro.db.vo.CollectionType; -import com.gempukku.lotro.game.CardCollection; -import com.gempukku.lotro.game.DefaultCardCollection; -import com.gempukku.lotro.game.LotroCardBlueprintLibrary; -import com.gempukku.lotro.game.Player; +import com.gempukku.lotro.game.*; import com.gempukku.lotro.hall.HallServer; import com.gempukku.lotro.league.LeagueService; import com.sun.jersey.spi.resource.Singleton; @@ -39,6 +36,8 @@ public class AdminResource extends AbstractResource { private LotroCardBlueprintLibrary _library; @Context private HallServer _hallServer; + @Context + private LotroServer _lotroServer; @Path("/clearCache") @GET @@ -54,6 +53,17 @@ public class AdminResource extends AbstractResource { return "OK"; } + @Path("/migrate") + @GET + public String migrate( + @Context HttpServletRequest request) throws Exception { + validateAdmin(request); + + _lotroServer.migrateReplays(); + + return "OK"; + } + @Path("/shutdown") @GET public String shutdown( diff --git a/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/ServerResource.java b/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/ServerResource.java index 5127d9c2e..4c879d96d 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/ServerResource.java +++ b/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/ServerResource.java @@ -50,10 +50,6 @@ public class ServerResource extends AbstractResource { ApplicationRoot.setRoot(new File("/etc/gemp-lotr")); else ApplicationRoot.setRoot(new File("i:\\gemp-lotr")); - - _logger.debug("starting resource"); - - _logger.debug("Resource created"); } @Path("/login")