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