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