Added ParallelMultiSearcher. · apache/lucene-solr@b1541ce (original) (raw)

``

1

`+

package org.apache.lucene.search;

`

``

2

+

``

3

`+

/* ====================================================================

`

``

4

`+

`

``

5

`+

`

``

6

`+

`

``

7

`+

`

``

8

`+

`

``

9

`+

`

``

10

`+

`

``

11

`+

`

``

12

`+

`

``

13

`+

`

``

14

`+

`

``

15

`+

`

``

16

`+

`

``

17

`+

`

``

18

`+

`

``

19

`+

`

``

20

`+

`

``

21

`+

`

``

22

`+

`

``

23

`+

`

``

24

`+

`

``

25

`+

`

``

26

`+

`

``

27

`+

`

``

28

`+

`

``

29

`+

`

``

30

`+

`

``

31

`+

`

``

32

`+

`

``

33

`+

`

``

34

`+

`

``

35

`+

`

``

36

`+

`

``

37


 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED

``

38

`+

`

``

39

`+

`

``

40

`+

`

``

41

`+

`

``

42

`+

`

``

43

`+

`

``

44

`+

`

``

45

`+

`

``

46

`+

`

``

47

`+

`

``

48

`+

`

``

49

`+

`

``

50

`+

`

``

51

`+

`

``

52

`+

`

``

53

`+

`

``

54

`+

`

``

55

`+

*/

`

``

56

+

``

57

`+

import java.io.IOException;

`

``

58

+

``

59

`+

import org.apache.lucene.index.Term;

`

``

60

+

``

61

`+

/** Implements parallel search over a set of Searchables.

`

``

62

`+

`

``

63

`+

`

``

64

`+

`

``

65

`+

*/

`

``

66

`+

public class ParallelMultiSearcher extends MultiSearcher {

`

``

67

+

``

68

`+

private Searchable[] searchables;

`

``

69

`+

private int[] starts;

`

``

70

+

``

71

`+

/** Creates a searcher which searches searchables. */

`

``

72

`+

public ParallelMultiSearcher(Searchable[] searchables) throws IOException {

`

``

73

`+

super(searchables);

`

``

74

`+

this.searchables=searchables;

`

``

75

`+

this.starts=getStarts();

`

``

76

`+

}

`

``

77

+

``

78

`+

/**

`

``

79

`+

`

``

80

`+

*/

`

``

81

`+

public int docFreq(Term term) throws IOException {

`

``

82

`+

int docFreq = 0;

`

``

83

`+

for (int i = 0; i < searchables.length; i++)

`

``

84

`+

docFreq += searchables[i].docFreq(term);

`

``

85

`+

return docFreq;

`

``

86

`+

}

`

``

87

+

``

88

`+

/**

`

``

89

`+

`

``

90

`+

`

``

91

`+

`

``

92

`+

*/

`

``

93

`+

public TopDocs search(Query query, Filter filter, int nDocs)

`

``

94

`+

throws IOException {

`

``

95

`+

HitQueue hq = new HitQueue(nDocs);

`

``

96

`+

int totalHits = 0;

`

``

97

`+

MultiSearcherThread[] msta =

`

``

98

`+

new MultiSearcherThread[searchables.length];

`

``

99

`+

for (int i = 0; i < searchables.length; i++) { // search each searcher

`

``

100

`+

// Assume not too many searchables and cost of creating a thread is by far inferior to a search

`

``

101

`+

msta[i] =

`

``

102

`+

new MultiSearcherThread(

`

``

103

`+

searchables[i],

`

``

104

`+

query,

`

``

105

`+

filter,

`

``

106

`+

nDocs,

`

``

107

`+

hq,

`

``

108

`+

i,

`

``

109

`+

starts,

`

``

110

`+

"MultiSearcher thread #" + (i + 1));

`

``

111

`+

msta[i].start();

`

``

112

`+

}

`

``

113

+

``

114

`+

for (int i = 0; i < searchables.length; i++) {

`

``

115

`+

try {

`

``

116

`+

msta[i].join();

`

``

117

`+

} catch (InterruptedException ie) {

`

``

118

`+

; // TODO: what should we do with this???

`

``

119

`+

}

`

``

120

`+

IOException ioe = msta[i].getIOException();

`

``

121

`+

if (ioe == null) {

`

``

122

`+

totalHits += msta[i].hits();

`

``

123

`+

} else {

`

``

124

`+

// if one search produced an IOException, rethrow it

`

``

125

`+

throw ioe;

`

``

126

`+

}

`

``

127

`+

}

`

``

128

+

``

129

`+

ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()];

`

``

130

`+

for (int i = hq.size() - 1; i >= 0; i--) // put docs in array

`

``

131

`+

scoreDocs[i] = (ScoreDoc) hq.pop();

`

``

132

+

``

133

`+

return new TopDocs(totalHits, scoreDocs);

`

``

134

`+

}

`

``

135

+

``

136

`+

/** Lower-level search API.

`

``

137

`+

`

``

138

`+

`

``

139

`+

`

``

140

`+

`

``

141

`+

`

``

142

`+

`

``

143

`+

`

``

144

`+

`

``

145

`+

`

``

146

`+

`

``

147

`+

`

``

148

`+

`

``

149

`+

*

`

``

150

`+

`

``

151

`+

*/

`

``

152

`+

public void search(Query query, Filter filter, final HitCollector results)

`

``

153

`+

throws IOException {

`

``

154

`+

for (int i = 0; i < searchables.length; i++) {

`

``

155

+

``

156

`+

final int start = starts[i];

`

``

157

+

``

158

`+

searchables[i].search(query, filter, new HitCollector() {

`

``

159

`+

public void collect(int doc, float score) {

`

``

160

`+

results.collect(doc + start, score);

`

``

161

`+

}

`

``

162

`+

});

`

``

163

+

``

164

`+

}

`

``

165

`+

}

`

``

166

+

``

167

`+

/*

`

``

168

`+

`

``

169

`+

`

``

170

`+

*/

`

``

171

`+

public Query rewrite(Query original) throws IOException {

`

``

172

`+

Query[] queries = new Query[searchables.length];

`

``

173

`+

for (int i = 0; i < searchables.length; i++) {

`

``

174

`+

queries[i] = searchables[i].rewrite(original);

`

``

175

`+

}

`

``

176

`+

return original.combine(queries);

`

``

177

`+

}

`

``

178

+

``

179

`+

}

`

``

180

+

``

181

`+

/**

`

``

182

`+

`

``

183

`+

*/

`

``

184

`+

class MultiSearcherThread extends Thread {

`

``

185

+

``

186

`+

private Searchable searchable;

`

``

187

`+

private Query query;

`

``

188

`+

private Filter filter;

`

``

189

`+

private int nDocs;

`

``

190

`+

private int hits;

`

``

191

`+

private TopDocs docs;

`

``

192

`+

private int i;

`

``

193

`+

private HitQueue hq;

`

``

194

`+

private int[] starts;

`

``

195

`+

private IOException ioe;

`

``

196

+

``

197

`+

public MultiSearcherThread(

`

``

198

`+

Searchable searchable,

`

``

199

`+

Query query,

`

``

200

`+

Filter filter,

`

``

201

`+

int nDocs,

`

``

202

`+

HitQueue hq,

`

``

203

`+

int i,

`

``

204

`+

int[] starts,

`

``

205

`+

String name) {

`

``

206

`+

super(name);

`

``

207

`+

this.searchable = searchable;

`

``

208

`+

this.query = query;

`

``

209

`+

this.filter = filter;

`

``

210

`+

this.nDocs = nDocs;

`

``

211

`+

this.hq = hq;

`

``

212

`+

this.i = i;

`

``

213

`+

this.starts = starts;

`

``

214

`+

}

`

``

215

+

``

216

`+

public void run() {

`

``

217

`+

try {

`

``

218

`+

docs = searchable.search(query, filter, nDocs);

`

``

219

`+

}

`

``

220

`+

// Store the IOException for later use by the caller of this thread

`

``

221

`+

catch (IOException ioe) {

`

``

222

`+

this.ioe = ioe;

`

``

223

`+

}

`

``

224

`+

if (ioe == null) {

`

``

225

`+

ScoreDoc[] scoreDocs = docs.scoreDocs;

`

``

226

`+

for (int j = 0;

`

``

227

`+

j < scoreDocs.length;

`

``

228

`+

j++) { // merge scoreDocs into hq

`

``

229

`+

ScoreDoc scoreDoc = scoreDocs[j];

`

``

230

`+

scoreDoc.doc += starts[i]; // convert doc

`

``

231

`+

//it would be so nice if we had a thread-safe insert

`

``

232

`+

synchronized (hq) {

`

``

233

`+

if (!hq.insert(scoreDoc))

`

``

234

`+

break;

`

``

235

`+

} // no more scores > minScore

`

``

236

`+

}

`

``

237

`+

}

`

``

238

`+

}

`

``

239

+

``

240

`+

public int hits() {

`

``

241

`+

return docs.totalHits;

`

``

242

`+

}

`

``

243

+

``

244

`+

public IOException getIOException() {

`

``

245

`+

return ioe;

`

``

246

`+

}

`

``

247

+

``

248

`+

}

`