* no new information can be obtained. E.g. when it's 2, it might be case of [0..4] query with
* [1,2] result, and we need one more query to get element 3.
*/
for (int i =1, j = 0; j < de.entries.size(); i = i<<1, j++) {
int idx = de.headIndex + i;
Nodeid x = de.entries.get(j);
if (!queried.contains(x) && !scheduled.contains(x) && (rootIndex == -1 || rootIndex - de.headIndex > 1)) {
/*queries for elements right before head is senseless, but unless we know head's index, do it anyway*/
toQuery.add(new DataEntry(x, idx, null));
scheduled.add(x);
}
}
}
} while (!datas.isEmpty());
if (!toQuery.isEmpty()) {
totalQueries++;
}
// for each query, create an between request range, keep record Range->DataEntry to know range's start index
LinkedList<HgRemoteRepository.Range> betweenBatch = new LinkedList<HgRemoteRepository.Range>();
HashMap<HgRemoteRepository.Range, DataEntry> rangeToEntry = new HashMap<HgRemoteRepository.Range, DataEntry>();
for (DataEntry de : toQuery) {
queried.add(de.queryHead);
HgRemoteRepository.Range r = new HgRemoteRepository.Range(branchRoot, de.queryHead);
betweenBatch.add(r);
rangeToEntry.put(r, de);
}
if (!betweenBatch.isEmpty()) {
Map<Range, List<Nodeid>> between = remoteRepo.between(betweenBatch);
for (Entry<Range, List<Nodeid>> e : between.entrySet()) {
DataEntry de = rangeToEntry.get(e.getKey());
assert de != null;
de.entries = e.getValue();
if (rootIndex == -1 && de.entries.size() == 1) {
// returned sequence of length 1 means we used element from [head-2] as root
int numberOfElementsExcludingRootAndHead = de.headIndex + 1;
rootIndex = numberOfElementsExcludingRootAndHead + 1;
if (debug) {
System.out.printf("On query %d found out exact number of missing elements: %d\n", totalQueries, numberOfElementsExcludingRootAndHead);
}
}
datas.add(de); // queue up to record result and construct further requests
}
betweenBatch.clear();
rangeToEntry.clear();
}
toQuery.clear();
}
if (rootIndex == -1) {
throw new HgInvalidStateException("Shall not happen, provided between output is correct");
}
result[rootIndex] = branchRoot;
boolean resultOk = true;
LinkedList<Nodeid> fromRootToHead = new LinkedList<Nodeid>();
IntVector missing = new IntVector();
for (int i = 0; i <= rootIndex; i++) {
Nodeid n = result[i];
if (n == null) {
missing.add(i);
resultOk = false;
}
fromRootToHead.addFirst(n); // reverse order