comparison src/org/tmatesoft/hg/internal/RevlogCompressor.java @ 534:243202f1bda5

Commit: refactor revision creation code from clone command to work separately, fit into existing library structure
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Mon, 04 Feb 2013 18:00:55 +0100
parents 0f6fa88e2162
children 7c0d2ce340b8
comparison
equal deleted inserted replaced
533:e6f72c9829a6 534:243202f1bda5
15 * contact TMate Software at support@hg4j.com 15 * contact TMate Software at support@hg4j.com
16 */ 16 */
17 package org.tmatesoft.hg.internal; 17 package org.tmatesoft.hg.internal;
18 18
19 import java.io.IOException; 19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.util.zip.Deflater; 20 import java.util.zip.Deflater;
22 import java.util.zip.DeflaterOutputStream; 21
22 import org.tmatesoft.hg.core.SessionContext;
23 import org.tmatesoft.hg.util.LogFacility.Severity;
23 24
24 /** 25 /**
25 * 26 *
26 * @author Artem Tikhomirov 27 * @author Artem Tikhomirov
27 * @author TMate Software Ltd. 28 * @author TMate Software Ltd.
28 */ 29 */
29 public class RevlogCompressor { 30 public class RevlogCompressor {
31 private final SessionContext ctx;
30 private final Deflater zip; 32 private final Deflater zip;
31 private byte[] sourceData; 33 private DataSerializer.DataSource sourceData;
32 private int compressedLenEstimate; 34 private int compressedLen;
33 35
34 public RevlogCompressor() { 36 public RevlogCompressor(SessionContext sessionCtx) {
37 ctx = sessionCtx;
35 zip = new Deflater(); 38 zip = new Deflater();
36 } 39 }
37 40
38 public void reset(byte[] source) { 41 public void reset(DataSerializer.DataSource source) {
39 sourceData = source; 42 sourceData = source;
40 compressedLenEstimate = -1; 43 compressedLen = -1;
41 } 44 }
42 45
43 public int writeCompressedData(OutputStream out) throws IOException { 46 // out stream is not closed!
47 public int writeCompressedData(DataSerializer out) throws IOException {
44 zip.reset(); 48 zip.reset();
45 DeflaterOutputStream dos = new DeflaterOutputStream(out, zip, Math.min(2048, sourceData.length)); 49 DeflaterDataSerializer dds = new DeflaterDataSerializer(out, zip, sourceData.serializeLength());
46 dos.write(sourceData); 50 sourceData.serialize(dds);
47 dos.finish(); 51 dds.finish();
48 return zip.getTotalOut(); 52 return zip.getTotalOut();
49 } 53 }
50 54
51 public int getCompressedLengthEstimate() { 55 public int getCompressedLength() {
52 if (compressedLenEstimate != -1) { 56 if (compressedLen != -1) {
53 return compressedLenEstimate; 57 return compressedLen;
54 } 58 }
55 zip.reset(); 59 Counter counter = new Counter();
56 int rv = 0; 60 try {
57 // from DeflaterOutputStream: 61 compressedLen = writeCompressedData(counter);
58 byte[] buffer = new byte[Math.min(2048, sourceData.length)]; 62 assert counter.totalWritten == compressedLen;
59 for (int i = 0, stride = buffer.length; i < sourceData.length; i+= stride) { 63 return compressedLen;
60 zip.setInput(sourceData, i, Math.min(stride, sourceData.length - i)); 64 } catch (IOException ex) {
61 while (!zip.needsInput()) { 65 // can't happen provided we write to our stream that does nothing but byte counting
62 rv += zip.deflate(buffer, 0, buffer.length); 66 ctx.getLog().dump(getClass(), Severity.Error, ex, "Failed estimating compressed length of revlog data");
63 } 67 return counter.totalWritten; // use best known value so far
64 } 68 }
65 zip.finish(); 69 }
66 while (!zip.finished()) { 70
67 rv += zip.deflate(buffer, 0, buffer.length); 71 private static class Counter extends DataSerializer {
68 } 72 public int totalWritten = 0;
69 return compressedLenEstimate = rv; 73
74 public void writeByte(byte... values) throws IOException {
75 totalWritten += values.length;
76 }
77
78 public void writeInt(int... values) throws IOException {
79 totalWritten += 4 * values.length;
80 }
81
82 public void write(byte[] data, int offset, int length) throws IOException {
83 totalWritten += length;
84 }
70 } 85 }
71 } 86 }