Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgRevisionMap.java @ 657:6334b0267103
ParentChildMap can supply RevisionMap. Refactor ArrayHelper to keep most of sorted/reverse index magic inside
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 04 Jul 2013 20:27:45 +0200 |
parents | 6526d8adbc0f |
children |
comparison
equal
deleted
inserted
replaced
656:a937e63b6e02 | 657:6334b0267103 |
---|---|
16 */ | 16 */ |
17 package org.tmatesoft.hg.repo; | 17 package org.tmatesoft.hg.repo; |
18 | 18 |
19 import static org.tmatesoft.hg.repo.HgRepository.BAD_REVISION; | 19 import static org.tmatesoft.hg.repo.HgRepository.BAD_REVISION; |
20 import static org.tmatesoft.hg.repo.HgRepository.TIP; | 20 import static org.tmatesoft.hg.repo.HgRepository.TIP; |
21 | |
22 import java.util.Arrays; | |
23 | 21 |
24 import org.tmatesoft.hg.core.Nodeid; | 22 import org.tmatesoft.hg.core.Nodeid; |
25 import org.tmatesoft.hg.internal.ArrayHelper; | 23 import org.tmatesoft.hg.internal.ArrayHelper; |
26 import org.tmatesoft.hg.repo.Revlog.RevisionInspector; | 24 import org.tmatesoft.hg.repo.Revlog.RevisionInspector; |
27 | 25 |
58 * in fact, initialization is much slower as it instantiates Nodeids, while #getRevisionIndex | 56 * in fact, initialization is much slower as it instantiates Nodeids, while #getRevisionIndex |
59 * compares directly against byte buffer. Measuring cpython with 70k+ gives 3 times difference (47 vs 171) | 57 * compares directly against byte buffer. Measuring cpython with 70k+ gives 3 times difference (47 vs 171) |
60 * for complete changelog iteration. | 58 * for complete changelog iteration. |
61 */ | 59 */ |
62 | 60 |
61 private final T revlog; | |
63 /* | 62 /* |
64 * XXX 3 * (x * 4) bytes. Can I do better? | 63 * XXX 3 * (x * 4) bytes. Can I do better? |
65 * It seems, yes. Don't need to keep sorted, always can emulate it with indirect access to sequential through sorted2natural. | 64 * It seems, yes. Don't need to keep sorted, always can emulate it with indirect access to sequential through sorted2natural. |
66 * i.e. instead sorted[mid].compareTo(toFind), do sequential[sorted2natural[mid]].compareTo(toFind) | 65 * i.e. instead sorted[mid].compareTo(toFind), do sequential[sorted2natural[mid]].compareTo(toFind) |
67 */ | 66 */ |
68 private Nodeid[] sequential; // natural repository order, childrenOf rely on ordering | 67 private Nodeid[] sequential; // natural repository order |
69 private Nodeid[] sorted; // for binary search | 68 private ArrayHelper<Nodeid> seqWrapper; |
70 private int[] sorted2natural; | |
71 private final T revlog; | |
72 | 69 |
73 public HgRevisionMap(T owner) { | 70 public HgRevisionMap(T owner) { |
74 revlog = owner; | 71 revlog = owner; |
75 } | 72 } |
76 | 73 |
77 public HgRepository getRepo() { | 74 public HgRepository getRepo() { |
78 return revlog.getRepo(); | 75 return revlog.getRepo(); |
79 } | 76 } |
80 | 77 |
81 public void next(int revisionIndex, Nodeid revision, int linkedRevision) { | 78 public void next(int revisionIndex, Nodeid revision, int linkedRevision) { |
82 sequential[revisionIndex] = sorted[revisionIndex] = revision; | 79 sequential[revisionIndex] = revision; |
83 } | 80 } |
84 | 81 |
85 /** | 82 /** |
86 * @return <code>this</code> for convenience. | 83 * @return <code>this</code> for convenience. |
87 */ | 84 */ |
88 public HgRevisionMap<T> init(/*XXX Pool<Nodeid> to reuse nodeids, if possible. */) throws HgRuntimeException { | 85 public HgRevisionMap<T> init(/*XXX Pool<Nodeid> to reuse nodeids, if possible. */) throws HgRuntimeException { |
89 // XXX HgRepository.register((RepoChangeListener) this); // listen to changes in repo, re-init if needed? | 86 // XXX HgRepository.register((RepoChangeListener) this); // listen to changes in repo, re-init if needed? |
90 final int revisionCount = revlog.getRevisionCount(); | 87 final int revisionCount = revlog.getRevisionCount(); |
91 sequential = new Nodeid[revisionCount]; | 88 sequential = new Nodeid[revisionCount]; |
92 sorted = new Nodeid[revisionCount]; | |
93 revlog.indexWalk(0, TIP, this); | 89 revlog.indexWalk(0, TIP, this); |
94 // next is alternative to Arrays.sort(sorted), and build sorted2natural looking up each element of sequential in sorted. | 90 // next is alternative to Arrays.sort(sorted), and build sorted2natural looking up each element of sequential in sorted. |
95 // the way sorted2natural was build is O(n*log n). | 91 // the way sorted2natural was build is O(n*log n). |
96 final ArrayHelper ah = new ArrayHelper(); | 92 seqWrapper = new ArrayHelper<Nodeid>(sequential); |
97 ah.sort(sorted); | 93 seqWrapper.sort(null, true, false); |
98 // note, values in ArrayHelper#getReversed are 1-based indexes, not 0-based | |
99 sorted2natural = ah.getReverse(); | |
100 return this; | 94 return this; |
95 } | |
96 | |
97 /* friendly initializer to use from HgParentChildMap | |
98 /*package*/ void init(ArrayHelper<Nodeid> _seqWrapper) { | |
99 assert _seqWrapper.getData().length == revlog.getRevisionCount(); | |
100 sequential = _seqWrapper.getData(); | |
101 seqWrapper = _seqWrapper; | |
101 } | 102 } |
102 | 103 |
103 public Nodeid revision(int revisionIndex) { | 104 public Nodeid revision(int revisionIndex) { |
104 return sequential[revisionIndex]; | 105 return sequential[revisionIndex]; |
105 } | 106 } |
107 | |
106 public int revisionIndex(Nodeid revision) { | 108 public int revisionIndex(Nodeid revision) { |
107 if (revision == null || revision.isNull()) { | 109 if (revision == null || revision.isNull()) { |
108 return BAD_REVISION; | 110 return BAD_REVISION; |
109 } | 111 } |
110 int x = Arrays.binarySearch(sorted, revision); | 112 return seqWrapper.binarySearch(revision, BAD_REVISION); |
111 if (x < 0) { | |
112 return BAD_REVISION; | |
113 } | |
114 return sorted2natural[x]-1; | |
115 } | 113 } |
116 } | 114 } |