Mercurial > jhg
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 } |
