Permalink
Browse files

Added deltazip file header.

Adapted tests (incl. test bug fixes)
Some ByteBuffer-position-related cleanup.
  • Loading branch information...
1 parent 7abc6f6 commit d6d87db37486f2c7eb2ee88e9b603e91777dca20 @eriksoe eriksoe committed Jun 23, 2011
View
13 src/main/java/com/trifork/deltazip/DZUtil.java
@@ -25,12 +25,15 @@ public ByteBuffer pread(long pos, int len) throws IOException {
}
public byte[] applyAppendSpec(DeltaZip.AppendSpecification spec) {
+ int pos = (int) spec.prefix_size;
+ ByteBuffer tail = spec.new_tail;
+ int total_length = (int) (spec.prefix_size + tail.remaining());
try {
- int length = (int) (spec.prefix_size + spec.new_tail.remaining());
- ByteArrayOutputStream baos = new ByteArrayOutputStream(length);
- baos.write(data);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(total_length);
+ baos.write(data, 0, pos);
+
WritableByteChannel channel = Channels.newChannel(baos);
- channel.write(spec.new_tail);
+ channel.write(tail);
channel.close();
return baos.toByteArray();
} catch (IOException ioe) {throw new RuntimeException(ioe);}
@@ -73,7 +76,7 @@ public ByteBuffer pread(long pos, int len) throws IOException {
public void applyAppendSpec(DeltaZip.AppendSpecification spec) throws IOException {
long pos = spec.prefix_size;
ByteBuffer tail = spec.new_tail;
- long total_length = (spec.prefix_size + tail.remaining());
+ long total_length = spec.prefix_size + tail.remaining();
while (tail.hasRemaining()) {
int w = file.write(tail, pos);
View
33 src/main/java/com/trifork/deltazip/DeltaZip.java
@@ -16,12 +16,16 @@
//==================== Constants =======================================
+ public static final int DELTAZIP_MAGIC_HEADER = 0xCEB47A10;
+ public static final int FILE_HEADER_LENGTH = 4;
+
private static final int VERSION_SIZE_BITS = 28;
private static final int VERSION_SIZE_LIMIT = 1 << VERSION_SIZE_BITS;
public static final int METHOD_UNCOMPRESSED = 0;
public static final int METHOD_CHUNKED = 2;
+
protected static final CompressionMethod[] COMPRESSION_METHODS;
protected static final CompressionMethod UNCOMPRESSED_INSTANCE = new UncompressedMethod();
protected static final CompressionMethod CHUNKED_INSTANCE = new ChunkedMethod();
@@ -49,6 +53,7 @@ private static void insertCM(CompressionMethod[] table, CompressionMethod cm) {
public DeltaZip(Access access) throws IOException {
this.access = access;
+ check_magic_header();
set_cursor_at_end();
}
@@ -75,17 +80,19 @@ public void previous() throws IOException {
* Has the side effect of placing the cursor at the end.
*/
public AppendSpecification add(ByteBuffer new_version) throws IOException {
- int save_pos = new_version.position();
-
set_cursor_at_end();
ExtByteArrayOutputStream baos = new ExtByteArrayOutputStream();
+
+ // If the file is empty, add a header:
+ if (current_pos==0) baos.writeBigEndianInteger(DELTAZIP_MAGIC_HEADER, 4);
+
ByteBuffer last_version = get();
+
if (last_version != null) {
pack_compressed(last_version, allToByteArray(new_version), baos);
}
pack_uncompressed(new_version, baos);
- new_version.position(save_pos); // Restore as-was.
return new AppendSpecification(current_pos, baos.toByteArray());
}
@@ -95,6 +102,10 @@ public AppendSpecification add(ByteBuffer new_version) throws IOException {
public AppendSpecification add(Iterator<ByteBuffer> versions_to_add) throws IOException {
set_cursor_at_end();
ExtByteArrayOutputStream baos = new ExtByteArrayOutputStream();
+
+ // If the file is empty, add a header:
+ if (current_pos==0) baos.writeBigEndianInteger(DELTAZIP_MAGIC_HEADER, 4);
+
ByteBuffer prev_version = get();
while (versions_to_add.hasNext()) {
@@ -110,6 +121,20 @@ public AppendSpecification add(Iterator<ByteBuffer> versions_to_add) throws IOEx
//==================== Internals =======================================
+ protected void check_magic_header() throws IOException {
+ long size = access.getSize();
+ if (size == 0) return; // OK (empty)
+ if (size < FILE_HEADER_LENGTH ||
+ read_magic_header() != DELTAZIP_MAGIC_HEADER)
+ throw new IOException("Not a deltazip file (invalid header)");
+ }
+
+ protected int read_magic_header() throws IOException {
+ ByteBuffer header = access.pread(0,4);
+ int magic = header.getInt(0);
+ return magic;
+ }
+
protected void set_cursor_at_end() throws IOException {
set_initial_position();
if (hasPrevious()) previous();
@@ -156,7 +181,7 @@ protected void pack_compressed(ByteBuffer version, byte[] ref_version, ExtByteAr
protected void pack_entry(ByteBuffer version, byte[] ref_version, CompressionMethod cm, ExtByteArrayOutputStream dst) {
int tag_blank = dst.insertBlank(4);
int size_before = dst.size();
- cm.compress(version, ref_version, dst);
+ cm.compress(version.duplicate(), ref_version, dst);
int size_after = dst.size();
int length = size_after - size_before;
View
10 src/test/java/com/trifork/deltazip/DeltaZipTest.java
@@ -23,6 +23,7 @@ public void test_read_known() throws Exception {
/** Chunked-deflate, no prefix/suffix. */
byte[] two_revs1 = {
+ (byte)0xCE, (byte)0xB4, 0x7A, 0x10,
32,0,0,7,0,0,4,(byte)243,
0,113,0,32,0,0,7,0,
0,0,13,72,101,108,108,111,
@@ -31,6 +32,7 @@ public void test_read_known() throws Exception {
/** Chunked-deflate, using prefix. */
byte[] two_revs2 = {
+ (byte)0xCE, (byte)0xB4, 0x7A, 0x10,
32,0,0,5,8,0,2,0,
4,32,0,0,5,0,0,0,
13,72,101,108,108,111,44,32,
@@ -84,7 +86,7 @@ public void test_add_get_with(byte[] file0, ByteBuffer rev1, ByteBuffer rev2) th
ByteArrayAccess access1 = new ByteArrayAccess(file1);
DeltaZip dz1 = new DeltaZip(access1);
AppendSpecification app2 = dz1.add(rev2);
- byte[] file2 = access0.applyAppendSpec(app2);
+ byte[] file2 = access1.applyAppendSpec(app2);
dump("file2=", file2);
ByteArrayAccess access2 = new ByteArrayAccess(file2);
@@ -110,14 +112,12 @@ public void test_add_get_with(byte[] file0, ByteBuffer rev1, ByteBuffer rev2) th
//======================================================================
public static String toString(ByteBuffer buf) {
- int save_pos = buf.position();
- String r = new String(DeltaZip.toByteArray(buf));
- buf.position(save_pos);
+ String r = new String(DeltaZip.allToByteArray(buf.duplicate()));
return r;
}
public static void dump(String s, ByteBuffer buf) {
- dump(s, DeltaZip.toByteArray(buf));
+ dump(s, DeltaZip.allToByteArray(buf.duplicate()));
}
public static void dump(String s, byte[] buf) {

0 comments on commit d6d87db

Please sign in to comment.