Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgParentChildMap.java @ 672:d2552e6a5af6
Effective update of HgParentChildMap when repository got few revisions added
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Fri, 12 Jul 2013 16:29:06 +0200 |
parents | d25f0324a27a |
children | 19f5167c2155 |
comparison
equal
deleted
inserted
replaced
671:002ed1b2baad | 672:d2552e6a5af6 |
---|---|
14 * the terms of a license other than GNU General Public License | 14 * the terms of a license other than GNU General Public License |
15 * contact TMate Software at support@hg4j.com | 15 * contact TMate Software at support@hg4j.com |
16 */ | 16 */ |
17 package org.tmatesoft.hg.repo; | 17 package org.tmatesoft.hg.repo; |
18 | 18 |
19 import static org.tmatesoft.hg.repo.HgRepository.TIP; | |
20 | |
21 import java.util.ArrayList; | 19 import java.util.ArrayList; |
22 import java.util.Arrays; | 20 import java.util.Arrays; |
23 import java.util.BitSet; | 21 import java.util.BitSet; |
24 import java.util.Collection; | 22 import java.util.Collection; |
25 import java.util.Collections; | 23 import java.util.Collections; |
100 headsBitSet.set(parent2Revision); | 98 headsBitSet.set(parent2Revision); |
101 } | 99 } |
102 } | 100 } |
103 | 101 |
104 /** | 102 /** |
105 * Prepare the map | 103 * Prepare (initialize or update) the map. Once {@link HgParentChildMap} was initialized, it keeps snapshot |
104 * of repository state. New revisions committed to the repository are not visible. To update the map, call | |
105 * {@link #init()} once again, it tries to refresh in effective way, and to bring in only relevant changes. | |
106 * | |
106 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> | 107 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
107 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | 108 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> |
108 */ | 109 */ |
109 public void init() throws HgRuntimeException { | 110 public void init() throws HgRuntimeException { |
110 final int revisionCount = revlog.getRevisionCount(); | 111 final int revisionCount = revlog.getRevisionCount(); |
112 Nodeid[] oldSequential = null, oldFirstParent = null, oldSecondParent = null, oldSorted = null; | |
113 if (sequential != null && sequential.length > 0 && sequential.length < revisionCount) { | |
114 int lastRecordedRevIndex = sequential.length-1; | |
115 if (sequential[lastRecordedRevIndex].equals(revlog.getRevision(lastRecordedRevIndex))) { | |
116 oldSequential = sequential; | |
117 oldFirstParent = firstParent; | |
118 oldSecondParent = secondParent; | |
119 oldSorted = sorted; | |
120 // not sure if there's a benefit in keeping sorted. assume quite some of them | |
121 // might end up on the same place and thus minimize rearrangements | |
122 } | |
123 } | |
111 firstParent = new Nodeid[revisionCount]; | 124 firstParent = new Nodeid[revisionCount]; |
112 // TODO [post 1.1] Branches/merges are less frequent, and most of secondParent would be -1/null, hence | 125 // TODO [post 1.1] Branches/merges are less frequent, and most of secondParent would be -1/null, hence |
113 // IntMap might be better alternative here, but need to carefully analyze (test) whether this brings | 126 // IntMap might be better alternative here, but need to carefully analyze (test) whether this brings |
114 // real improvement (IntMap has 2n capacity, and element lookup is log(n) instead of array's constant). | 127 // real improvement (IntMap has 2n capacity, and element lookup is log(n) instead of array's constant). |
115 // FWIW: in cpython's repo, with 70k+ revisions, there are 2618 values in secondParent | 128 // FWIW: in cpython's repo, with 70k+ revisions, there are 2618 values in secondParent |
116 secondParent = new Nodeid[revisionCount]; | 129 secondParent = new Nodeid[revisionCount]; |
117 // | 130 // |
118 sequential = new Nodeid[revisionCount]; | 131 sequential = new Nodeid[revisionCount]; |
119 sorted = new Nodeid[revisionCount]; | 132 sorted = new Nodeid[revisionCount]; |
120 headsBitSet = new BitSet(revisionCount); | 133 headsBitSet = new BitSet(revisionCount); |
121 revlog.indexWalk(0, TIP, this); | 134 if (oldSequential != null) { |
135 assert oldFirstParent.length == oldSequential.length; | |
136 assert oldSecondParent.length == oldSequential.length; | |
137 assert oldSorted.length == oldSequential.length; | |
138 System.arraycopy(oldSequential, 0, sequential, 0, oldSequential.length); | |
139 System.arraycopy(oldFirstParent, 0, firstParent, 0, oldFirstParent.length); | |
140 System.arraycopy(oldSecondParent, 0, secondParent, 0, oldSecondParent.length); | |
141 System.arraycopy(oldSorted, 0, sorted, 0, oldSorted.length); | |
142 // restore old heads so that new one are calculated correctly | |
143 headsBitSet.set(0, oldSequential.length); | |
144 for (int headIndex : heads.keys()) { | |
145 headsBitSet.clear(headIndex); | |
146 } | |
147 } | |
148 revlog.indexWalk(oldSequential == null ? 0 : oldSequential.length, revisionCount-1, this); | |
122 seqWrapper = new ArrayHelper<Nodeid>(sequential); | 149 seqWrapper = new ArrayHelper<Nodeid>(sequential); |
123 // HgRevisionMap doesn't keep sorted, try alternative here. | 150 // HgRevisionMap doesn't keep sorted, try alternative here. |
124 // reference this.sorted (not only from ArrayHelper) helps to track ownership in hprof/mem dumps | 151 // reference this.sorted (not only from ArrayHelper) helps to track ownership in hprof/mem dumps |
125 seqWrapper.sort(sorted, false, true); | 152 seqWrapper.sort(sorted, false, true); |
126 // no reason to keep BitSet, number of heads is usually small | 153 // no reason to keep BitSet, number of heads is usually small |
127 IntMap<Nodeid> _heads = new IntMap<Nodeid>(headsBitSet.size() - headsBitSet.cardinality()); | 154 IntMap<Nodeid> _heads = new IntMap<Nodeid>(revisionCount - headsBitSet.cardinality()); |
128 int index = 0; | 155 int index = 0; |
129 while (index < sequential.length) { | 156 while (index < sequential.length) { |
130 index = headsBitSet.nextClearBit(index); | 157 index = headsBitSet.nextClearBit(index); |
131 // nextClearBit(length-1) gives length when bit is set, | 158 // nextClearBit(length-1) gives length when bit is set, |
132 // however, last revision can't be a parent of any other, and | 159 // however, last revision can't be a parent of any other, and |