private void UpdateNextGroup(int topN, ShardIter <T> shard) { while (shard.Iter.MoveNext()) { ISearchGroup <T> group = shard.Next(); MergedGroup <T> mergedGroup = groupsSeen.ContainsKey(group.GroupValue) ? groupsSeen[group.GroupValue] : null; bool isNew = mergedGroup == null; //System.out.println(" next group=" + (group.groupValue == null ? "null" : ((BytesRef) group.groupValue).utf8ToString()) + " sort=" + Arrays.toString(group.sortValues)); if (isNew) { // Start a new group: //System.out.println(" new"); mergedGroup = new MergedGroup <T>(group.GroupValue); mergedGroup.MinShardIndex = shard.ShardIndex; Debug.Assert(group.SortValues != null); mergedGroup.TopValues = group.SortValues; groupsSeen[group.GroupValue] = mergedGroup; mergedGroup.IsInQueue = true; queue.Add(mergedGroup); } else if (mergedGroup.IsProcessed) { // This shard produced a group that we already // processed; move on to next group... continue; } else { //System.out.println(" old"); bool competes = false; for (int compIDX = 0; compIDX < groupComp.Comparers.Length; compIDX++) { int cmp = groupComp.Reversed[compIDX] * groupComp.Comparers[compIDX].CompareValues(group.SortValues[compIDX], mergedGroup.TopValues[compIDX]); if (cmp < 0) { // Definitely competes competes = true; break; } else if (cmp > 0) { // Definitely does not compete break; } else if (compIDX == groupComp.Comparers.Length - 1) { if (shard.ShardIndex < mergedGroup.MinShardIndex) { competes = true; } } } //System.out.println(" competes=" + competes); if (competes) { // Group's sort changed -- remove & re-insert if (mergedGroup.IsInQueue) { queue.Remove(mergedGroup); } mergedGroup.TopValues = group.SortValues; mergedGroup.MinShardIndex = shard.ShardIndex; queue.Add(mergedGroup); mergedGroup.IsInQueue = true; } } mergedGroup.Shards.Add(shard); break; } // Prune un-competitive groups: while (queue.Count > topN) { MergedGroup <T> group = queue.Last(); queue.Remove(group); //System.out.println("PRUNE: " + group); group.IsInQueue = false; } }