comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 196:e2115da4cf6a

Pool objects to avoid memory polution with duplicates
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Mon, 18 Apr 2011 18:04:24 +0200
parents d5268ca7715b
children 047b1dec7a04
comparison
equal deleted inserted replaced
195:c9b305df0b89 196:e2115da4cf6a
19 import java.io.IOException; 19 import java.io.IOException;
20 20
21 import org.tmatesoft.hg.core.HgBadStateException; 21 import org.tmatesoft.hg.core.HgBadStateException;
22 import org.tmatesoft.hg.core.Nodeid; 22 import org.tmatesoft.hg.core.Nodeid;
23 import org.tmatesoft.hg.internal.DataAccess; 23 import org.tmatesoft.hg.internal.DataAccess;
24 import org.tmatesoft.hg.internal.Pool;
24 import org.tmatesoft.hg.internal.RevlogStream; 25 import org.tmatesoft.hg.internal.RevlogStream;
25 26
26 27
27 /** 28 /**
28 * 29 *
34 /*package-local*/ HgManifest(HgRepository hgRepo, RevlogStream content) { 35 /*package-local*/ HgManifest(HgRepository hgRepo, RevlogStream content) {
35 super(hgRepo, content); 36 super(hgRepo, content);
36 } 37 }
37 38
38 public void walk(int start, int end, final Inspector inspector) { 39 public void walk(int start, int end, final Inspector inspector) {
39 RevlogStream.Inspector insp = new RevlogStream.Inspector() { 40 if (inspector == null) {
40 41 throw new IllegalArgumentException();
41 private boolean gtg = true; // good to go 42 }
42 43 content.iterate(start, end, true, new ManifestParser(inspector));
43 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) {
44 if (!gtg) {
45 return;
46 }
47 try {
48 gtg = gtg && inspector.begin(revisionNumber, new Nodeid(nodeid, true));
49 int i;
50 String fname = null;
51 String flags = null;
52 Nodeid nid = null;
53 byte[] data = da.byteArray();
54 for (i = 0; gtg && i < actualLen; i++) {
55 int x = i;
56 for( ; data[i] != '\n' && i < actualLen; i++) {
57 if (fname == null && data[i] == 0) {
58 fname = new String(data, x, i - x);
59 x = i+1;
60 }
61 }
62 if (i < actualLen) {
63 assert data[i] == '\n';
64 int nodeidLen = i - x < 40 ? i-x : 40;
65 nid = Nodeid.fromAscii(data, x, nodeidLen);
66 if (nodeidLen + x < i) {
67 // 'x' and 'l' for executable bits and symlinks?
68 // hg --debug manifest shows 644 for each regular file in my repo
69 flags = new String(data, x + nodeidLen, i-x-nodeidLen);
70 }
71 gtg = gtg && inspector.next(nid, fname, flags);
72 }
73 nid = null;
74 fname = flags = null;
75 }
76 gtg = gtg && inspector.end(revisionNumber);
77 } catch (IOException ex) {
78 throw new HgBadStateException(ex);
79 }
80 }
81 };
82 content.iterate(start, end, true, insp);
83 } 44 }
84 45
85 public interface Inspector { 46 public interface Inspector {
86 boolean begin(int revision, Nodeid nid); 47 boolean begin(int revision, Nodeid nid);
87 boolean next(Nodeid nid, String fname, String flags); 48 boolean next(Nodeid nid, String fname, String flags);
88 boolean end(int revision); 49 boolean end(int revision);
89 } 50 }
51
52 private static class ManifestParser implements RevlogStream.Inspector {
53 private boolean gtg = true; // good to go
54 private final Inspector inspector;
55 private final Pool<Nodeid> nodeidPool;
56 private final Pool<String> fnamePool;
57 private final Pool<String> flagsPool;
58
59 public ManifestParser(Inspector delegate) {
60 assert delegate != null;
61 inspector = delegate;
62 nodeidPool = new Pool<Nodeid>();
63 fnamePool = new Pool<String>();
64 flagsPool = new Pool<String>();
65 }
66
67 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) {
68 if (!gtg) {
69 return;
70 }
71 try {
72 gtg = gtg && inspector.begin(revisionNumber, new Nodeid(nodeid, true));
73 int i;
74 String fname = null;
75 String flags = null;
76 Nodeid nid = null;
77 byte[] data = da.byteArray();
78 for (i = 0; gtg && i < actualLen; i++) {
79 int x = i;
80 for( ; data[i] != '\n' && i < actualLen; i++) {
81 if (fname == null && data[i] == 0) {
82 fname = fnamePool.unify(new String(data, x, i - x));
83 x = i+1;
84 }
85 }
86 if (i < actualLen) {
87 assert data[i] == '\n';
88 int nodeidLen = i - x < 40 ? i-x : 40;
89 nid = nodeidPool.unify(Nodeid.fromAscii(data, x, nodeidLen));
90 if (nodeidLen + x < i) {
91 // 'x' and 'l' for executable bits and symlinks?
92 // hg --debug manifest shows 644 for each regular file in my repo
93 flags = flagsPool.unify(new String(data, x + nodeidLen, i-x-nodeidLen));
94 }
95 gtg = gtg && inspector.next(nid, fname, flags);
96 }
97 nid = null;
98 fname = flags = null;
99 }
100 gtg = gtg && inspector.end(revisionNumber);
101 } catch (IOException ex) {
102 throw new HgBadStateException(ex);
103 }
104 }
105 }
90 } 106 }