r23221 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r23220‎ | r23221 | r23222 >
Date:14:26, 22 June 2007
Author:rainman
Status:old
Tags:
Comment:
Don't use single shared IndexSearcher, but a pool of IndexSearchers.

Using single instance will make queries serialized on multi-processor
systems, since they will share the same RandomAccessFile instance.

I suspect the same issue caused serialization of queries on mono version
as well.
Modified paths:
  • /trunk/lucene-search-2.0/src/org/wikimedia/lsearch/search/SearcherCache.java (modified) (history)
  • /trunk/lucene-search-2.0/src/org/wikimedia/lsearch/search/UpdateThread.java (modified) (history)

Diff [purge]

Index: trunk/lucene-search-2.0/src/org/wikimedia/lsearch/search/SearcherCache.java
@@ -5,6 +5,8 @@
66 import java.rmi.RemoteException;
77 import java.rmi.registry.LocateRegistry;
88 import java.rmi.registry.Registry;
 9+import java.util.ArrayList;
 10+import java.util.Arrays;
911 import java.util.Collections;
1012 import java.util.HashSet;
1113 import java.util.Hashtable;
@@ -52,19 +54,54 @@
5355 log.debug("Closing searchable "+s);
5456 s.close();
5557 } catch (IOException e) {
56 - log.warn("I/O error closing searchable "+s);
 58+ log.warn("I/O error closing searchables "+s);
5759 }
 60+ }
 61+ }
 62+
 63+ public static final int OPEN_SEARCHERS = 4;
 64+
 65+ /** Holds OPEN_SEARCHERS num of index searchers, for multiprocessor workstations */
 66+ public static class SearcherPool {
 67+ IndexSearcherMul searchers[] = new IndexSearcherMul[OPEN_SEARCHERS];
 68+
 69+ SearcherPool(IndexId iid, String path) throws IOException {
 70+ for(int i=0;i<OPEN_SEARCHERS;i++){
 71+ searchers[i] = open(iid, path);
 72+ }
5873 }
5974
 75+ private IndexSearcherMul open(IndexId iid, String path) throws IOException {
 76+ IndexSearcherMul searcher = null;
 77+ log.debug("Openning local index for "+iid);
 78+ if(!iid.isMySearch())
 79+ throw new IOException(iid+" is not searched by this host.");
 80+ if(iid.isLogical())
 81+ throw new IOException(iid+" will not open logical index.");
 82+ try {
 83+ searcher = new IndexSearcherMul(path);
 84+ searcher.setSimilarity(new WikiSimilarity());
 85+ } catch (IOException e) {
 86+ // tell registry this is not a good index
 87+ IndexRegistry.getInstance().invalidateCurrent(iid);
 88+ log.error("I/O Error opening index at path "+iid.getCanonicalSearchPath()+" : "+e.getMessage());
 89+ throw e;
 90+ }
 91+ return searcher;
 92+ }
6093
61 - }
 94+ IndexSearcherMul get(){
 95+ return searchers[(int)(Math.random()*searchers.length)];
 96+ }
 97+
 98+ }
6299 static org.apache.log4j.Logger log = Logger.getLogger(SearcherCache.class);
63100 /** dbrole@host -> RemoteSearchable */
64101 protected Hashtable<String,CachedSearchable> remoteCache;
65102 /** dbrole -> set(dbrole@host) */
66103 protected Hashtable<String,Set<String>> remoteKeys;
67104 /** dbrole -> IndexSearcher */
68 - protected Hashtable<String,IndexSearcherMul> localCache;
 105+ protected Hashtable<String,SearcherPool> localCache;
69106 /** searchable -> host */
70107 protected Hashtable<Searchable,String> searchableHost;
71108
@@ -125,6 +162,14 @@
126163 }
127164 }
128165
 166+ /** Get searcher from local cache, or if doesn't exist null */
 167+ protected IndexSearcherMul fromLocalCache(String key){
 168+ SearcherPool pool = localCache.get(key);
 169+ if(pool != null)
 170+ return pool.get();
 171+ return null;
 172+ }
 173+
129174 /**
130175 * Returns a searchable from cache. If the searchable is not
131176 * in cache, the method will create it (via local call or RMI)
@@ -135,7 +180,7 @@
136181 public Searchable getSearchable(IndexId iid, String host) throws NotBoundException, IOException{
137182 Searchable s = null;
138183 if(global.isLocalhost(host))
139 - s = localCache.get(makeKey(iid,host));
 184+ s = fromLocalCache(iid.toString());
140185 else
141186 s = remoteCache.get(makeKey(iid,host));
142187
@@ -152,7 +197,7 @@
153198 * @throws IOException
154199 */
155200 public IndexSearcherMul getLocalSearcher(IndexId iid) throws IOException{
156 - IndexSearcherMul s = localCache.get(iid.toString());
 201+ IndexSearcherMul s = fromLocalCache(iid.toString());
157202
158203 if(s == null)
159204 s = addLocalSearcherToCache(iid);
@@ -209,12 +254,13 @@
210255 synchronized(iid){
211256 // make sure some other thread has not opened the searcher
212257 if(localCache.get(iid.toString()) == null){
213 - IndexSearcherMul searcher = getLocal(iid);
214 - localCache.put(iid.toString(),searcher);
215 - searchableHost.put(searcher,"");
216 - return searcher;
 258+ SearcherPool pool = new SearcherPool(iid,iid.getCanonicalSearchPath());
 259+ localCache.put(iid.toString(),pool);
 260+ for(IndexSearcherMul s : pool.searchers)
 261+ searchableHost.put(s,"");
 262+ return pool.get();
217263 } else
218 - return localCache.get(iid.toString());
 264+ return fromLocalCache(iid.toString());
219265 }
220266 }
221267
@@ -255,29 +301,6 @@
256302 }
257303 }
258304
259 - /** Get a local {@link Searchable} object. This function is called only when
260 - * index is openned for the first time (e.g. at startup).
261 - * The preferred way of openning/updating indexes is via {@link UpdateThread}.
262 - */
263 - protected IndexSearcherMul getLocal(IndexId iid) throws IOException{
264 - IndexSearcherMul searcher = null;
265 - log.debug("Openning local index for "+iid);
266 - if(!iid.isMySearch())
267 - throw new IOException(iid+" is not searched by this host.");
268 - if(iid.isLogical())
269 - throw new IOException(iid+" will not open logical index.");
270 - try {
271 - searcher = new IndexSearcherMul(iid.getCanonicalSearchPath());
272 - searcher.setSimilarity(new WikiSimilarity());
273 - } catch (IOException e) {
274 - // tell registry this is not a good index
275 - IndexRegistry.getInstance().invalidateCurrent(iid);
276 - log.error("I/O Error opening index at path "+iid.getCanonicalSearchPath()+" : "+e.getMessage());
277 - throw e;
278 - }
279 - return searcher;
280 - }
281 -
282305 /** make a key for cache hashtables */
283306 protected String makeKey(IndexId iid, String host){
284307 return iid+"@"+host;
@@ -320,11 +343,7 @@
321344 */
322345 public void invalidateSearchable(IndexId iid, String host, SearchableMul rs){
323346 if(global.isLocalhost(host)){
324 - try {
325 - invalidateLocalSearcher(iid,getLocal(iid));
326 - } catch (IOException e) {
327 - // error logged elsewhere
328 - }
 347+ log.error("Should use function invalidateLocalSearcher for local searcher invalidation");
329348 return;
330349 }
331350 String key = makeKey(iid,host);
@@ -372,31 +391,36 @@
373392 * @param iid
374393 * @param searcher
375394 */
376 - public void invalidateLocalSearcher(IndexId iid, IndexSearcherMul searcher){
 395+ public IndexSearcherMul[] invalidateLocalSearcher(IndexId iid, SearcherPool newpool) {
377396 IndexSearcherMul olds;
378 - boolean close = false;
379 - log.debug("Invalidating local searcher for "+iid);
 397+ log.debug("Invalidating local searcher for "+iid);
 398+ ArrayList<SearchableMul> close = new ArrayList<SearchableMul>();
380399 synchronized(lock){
381 - olds = localCache.get(iid.toString());
 400+ SearcherPool oldpool = localCache.get(iid.toString());
382401 // put in the new value
383 - localCache.put(iid.toString(),searcher);
384 - searchableHost.put(searcher,"");
385 - if(olds == null)
386 - return; // no old searcher
387 - searchableHost.remove(olds);
388 - // close the old index searcher (imediatelly, or queue if in use)
389 - SimpleInt useCount = inUse.get(olds);
390 - if(useCount == null || useCount.count == 0)
391 - close = true;
392 - else{
393 - log.debug("Searcher for "+iid+" will be closed after local searches are done.");
 402+ localCache.put(iid.toString(),newpool);
 403+ for(IndexSearcherMul s : newpool.searchers)
 404+ searchableHost.put(s,"");
 405+ if(oldpool == null)
 406+ return newpool.searchers; // no old searcher
 407+ for(IndexSearcherMul s : oldpool.searchers){
 408+ searchableHost.remove(s);
 409+ // close the old index searcher (imediatelly, or queue if in use)
 410+ SimpleInt useCount = inUse.get(s);
 411+ if(useCount == null || useCount.count == 0)
 412+ close.add(s);
 413+ else{
 414+ log.debug("Searcher for "+iid+" will be closed after local searches are done.");
 415+ }
 416+
 417+ closeQueue.add(s);
394418 }
395 -
396 - closeQueue.add(olds);
397419 }
398420 // close outside of sync block
399 - if(close)
400 - closeSearcher(olds);
 421+ for(SearchableMul s : close)
 422+ closeSearcher(s);
 423+
 424+ return newpool.searchers;
401425 }
402426
403427 /** Tell the cache that the searcher is in use */
@@ -461,7 +485,7 @@
462486
463487 protected SearcherCache(){
464488 remoteCache = new Hashtable<String,CachedSearchable>();
465 - localCache = new Hashtable<String,IndexSearcherMul>();
 489+ localCache = new Hashtable<String,SearcherPool>();
466490 deadHosts = Collections.synchronizedSet(new HashSet<SearchHost>());
467491 global = GlobalConfiguration.getInstance();
468492 inUse = new Hashtable<Searchable,SimpleInt>();
Index: trunk/lucene-search-2.0/src/org/wikimedia/lsearch/search/UpdateThread.java
@@ -208,8 +208,7 @@
209209 searchpath.mkdir();
210210
211211 // check if updated index is a valid one (throws an exception on error)
212 - IndexSearcherMul is = new IndexSearcherMul(li.path);
213 - is.setSimilarity(new WikiSimilarity());
 212+ SearcherCache.SearcherPool pool = new SearcherCache.SearcherPool(iid,li.path);
214213
215214 // refresh the symlink
216215 command = "/bin/rm -rf "+iid.getSearchPath();
@@ -221,7 +220,7 @@
222221
223222 // update registry, cache, rmi object
224223 registry.refreshUpdates(iid);
225 - updateCache(is,li);
 224+ updateCache(pool,li);
226225 RMIServer.rebind(iid);
227226 registry.refreshCurrent(li);
228227
@@ -236,11 +235,12 @@
237236 }
238237
239238 /** Update search cache after successful rsync of update version of index */
240 - protected void updateCache(IndexSearcherMul is, LocalIndex li){
 239+ protected void updateCache(SearcherCache.SearcherPool pool, LocalIndex li){
241240 // do some typical queries to preload some lucene caches, pages into memory, etc..
242 - Warmup.warmupIndexSearcher(is,li.iid,true);
 241+ for(IndexSearcherMul is : pool.searchers)
 242+ Warmup.warmupIndexSearcher(is,li.iid,true);
243243 // add to cache
244 - cache.invalidateLocalSearcher(li.iid,is);
 244+ cache.invalidateLocalSearcher(li.iid,pool);
245245 }
246246
247247 protected UpdateThread(){

Status & tagging log