view src/org/tmatesoft/hg/internal/RevlogCompressor.java @ 628:6526d8adbc0f

Explicit HgRuntimeException to facilitate easy switch from runtime to checked exceptions
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 22 May 2013 15:52:31 +0200
parents 7c0d2ce340b8
children
line wrap: on
line source
/*
 * Copyright (c) 2013 TMate Software Ltd
 *  
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program 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 General Public License for more details.
 *
 * For information on how to redistribute this software under
 * the terms of a license other than GNU General Public License
 * contact TMate Software at support@hg4j.com
 */
package org.tmatesoft.hg.internal;

import java.util.zip.Deflater;

import org.tmatesoft.hg.core.HgIOException;
import org.tmatesoft.hg.core.SessionContext;
import org.tmatesoft.hg.repo.HgRuntimeException;
import org.tmatesoft.hg.util.LogFacility.Severity;

/**
 * 
 * @author Artem Tikhomirov
 * @author TMate Software Ltd.
 */
public class RevlogCompressor {
	private final SessionContext ctx;
	private final Deflater zip;
	private DataSerializer.DataSource sourceData;
	private int compressedLen;
	
	public RevlogCompressor(SessionContext sessionCtx) {
		ctx = sessionCtx;
		zip = new Deflater();
	}

	public void reset(DataSerializer.DataSource source) {
		sourceData = source;
		compressedLen = -1;
	}
	
	// out stream is not closed!
	public int writeCompressedData(DataSerializer out) throws HgIOException, HgRuntimeException {
		zip.reset();
		DeflaterDataSerializer dds = new DeflaterDataSerializer(out, zip, sourceData.serializeLength());
		sourceData.serialize(dds);
		dds.finish();
		return zip.getTotalOut();
	}

	public int getCompressedLength() throws HgRuntimeException {
		if (compressedLen != -1) {
			return compressedLen;
		}
		Counter counter = new Counter();
		try {
			compressedLen = writeCompressedData(counter);
			assert counter.totalWritten == compressedLen;
	        return compressedLen;
		} catch (HgIOException ex) {
			// can't happen provided we write to our stream that does nothing but byte counting
			ctx.getLog().dump(getClass(), Severity.Error, ex, "Failed estimating compressed length of revlog data");
			return counter.totalWritten; // use best known value so far
		}
	}

	private static class Counter extends DataSerializer {
		public int totalWritten = 0;

		public void writeByte(byte... values) throws HgIOException {
			totalWritten += values.length;
		}

		public void writeInt(int... values) throws HgIOException {
			totalWritten += 4 * values.length;
		}

		public void write(byte[] data, int offset, int length) throws HgIOException {
			totalWritten += length;
		}
	}
}