From d5ea46a29cb7093fa7ccf0dc769ebf4a60cdc3d4 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Thu, 20 Oct 2016 18:03:56 +1100 Subject: [PATCH] PGZIP --- .../java/com/boydti/fawe/bukkit/Metrics.java | 21 +- .../main/java/com/boydti/fawe/FaweAPI.java | 40 +-- .../fawe/object/io/PGZIPOutputStream.java | 283 ++++++++++++++++++ .../general/plot/FaweSchematicHandler.java | 12 +- .../java/com/boydti/fawe/util/MainUtil.java | 53 +--- .../extent/clipboard/io/ClipboardFormat.java | 26 +- .../com/boydti/fawe/forge/ForgeMetrics.java | 13 +- .../com/boydti/fawe/forge/ForgeMetrics.java | 13 +- .../com/boydti/fawe/forge/ForgeMetrics.java | 13 +- .../com/boydti/fawe/forge/ForgeMetrics.java | 13 +- .../fawe/nukkit/optimization/Metrics.java | 19 +- 11 files changed, 343 insertions(+), 163 deletions(-) create mode 100644 core/src/main/java/com/boydti/fawe/object/io/PGZIPOutputStream.java diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/Metrics.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/Metrics.java index 41bda87a..95e96196 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/Metrics.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/Metrics.java @@ -2,27 +2,16 @@ package com.boydti.fawe.bukkit; import com.boydti.fawe.Fawe; import com.boydti.fawe.object.io.FastByteArrayOutputStream; +import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.util.MainUtil; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.lang.reflect.InvocationTargetException; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.logging.Level; -import java.util.zip.GZIPOutputStream; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; @@ -86,9 +75,9 @@ public class Metrics { */ public static byte[] gzip(String input) { FastByteArrayOutputStream baos = new FastByteArrayOutputStream(); - GZIPOutputStream gzos = null; + PGZIPOutputStream gzos = null; try { - gzos = new GZIPOutputStream(baos); + gzos = new PGZIPOutputStream(baos); gzos.write(input.getBytes("UTF-8")); } catch (IOException e) { MainUtil.handleError(e); diff --git a/core/src/main/java/com/boydti/fawe/FaweAPI.java b/core/src/main/java/com/boydti/fawe/FaweAPI.java index 4518fac7..ec567a43 100644 --- a/core/src/main/java/com/boydti/fawe/FaweAPI.java +++ b/core/src/main/java/com/boydti/fawe/FaweAPI.java @@ -4,28 +4,15 @@ import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Settings; import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.example.NMSRelighter; -import com.boydti.fawe.object.FaweLocation; -import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.PseudoRandom; -import com.boydti.fawe.object.RegionWrapper; -import com.boydti.fawe.object.RunnableVal; +import com.boydti.fawe.object.*; import com.boydti.fawe.object.changeset.DiskStorageHistory; +import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.object.mask.CustomMask; import com.boydti.fawe.object.schematic.Schematic; import com.boydti.fawe.regions.FaweMaskManager; -import com.boydti.fawe.util.EditSessionBuilder; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.MemUtil; -import com.boydti.fawe.util.SetQueue; -import com.boydti.fawe.util.TaskManager; -import com.boydti.fawe.util.WEManager; +import com.boydti.fawe.util.*; import com.boydti.fawe.wrappers.WorldWrapper; -import com.sk89q.jnbt.ByteArrayTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.jnbt.ShortTag; -import com.sk89q.jnbt.Tag; +import com.sk89q.jnbt.*; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEdit; @@ -40,24 +27,13 @@ import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.World; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.lang.reflect.Field; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; +import java.util.zip.Deflater; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import javax.annotation.Nonnull; @@ -169,7 +145,7 @@ public class FaweAPI { @Override public void run(OutputStream value) { try { - try (GZIPOutputStream gzip = new GZIPOutputStream(value, true)) { + try (PGZIPOutputStream gzip = new PGZIPOutputStream(value)) { try (ClipboardWriter writer = format.getWriter(gzip)) { writer.write(clipboard, null); } diff --git a/core/src/main/java/com/boydti/fawe/object/io/PGZIPOutputStream.java b/core/src/main/java/com/boydti/fawe/object/io/PGZIPOutputStream.java new file mode 100644 index 00000000..259f88eb --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/io/PGZIPOutputStream.java @@ -0,0 +1,283 @@ +package com.boydti.fawe.object.io; + +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.concurrent.*; +import java.util.zip.CRC32; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.GZIPOutputStream; +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +/** + * A multi-threaded version of {@link GZIPOutputStream}. + * + * @author shevek + */ +public class PGZIPOutputStream extends FilterOutputStream { + + private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool(); + + public static ExecutorService getSharedThreadPool() { + return EXECUTOR; + } + + + // private static final Logger LOG = LoggerFactory.getLogger(PGZIPOutputStream.class); + private final static int GZIP_MAGIC = 0x8b1f; + + // todo: remove after block guessing is implemented + // array list that contains the block sizes + ArrayList blockSizes = new ArrayList(); + + private int level = Deflater.BEST_SPEED; + private int strategy = Deflater.HUFFMAN_ONLY; + + @Nonnull + private Deflater newDeflater() { + Deflater def = new Deflater(level, true); + def.setStrategy(strategy); + return def; + } + + public void setStrategy(int strategy) { + this.strategy = strategy; + } + + public void setLevel(int level) { + this.level = level; + } + + @Nonnull + private static DeflaterOutputStream newDeflaterOutputStream(@Nonnull OutputStream out, @Nonnull Deflater deflater) { + return new DeflaterOutputStream(out, deflater, 512, true); + } + + private class Block implements Callable { + + private class State { + + private final Deflater def = newDeflater(); + private final ByteArrayOutputStream buf = new ByteArrayOutputStream(SIZE); + private final DeflaterOutputStream str = newDeflaterOutputStream(buf, def); + } + /** This ThreadLocal avoids the recycling of a lot of memory, causing lumpy performance. */ + private final ThreadLocal STATE = new ThreadLocal() { + @Override + protected State initialValue() { + return new State(); + } + }; + public static final int SIZE = 64 * 1024; + // private final int index; + private final byte[] in = new byte[SIZE]; + private int in_length = 0; + + /* + public Block(@Nonnegative int index) { + this.index = index; + } + */ + // Only on worker thread + @Override + public byte[] call() throws Exception { + // LOG.info("Processing " + this + " on " + Thread.currentThread()); + + State state = STATE.get(); + // ByteArrayOutputStream buf = new ByteArrayOutputStream(in.length); // Overestimate output size required. + // DeflaterOutputStream def = newDeflaterOutputStream(buf); + state.def.reset(); + state.buf.reset(); + state.str.write(in, 0, in_length); + state.str.flush(); + + // return Arrays.copyOf(in, in_length); + return state.buf.toByteArray(); + } + + @Override + public String toString() { + return "Block" /* + index */ + "(" + in_length + "/" + in.length + " bytes)"; + } + } + // TODO: Share, daemonize. + private final ExecutorService executor; + private final int nthreads; + private final CRC32 crc = new CRC32(); + private final BlockingQueue> emitQueue; + private Block block = new Block(/* 0 */); + /** Used as a sentinel for 'closed'. */ + private int bytesWritten = 0; + + // Master thread only + public PGZIPOutputStream(@Nonnull OutputStream out, @Nonnull ExecutorService executor, @Nonnegative int nthreads) throws IOException { + super(out); + this.executor = executor; + this.nthreads = nthreads; + this.emitQueue = new ArrayBlockingQueue>(nthreads); + writeHeader(); + } + + /** + * Creates a PGZIPOutputStream + * using {@link PGZIPOutputStream#getSharedThreadPool()}. + * + * @param out the eventual output stream for the compressed data. + * @throws IOException if it all goes wrong. + */ + public PGZIPOutputStream(@Nonnull OutputStream out, @Nonnegative int nthreads) throws IOException { + this(out, PGZIPOutputStream.getSharedThreadPool(), nthreads); + } + + /** + * Creates a PGZIPOutputStream + * using {@link PGZIPOutputStream#getSharedThreadPool()} + * and {@link Runtime#availableProcessors()}. + * + * @param out the eventual output stream for the compressed data. + * @throws IOException if it all goes wrong. + */ + public PGZIPOutputStream(@Nonnull OutputStream out) throws IOException { + this(out, Runtime.getRuntime().availableProcessors()); + } + + /* + * @see http://www.gzip.org/zlib/rfc-gzip.html#file-format + */ + private void writeHeader() throws IOException { + out.write(new byte[]{ + (byte) GZIP_MAGIC, // ID1: Magic number (little-endian short) + (byte) (GZIP_MAGIC >> 8), // ID2: Magic number (little-endian short) + Deflater.DEFLATED, // CM: Compression method + 0, // FLG: Flags (byte) + 0, 0, 0, 0, // MTIME: Modification time (int) + 0, // XFL: Extra flags + 3 // OS: Operating system (3 = Linux) + }); + } + + // Master thread only + @Override + public void write(int b) throws IOException { + byte[] single = new byte[1]; + single[0] = (byte) (b & 0xFF); + write(single); + } + + // Master thread only + @Override + public void write(@Nonnull byte[] b) throws IOException { + write(b, 0, b.length); + } + + // Master thread only + @Override + public void write(@Nonnull byte[] b, int off, int len) throws IOException { + crc.update(b, off, len); + bytesWritten += len; + while (len > 0) { + // assert block.in_length < block.in.length + int capacity = block.in.length - block.in_length; + if (len >= capacity) { + System.arraycopy(b, off, block.in, block.in_length, capacity); + block.in_length += capacity; // == block.in.length + off += capacity; + len -= capacity; + submit(); + } else { + System.arraycopy(b, off, block.in, block.in_length, len); + block.in_length += len; + // off += len; + // len = 0; + break; + } + } + } + + // Master thread only + private void submit() throws IOException { + emitUntil(nthreads - 1); + emitQueue.add(executor.submit(block)); + block = new Block(/* block.index + 1 */); + } + + // Emit If Available - submit always + // Emit At Least one - submit when executor is full + // Emit All Remaining - flush(), close() + // Master thread only + private void tryEmit() throws IOException, InterruptedException, ExecutionException { + for (;;) { + Future future = emitQueue.peek(); + // LOG.info("Peeked future " + future); + if (future == null) + return; + if (!future.isDone()) + return; + // It's an ordered queue. This MUST be the same element as above. + emitQueue.remove(); + byte[] toWrite = future.get(); + blockSizes.add(toWrite.length); // todo: remove after block guessing is implemented + out.write(toWrite); + } + } + + // Master thread only + /** Emits any opportunistically available blocks. Furthermore, emits blocks until the number of executing tasks is less than taskCountAllowed. */ + private void emitUntil(@Nonnegative int taskCountAllowed) throws IOException { + try { + while (emitQueue.size() > taskCountAllowed) { + // LOG.info("Waiting for taskCount=" + emitQueue.size() + " -> " + taskCountAllowed); + Future future = emitQueue.remove(); // Valid because emitQueue.size() > 0 + byte[] toWrite = future.get(); // Blocks until this task is done. + blockSizes.add(toWrite.length); // todo: remove after block guessing is implemented + out.write(toWrite); + } + // We may have achieved more opportunistically available blocks + // while waiting for a block above. Let's emit them here. + tryEmit(); + } catch (ExecutionException e) { + throw new IOException(e); + } catch (InterruptedException e) { + throw new InterruptedIOException(); + } + } + + // Master thread only + @Override + public void flush() throws IOException { + // LOG.info("Flush: " + block); + if (block.in_length > 0) + submit(); + emitUntil(0); + super.flush(); + } + + // Master thread only + @Override + public void close() throws IOException { + // LOG.info("Closing: bytesWritten=" + bytesWritten); + if (bytesWritten >= 0) { + flush(); + + newDeflaterOutputStream(out, newDeflater()).finish(); + + ByteBuffer buf = ByteBuffer.allocate(8); + buf.order(ByteOrder.LITTLE_ENDIAN); + // LOG.info("CRC is " + crc.getValue()); + buf.putInt((int) crc.getValue()); + buf.putInt(bytesWritten); + out.write(buf.array()); // allocate() guarantees a backing array. + // LOG.info("trailer is " + Arrays.toString(buf.array())); + + out.flush(); + out.close(); + + bytesWritten = Integer.MIN_VALUE; + // } else { + // LOG.warn("Already closed."); + } + } +} \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java b/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java index e5c12c69..57c06031 100644 --- a/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java +++ b/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java @@ -4,6 +4,7 @@ import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.clipboard.ReadOnlyClipboard; +import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; @@ -25,17 +26,12 @@ import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.SchematicWriter; import com.sk89q.worldedit.regions.CuboidRegion; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; import java.net.URL; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.zip.GZIPOutputStream; public class FaweSchematicHandler extends SchematicHandler { @Override @@ -120,7 +116,7 @@ public class FaweSchematicHandler extends SchematicHandler { File tmp = MainUtil.getFile(PS.get().IMP.getDirectory(), path); tmp.getParentFile().mkdirs(); com.sk89q.jnbt.CompoundTag weTag = (com.sk89q.jnbt.CompoundTag) FaweCache.asTag(tag); - try (OutputStream stream = new FileOutputStream(tmp); NBTOutputStream output = new NBTOutputStream(new GZIPOutputStream(stream))) { + try (OutputStream stream = new FileOutputStream(tmp); NBTOutputStream output = new NBTOutputStream(new PGZIPOutputStream(stream))) { Map map = weTag.getValue(); output.writeNamedTag("Schematic", map.containsKey("Schematic") ? map.get("Schematic") : weTag); } @@ -144,7 +140,7 @@ public class FaweSchematicHandler extends SchematicHandler { @Override public void run(OutputStream output) { try { - try (GZIPOutputStream gzip = new GZIPOutputStream(output, true)) { + try (PGZIPOutputStream gzip = new PGZIPOutputStream(output)) { com.sk89q.jnbt.CompoundTag weTag = (com.sk89q.jnbt.CompoundTag) FaweCache.asTag(tag); try (NBTOutputStream nos = new NBTOutputStream(gzip)) { Map map = weTag.getValue(); diff --git a/core/src/main/java/com/boydti/fawe/util/MainUtil.java b/core/src/main/java/com/boydti/fawe/util/MainUtil.java index f67fd193..15ff1756 100644 --- a/core/src/main/java/com/boydti/fawe/util/MainUtil.java +++ b/core/src/main/java/com/boydti/fawe/util/MainUtil.java @@ -3,49 +3,22 @@ package com.boydti.fawe.util; import com.boydti.fawe.Fawe; import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.FaweInputStream; -import com.boydti.fawe.object.FaweOutputStream; -import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.RegionWrapper; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.object.RunnableVal2; +import com.boydti.fawe.object.*; import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet; import com.boydti.fawe.object.changeset.FaweStreamChangeSet; import com.boydti.fawe.object.io.AbstractDelegateOutputStream; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.EndTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; +import com.boydti.fawe.object.io.PGZIPOutputStream; +import com.sk89q.jnbt.*; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.util.Location; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; +import java.io.*; import java.lang.reflect.Array; import java.lang.reflect.Method; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLConnection; +import java.net.*; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; +import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.List; @@ -53,16 +26,11 @@ import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; +import java.util.zip.Deflater; import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import net.jpountz.lz4.LZ4Compressor; -import net.jpountz.lz4.LZ4Factory; -import net.jpountz.lz4.LZ4FastDecompressor; -import net.jpountz.lz4.LZ4InputStream; -import net.jpountz.lz4.LZ4OutputStream; -import net.jpountz.lz4.LZ4Utils; +import net.jpountz.lz4.*; public class MainUtil { /* @@ -209,7 +177,10 @@ public class MainUtil { } int gzipAmount = amount > 6 ? 1 : 0; for (int i = 0; i < gzipAmount; i++) { - os = new BufferedOutputStream(new GZIPOutputStream(os, buffer, true)); + PGZIPOutputStream gzip = new PGZIPOutputStream(os, buffer); + os = new BufferedOutputStream(gzip); + gzip.setStrategy(Deflater.DEFAULT_STRATEGY); + gzip.setLevel(9); } LZ4Factory factory = LZ4Factory.fastestInstance(); int fastAmount = 1 + ((amount - 1) % 3); diff --git a/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java index bfc69bd3..e76d1ff9 100644 --- a/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java +++ b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java @@ -23,6 +23,7 @@ import com.boydti.fawe.object.FaweOutputStream; import com.boydti.fawe.object.clipboard.AbstractClipboardFormat; import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard; import com.boydti.fawe.object.clipboard.IClipboardFormat; +import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.object.schematic.FaweFormat; import com.boydti.fawe.object.schematic.PNGWriter; import com.boydti.fawe.object.schematic.Schematic; @@ -32,14 +33,7 @@ import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.jnbt.NBTConstants; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.util.EnumSet; import java.util.Map; import java.util.Set; @@ -69,12 +63,12 @@ public enum ClipboardFormat { @Override public ClipboardWriter getWriter(OutputStream outputStream) throws IOException { - GZIPOutputStream gzip; - if (outputStream instanceof GZIPOutputStream) { - gzip = (GZIPOutputStream) outputStream; + PGZIPOutputStream gzip; + if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) { + gzip = (PGZIPOutputStream) outputStream; } else { outputStream = new BufferedOutputStream(outputStream); - gzip = new GZIPOutputStream(outputStream, true); + gzip = new PGZIPOutputStream(outputStream); } NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip)); return new SchematicWriter(nbtStream); @@ -125,11 +119,11 @@ public enum ClipboardFormat { @Override public ClipboardWriter getWriter(OutputStream outputStream) throws IOException { outputStream = new BufferedOutputStream(outputStream); - GZIPOutputStream gzip; - if (outputStream instanceof GZIPOutputStream) { - gzip = (GZIPOutputStream) outputStream; + OutputStream gzip; + if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) { + gzip = outputStream; } else { - gzip = new GZIPOutputStream(outputStream, true); + gzip = new PGZIPOutputStream(outputStream); } NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip)); return new StructureFormat(nbtStream); diff --git a/forge110/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java b/forge110/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java index 62dd9544..3142ebc7 100644 --- a/forge110/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java +++ b/forge110/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java @@ -31,19 +31,14 @@ package com.boydti.fawe.forge; import com.boydti.fawe.object.io.FastByteArrayOutputStream; +import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.util.MainUtil; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.UUID; -import java.util.zip.GZIPOutputStream; import net.minecraft.server.MinecraftServer; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -357,10 +352,10 @@ public class ForgeMetrics { */ public static byte[] gzip(String input) { FastByteArrayOutputStream baos = new FastByteArrayOutputStream(); - GZIPOutputStream gzos = null; + PGZIPOutputStream gzos = null; try { - gzos = new GZIPOutputStream(baos); + gzos = new PGZIPOutputStream(baos); gzos.write(input.getBytes("UTF-8")); } catch (IOException e) { MainUtil.handleError(e); diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java b/forge1710/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java index 0e984057..7faf5c31 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java @@ -31,24 +31,19 @@ package com.boydti.fawe.forge; import com.boydti.fawe.object.io.FastByteArrayOutputStream; +import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.util.MainUtil; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.UUID; -import java.util.zip.GZIPOutputStream; import net.minecraft.server.MinecraftServer; import net.minecraftforge.common.config.Configuration; @@ -356,10 +351,10 @@ public class ForgeMetrics { */ public static byte[] gzip(String input) { FastByteArrayOutputStream baos = new FastByteArrayOutputStream(); - GZIPOutputStream gzos = null; + PGZIPOutputStream gzos = null; try { - gzos = new GZIPOutputStream(baos); + gzos = new PGZIPOutputStream(baos); gzos.write(input.getBytes("UTF-8")); } catch (IOException e) { MainUtil.handleError(e); diff --git a/forge189/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java b/forge189/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java index b4b59f95..92e2d6c0 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java @@ -31,19 +31,14 @@ package com.boydti.fawe.forge; import com.boydti.fawe.object.io.FastByteArrayOutputStream; +import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.util.MainUtil; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.UUID; -import java.util.zip.GZIPOutputStream; import net.minecraft.server.MinecraftServer; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -356,10 +351,10 @@ public class ForgeMetrics { */ public static byte[] gzip(String input) { FastByteArrayOutputStream baos = new FastByteArrayOutputStream(); - GZIPOutputStream gzos = null; + PGZIPOutputStream gzos = null; try { - gzos = new GZIPOutputStream(baos); + gzos = new PGZIPOutputStream(baos); gzos.write(input.getBytes("UTF-8")); } catch (IOException e) { MainUtil.handleError(e); diff --git a/forge194/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java b/forge194/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java index 62dd9544..3142ebc7 100644 --- a/forge194/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java +++ b/forge194/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java @@ -31,19 +31,14 @@ package com.boydti.fawe.forge; import com.boydti.fawe.object.io.FastByteArrayOutputStream; +import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.util.MainUtil; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.UUID; -import java.util.zip.GZIPOutputStream; import net.minecraft.server.MinecraftServer; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -357,10 +352,10 @@ public class ForgeMetrics { */ public static byte[] gzip(String input) { FastByteArrayOutputStream baos = new FastByteArrayOutputStream(); - GZIPOutputStream gzos = null; + PGZIPOutputStream gzos = null; try { - gzos = new GZIPOutputStream(baos); + gzos = new PGZIPOutputStream(baos); gzos.write(input.getBytes("UTF-8")); } catch (IOException e) { MainUtil.handleError(e); diff --git a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/Metrics.java b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/Metrics.java index 38adda69..0c2bdb7e 100644 --- a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/Metrics.java +++ b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/Metrics.java @@ -5,24 +5,15 @@ import cn.nukkit.plugin.PluginDescription; import cn.nukkit.utils.LogLevel; import com.boydti.fawe.Fawe; import com.boydti.fawe.object.io.FastByteArrayOutputStream; +import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.TaskManager; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.UUID; -import java.util.zip.GZIPOutputStream; +import java.util.*; public class Metrics { @@ -81,9 +72,9 @@ public class Metrics { */ public static byte[] gzip(String input) { FastByteArrayOutputStream baos = new FastByteArrayOutputStream(); - GZIPOutputStream gzos = null; + PGZIPOutputStream gzos = null; try { - gzos = new GZIPOutputStream(baos); + gzos = new PGZIPOutputStream(baos); gzos.write(input.getBytes("UTF-8")); } catch (IOException e) { MainUtil.handleError(e);