// TODO: broadcastNodeExpire? then we can purge the // known-stale cache entries... // MOCK: in a real env you have to hit the wire // (send this query to all remote nodes // concurrently): internal virtual TopDocs SearchNode(int nodeID, long[] nodeVersions, Query q, Sort sort, int numHits, ScoreDoc searchAfter) { NodeState.ShardIndexSearcher s = m_nodes[nodeID].Acquire(nodeVersions); try { if (sort is null) { if (searchAfter != null) { return(s.LocalSearchAfter(searchAfter, q, numHits)); } else { return(s.LocalSearch(q, numHits)); } } else { if (Debugging.AssertsEnabled) { Debugging.Assert(searchAfter is null); // not supported yet } return(s.LocalSearch(q, numHits, sort)); } } finally { NodeState.Release(s); // LUCENENET: made static per CA1822 and eliminated array lookup } }
public override TopDocs SearchAfter(ScoreDoc after, Query query, int numHits) { TopDocs[] shardHits = new TopDocs[nodeVersions.Length]; // results are merged in that order: score, shardIndex, doc. therefore we set // after to after.Score and depending on the nodeID we set doc to either: // - not collect any more documents with that score (only with worse score) // - collect more documents with that score (and worse) following the last collected document // - collect all documents with that score (and worse) ScoreDoc shardAfter = new ScoreDoc(after.Doc, after.Score); for (int nodeID = 0; nodeID < nodeVersions.Length; nodeID++) { if (nodeID < after.ShardIndex) { // all documents with after.Score were already collected, so collect // only documents with worse scores. NodeState.ShardIndexSearcher s = outerInstance.outerInstance.m_nodes[nodeID].Acquire(nodeVersions); try { // Setting after.Doc to reader.MaxDoc-1 is a way to tell // TopScoreDocCollector that no more docs with that score should // be collected. note that in practice the shard which sends the // request to a remote shard won't have reader.MaxDoc at hand, so // it will send some arbitrary value which will be fixed on the // other end. shardAfter.Doc = s.IndexReader.MaxDoc - 1; } finally { Release(s); // LUCENENET: Made static per CA1822 and eliminated array lookup } } else if (nodeID == after.ShardIndex) { // collect all documents following the last collected doc with // after.Score + documents with worse scores. shardAfter.Doc = after.Doc; } else { // all documents with after.Score (and worse) should be collected // because they didn't make it to top-N in the previous round. shardAfter.Doc = -1; } if (nodeID == MyNodeID) { // My node; run using local shard searcher we // already aquired: shardHits[nodeID] = LocalSearchAfter(shardAfter, query, numHits); } else { shardHits[nodeID] = outerInstance.outerInstance.SearchNode(nodeID, nodeVersions, query, null, numHits, shardAfter); } //System.out.println(" node=" + nodeID + " totHits=" + shardHits[nodeID].TotalHits); } // Merge: return(TopDocs.Merge(null, numHits, shardHits)); }
// TODO: broadcastNodeExpire? then we can purge the // known-stale cache entries... // MOCK: in a real env you have to hit the wire // (send this query to all remote nodes // concurrently): internal virtual TopDocs SearchNode(int nodeID, long[] nodeVersions, Query q, Sort sort, int numHits, ScoreDoc searchAfter) { NodeState.ShardIndexSearcher s = m_nodes[nodeID].Acquire(nodeVersions); try { if (sort == null) { if (searchAfter != null) { return(s.LocalSearchAfter(searchAfter, q, numHits)); } else { return(s.LocalSearch(q, numHits)); } } else { Debug.Assert(searchAfter == null); // not supported yet return(s.LocalSearch(q, numHits, sort)); } } finally { m_nodes[nodeID].Release(s); } }
private PreviousSearchState AssertSame(IndexSearcher mockSearcher, NodeState.ShardIndexSearcher shardSearcher, Query q, Sort sort, PreviousSearchState state) { int numHits = TestUtil.NextInt(Random(), 1, 100); if (state != null && state.SearchAfterLocal == null) { // In addition to what we last searched: numHits += state.NumHitsPaged; } if (VERBOSE) { Console.WriteLine("TEST: query=" + q + " sort=" + sort + " numHits=" + numHits); if (state != null) { Console.WriteLine(" prev: searchAfterLocal=" + state.SearchAfterLocal + " searchAfterShard=" + state.SearchAfterShard + " numHitsPaged=" + state.NumHitsPaged); } } // Single (mock local) searcher: TopDocs hits; if (sort == null) { if (state != null && state.SearchAfterLocal != null) { hits = mockSearcher.SearchAfter(state.SearchAfterLocal, q, numHits); } else { hits = mockSearcher.Search(q, numHits); } } else { hits = mockSearcher.Search(q, numHits, sort); } // Shard searcher TopDocs shardHits; if (sort == null) { if (state != null && state.SearchAfterShard != null) { shardHits = shardSearcher.SearchAfter(state.SearchAfterShard, q, numHits); } else { shardHits = shardSearcher.Search(q, numHits); } } else { shardHits = shardSearcher.Search(q, numHits, sort); } int numNodes = shardSearcher.NodeVersions.Length; int[] @base = new int[numNodes]; IList <IndexReaderContext> subs = mockSearcher.TopReaderContext.Children; Assert.AreEqual(numNodes, subs.Count); for (int nodeID = 0; nodeID < numNodes; nodeID++) { @base[nodeID] = subs[nodeID].DocBaseInParent; } if (VERBOSE) { /* * for(int shardID=0;shardID<shardSearchers.Length;shardID++) { * System.out.println(" shard=" + shardID + " maxDoc=" + shardSearchers[shardID].searcher.getIndexReader().MaxDoc); * } */ Console.WriteLine(" single searcher: " + hits.TotalHits + " totalHits maxScore=" + hits.MaxScore); for (int i = 0; i < hits.ScoreDocs.Length; i++) { ScoreDoc sd = hits.ScoreDocs[i]; Console.WriteLine(" doc=" + sd.Doc + " score=" + sd.Score); } Console.WriteLine(" shard searcher: " + shardHits.TotalHits + " totalHits maxScore=" + shardHits.MaxScore); for (int i = 0; i < shardHits.ScoreDocs.Length; i++) { ScoreDoc sd = shardHits.ScoreDocs[i]; Console.WriteLine(" doc=" + sd.Doc + " (rebased: " + (sd.Doc + @base[sd.ShardIndex]) + ") score=" + sd.Score + " shard=" + sd.ShardIndex); } } int numHitsPaged; if (state != null && state.SearchAfterLocal != null) { numHitsPaged = hits.ScoreDocs.Length; if (state != null) { numHitsPaged += state.NumHitsPaged; } } else { numHitsPaged = hits.ScoreDocs.Length; } bool moreHits; ScoreDoc bottomHit; ScoreDoc bottomHitShards; if (numHitsPaged < hits.TotalHits) { // More hits to page through moreHits = true; if (sort == null) { bottomHit = hits.ScoreDocs[hits.ScoreDocs.Length - 1]; ScoreDoc sd = shardHits.ScoreDocs[shardHits.ScoreDocs.Length - 1]; // Must copy because below we rebase: bottomHitShards = new ScoreDoc(sd.Doc, sd.Score, sd.ShardIndex); if (VERBOSE) { Console.WriteLine(" save bottomHit=" + bottomHit); } } else { bottomHit = null; bottomHitShards = null; } } else { Assert.AreEqual(hits.TotalHits, numHitsPaged); bottomHit = null; bottomHitShards = null; moreHits = false; } // Must rebase so Assert.AreEqual passes: for (int hitID = 0; hitID < shardHits.ScoreDocs.Length; hitID++) { ScoreDoc sd = shardHits.ScoreDocs[hitID]; sd.Doc += @base[sd.ShardIndex]; } TestUtil.AssertEquals(hits, shardHits); if (moreHits) { // Return a continuation: return(new PreviousSearchState(q, sort, bottomHit, bottomHitShards, shardSearcher.NodeVersions, numHitsPaged)); } else { return(null); } }