comparison src/org/tmatesoft/hg/internal/RevlogDump.java @ 392:656a6c1346ff

Extra debug option (dumpDataStats) and patch structure decoding for RevlogDump debug utility
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 21 Feb 2012 18:25:15 +0100
parents d45ad07dc94c
children f52ca9530774
comparison
equal deleted inserted replaced
391:856517285256 392:656a6c1346ff
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.BufferedInputStream; 19 import java.io.BufferedInputStream;
20 import java.io.ByteArrayInputStream;
20 import java.io.DataInput; 21 import java.io.DataInput;
21 import java.io.DataInputStream; 22 import java.io.DataInputStream;
22 import java.io.File; 23 import java.io.File;
23 import java.io.FileInputStream; 24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.io.UnsupportedEncodingException;
24 import java.math.BigInteger; 27 import java.math.BigInteger;
25 import java.nio.ByteBuffer; 28 import java.nio.ByteBuffer;
26 import java.nio.channels.FileChannel; 29 import java.nio.channels.FileChannel;
27 import java.util.zip.Inflater; 30 import java.util.zip.Inflater;
28 31
43 public static void main(String[] args) throws Exception { 46 public static void main(String[] args) throws Exception {
44 String repo = "/temp/hg/hello/.hg/"; 47 String repo = "/temp/hg/hello/.hg/";
45 String filename = "store/00changelog.i"; 48 String filename = "store/00changelog.i";
46 // String filename = "store/data/hello.c.i"; 49 // String filename = "store/data/hello.c.i";
47 // String filename = "store/data/docs/readme.i"; 50 // String filename = "store/data/docs/readme.i";
48 boolean dumpData = true; 51 boolean dumpDataFull = true;
52 boolean dumpDataStats = false;
49 if (args.length > 1) { 53 if (args.length > 1) {
50 repo = args[0]; 54 repo = args[0];
51 filename = args[1]; 55 filename = args[1];
52 dumpData = args.length > 2 ? "dumpData".equals(args[2]) : false; 56 dumpDataFull = args.length > 2 ? "dumpData".equals(args[2]) : false;
57 dumpDataStats = args.length > 2 ? "dumpDataStats".equals(args[2]) : false;
53 } 58 }
59 final boolean needRevData = dumpDataFull || dumpDataStats;
54 // 60 //
55 DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(new File(repo, filename)))); 61 DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(new File(repo, filename))));
56 DataInput di = dis; 62 DataInput di = dis;
57 dis.mark(10); 63 dis.mark(10);
58 int versionField = di.readInt(); 64 int versionField = di.readInt();
60 final int INLINEDATA = 1 << 16; 66 final int INLINEDATA = 1 << 16;
61 67
62 final boolean inlineData = (versionField & INLINEDATA) != 0; 68 final boolean inlineData = (versionField & INLINEDATA) != 0;
63 System.out.printf("%#8x, inline: %b\n", versionField, inlineData); 69 System.out.printf("%#8x, inline: %b\n", versionField, inlineData);
64 FileChannel dataStream = null; 70 FileChannel dataStream = null;
65 if (!inlineData && dumpData) { 71 if (!inlineData && needRevData) {
66 dataStream = new FileInputStream(new File(repo, filename.substring(0, filename.length()-2) + ".d")).getChannel(); 72 dataStream = new FileInputStream(new File(repo, filename.substring(0, filename.length()-2) + ".d")).getChannel();
67 } 73 }
68 System.out.println("Index Offset Flags Packed Actual Base Rev Link Rev Parent1 Parent2 nodeid"); 74 System.out.println("Index Offset Flags Packed Actual Base Rev Link Rev Parent1 Parent2 nodeid");
69 int entryIndex = 0; 75 int entryIndex = 0;
70 while (dis.available() > 0) { 76 while (dis.available() > 0) {
86 System.out.printf("%4d:%14d %6X %10d %10d %10d %10d %8d %8d %040x\n", entryIndex, offset, flags, compressedLen, actualLen, baseRevision, linkRevision, parent1Revision, parent2Revision, new BigInteger(buf)); 92 System.out.printf("%4d:%14d %6X %10d %10d %10d %10d %8d %8d %040x\n", entryIndex, offset, flags, compressedLen, actualLen, baseRevision, linkRevision, parent1Revision, parent2Revision, new BigInteger(buf));
87 String resultString; 93 String resultString;
88 byte[] data = new byte[compressedLen]; 94 byte[] data = new byte[compressedLen];
89 if (inlineData) { 95 if (inlineData) {
90 di.readFully(data); 96 di.readFully(data);
91 } else if (dumpData) { 97 } else if (needRevData) {
92 dataStream.position(offset); 98 dataStream.position(offset);
93 dataStream.read(ByteBuffer.wrap(data)); 99 dataStream.read(ByteBuffer.wrap(data));
94 } 100 }
95 if (dumpData) { 101 if (needRevData) {
96 if (compressedLen == 0) { 102 if (compressedLen == 0) {
97 resultString = "<NO DATA>"; 103 resultString = "<NO DATA>";
98 } else { 104 } else {
99 if (data[0] == 0x78 /* 'x' */) { 105 if (data[0] == 0x78 /* 'x' */) {
100 Inflater zlib = new Inflater(); 106 Inflater zlib = new Inflater();
101 zlib.setInput(data, 0, compressedLen); 107 zlib.setInput(data, 0, compressedLen);
102 byte[] result = new byte[actualLen*2]; 108 byte[] result = new byte[actualLen*2];
103 int resultLen = zlib.inflate(result); 109 int resultLen = zlib.inflate(result);
104 zlib.end(); 110 zlib.end();
105 resultString = new String(result, 0, resultLen, "UTF-8"); 111 resultString = buildString(result, 0, resultLen, baseRevision != entryIndex, dumpDataFull);
106 } else if (data[0] == 0x75 /* 'u' */) { 112 } else if (data[0] == 0x75 /* 'u' */) {
107 resultString = new String(data, 1, data.length - 1, "UTF-8"); 113 resultString = buildString(data, 1, data.length - 1, baseRevision != entryIndex, dumpDataFull);
108 } else { 114 } else {
109 resultString = new String(data); 115 resultString = buildString(data, 0, data.length, baseRevision != entryIndex, dumpDataFull);
110 } 116 }
111 } 117 }
112 System.out.println(resultString); 118 System.out.println(resultString);
113 } 119 }
114 entryIndex++; 120 entryIndex++;
117 if (dataStream != null) { 123 if (dataStream != null) {
118 dataStream.close(); 124 dataStream.close();
119 } 125 }
120 // 126 //
121 } 127 }
128
129 private static String buildString(byte[] data, int offset, int len, boolean isPatch, boolean completeDataDump) throws IOException, UnsupportedEncodingException {
130 if (isPatch) {
131 DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data, offset, len));
132 StringBuilder sb = new StringBuilder();
133 sb.append("<PATCH>:\n");
134 while (dis.available() > 0) {
135 int s = dis.readInt();
136 int e = dis.readInt();
137 int l = dis.readInt();
138 sb.append(String.format("%d..%d, %d", s, e, l));
139 if (completeDataDump) {
140 byte[] src = new byte[l];
141 dis.read(src, 0, l);
142 sb.append(":");
143 sb.append(new String(src, 0, l, "UTF-8"));
144 } else {
145 dis.skipBytes(l);
146 }
147 sb.append('\n');
148 }
149 return sb.toString();
150 } else {
151 if (completeDataDump) {
152 return new String(data, offset, len, "UTF-8");
153 }
154 return String.format("<DATA>:%d bytes", len-offset);
155 }
156 }
122 } 157 }