On 5/12/06, jason rutherglen <[EMAIL PROTECTED]> wrote:
 The locking and referencing is a little bit complex and looks like it can 
easily be screwed up.  Any hints from Solr dev team on how to pass the existing 
into the SolrIndexSearcher?

Yeah, IMO, getSearcher() is the most complex piece of code in Solr...
I reviewed it like 10 times (and found a race condition on the 5th ;-)

_searcher contains the reference to the current searcher, but you need
to grab the searcherLock to make sure that it doesn't go away.

I *think* that the initialization of currSearchHolder could be moved
to earlier in the function.
You just need to make sure that you .decref() it for any possible
error path.  Do something like:

Move this to the very top of the function:
      RefCounted<SolrIndexSearcher> currSearcherHolder=null;

Then at the end of the first sync block (but still in it) get the
refcounted searcher:
         if (_searcher!=null) {
           currSearcherHolder=_searcher;
           currSearcherHolder.incref();
         }

Then get the searcher from the holder where you create the new
searcher, and decref() the currSearchHolder if there are any errors.

   SolrIndexSearcher tmp;
   try {
     if (onDeckSearchers < 1) {
       // should never happen... just a sanity check
       log.severe("ERROR!!! onDeckSearchers is " + onDeckSearchers);
       // reset to 1 (don't bother synchronizing)
       onDeckSearchers=1;
     } else if (onDeckSearchers > 1) {
       log.info("PERFORMANCE WARNING: Overlapping onDeckSearchers=" +
onDeckSearchers);
     }
     SolrIndexSearcher currSearcher = currSearcherHolder==null ? null
: currSearcherHolder.get();  // NEW CODE

     tmp = new SolrIndexSearcher(schema, "main", index_path, true,
currSearcher);
     // The new SolrIndexSearcher should *not* hold onto a reference
to currSearcher past it's constructor.
   } catch (Throwable th) {
     if (currSearcherHolder!=null) currSearchHolder.decref();  // NEW CODE
     synchronized(searcherLock) {
       onDeckSearchers--;
       // notify another waiter to continue... it may succeed
       // and wake any others.
       searcherLock.notify();
     }
     throw new RuntimeException(th);
   }

-Yonik

Reply via email to