You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-commits@lucene.apache.org by ry...@apache.org on 2008/03/09 20:29:07 UTC

svn commit: r635334 - in /lucene/solr/trunk: client/java/solrj/src/org/apache/solr/client/solrj/embedded/ client/java/solrj/test/org/apache/solr/client/solrj/ client/java/solrj/test/org/apache/solr/client/solrj/embedded/ src/java/org/apache/solr/core/ ...

Author: ryan
Date: Sun Mar  9 12:29:04 2008
New Revision: 635334

URL: http://svn.apache.org/viewvc?rev=635334&view=rev
Log:
SOLR-350 -- make MultiCore subclassable so to allow custom persistance methods (for example, SQL)

Added:
    lucene/solr/trunk/src/java/org/apache/solr/core/SolrMultiCore.java
Modified:
    lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java
    lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java
    lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java
    lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java
    lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java
    lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
    lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java
    lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java

Modified: lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java?rev=635334&r1=635333&r2=635334&view=diff
==============================================================================
--- lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java (original)
+++ lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java Sun Mar  9 12:29:04 2008
@@ -54,22 +54,31 @@
   protected ModifiableSolrParams _invariantParams;
   protected ResponseParser _processor;
   
-  protected final SolrCore core;
+  protected final MultiCore multicore; // either multicore
+  protected final SolrCore core; // or single core
   protected final SolrRequestParsers parser;
   protected final String coreName;  // use MultiCore registry
   
   public EmbeddedSolrServer( SolrCore core )
   {
+    if ( core == null ) {
+      throw new NullPointerException("SolrCore instance required");
+    }
     this.core = core;
+    this.multicore = null;
     this.coreName = null;
     this.parser = init();
   }
     
-  public EmbeddedSolrServer( String coreName )
+  public EmbeddedSolrServer(  MultiCore multicore, String coreName )
   {
+    if ( multicore == null ) {
+      throw new NullPointerException("MultiCore instance required");
+    }
     this.core = null;
+    this.multicore = multicore;
     this.coreName = coreName;
-    SolrCore c = MultiCore.getRegistry().getCore( coreName );
+    SolrCore c = multicore.getCore( coreName );
     if( c == null ) {
       throw new RuntimeException( "Unknown core: "+coreName );
     }
@@ -96,7 +105,6 @@
     }
 
     // Check for multicore action
-    MultiCore multicore = MultiCore.getRegistry();
     SolrCore core = this.core;
     if( core == null ) {
       core = multicore.getCore( coreName );
@@ -126,7 +134,7 @@
       }
       // Perhaps the path is to manage the cores
       if( handler == null &&
-          coreName != null && 
+          multicore != null &&
           path.equals( multicore.getAdminPath() ) && 
           multicore.isEnabled() ) {
         handler = multicore.getMultiCoreHandler();

Modified: lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java?rev=635334&r1=635333&r2=635334&view=diff
==============================================================================
--- lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java (original)
+++ lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java Sun Mar  9 12:29:04 2008
@@ -25,7 +25,7 @@
 import org.apache.solr.client.solrj.request.UpdateRequest.ACTION;
 import org.apache.solr.client.solrj.response.MultiCoreResponse;
 import org.apache.solr.common.SolrInputDocument;
-import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.MultiCore;
 
 
 /**
@@ -34,6 +34,9 @@
  */
 public abstract class MultiCoreExampleTestBase extends SolrExampleTestBase 
 {
+  @SuppressWarnings("deprecation")
+  protected static final MultiCore multicore =  org.apache.solr.core.SolrMultiCore.getInstance();
+  
   @Override public String getSolrHome() { return "../../../example/multicore/"; }
   
   @Override public String getSchemaFile()     { return getSolrHome()+"core0/conf/schema.xml";     }

Modified: lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java?rev=635334&r1=635333&r2=635334&view=diff
==============================================================================
--- lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java (original)
+++ lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java Sun Mar  9 12:29:04 2008
@@ -21,7 +21,6 @@
 
 import org.apache.solr.client.solrj.MultiCoreExampleTestBase;
 import org.apache.solr.client.solrj.SolrServer;
-import org.apache.solr.core.MultiCore;
 
 /**
  * This runs SolrServer test using 
@@ -37,24 +36,24 @@
     
     File home = new File( getSolrHome() );
     File f = new File( home, "multicore.xml" );
-    MultiCore.getRegistry().load( getSolrHome(), f );
+    multicore.load( getSolrHome(), f );
   }
 
   @Override
   protected SolrServer getSolrCore0()
   {
-    return new EmbeddedSolrServer( "core0" );
+    return new EmbeddedSolrServer( multicore, "core0" );
   }
 
   @Override
   protected SolrServer getSolrCore1()
   {
-    return new EmbeddedSolrServer( "core1" );
+    return new EmbeddedSolrServer( multicore, "core1" );
   }
 
   @Override
   protected SolrServer getSolrAdmin()
   {
-    return new EmbeddedSolrServer( "core0" );
+    return new EmbeddedSolrServer( multicore, "core0" );
   } 
 }

Modified: lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java?rev=635334&r1=635333&r2=635334&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java Sun Mar  9 12:29:04 2008
@@ -49,30 +49,33 @@
  */
 public class MultiCore 
 {
-  private static Logger log = Logger.getLogger(MultiCore.class.getName());
-  private static final MultiCore instance = new MultiCore();
+  protected static Logger log = Logger.getLogger(MultiCore.class.getName());
   
-  // Synchronized map of all cores
-  private final Map<String, CoreDescriptor> cores = new LinkedHashMap<String, CoreDescriptor>();
+  protected final Map<String, CoreDescriptor> cores = new LinkedHashMap<String, CoreDescriptor>();
+  protected boolean enabled = false;
+  protected boolean persistent = false;
+  protected String adminPath = null;
+  protected MultiCoreHandler multiCoreHandler = null;
+  protected File configFile = null;
+  protected String libDir = null;
+  protected ClassLoader libLoader = null;
+  protected SolrResourceLoader loader = null;
+  protected java.lang.ref.WeakReference<SolrCore> adminCore = null;
   
-  private boolean enabled = false;
-  private boolean persistent = false;
-  private String adminPath = null;
-  private MultiCoreHandler multiCoreHandler = null;
-  private File configFile = null;
-  private String libDir = null;
-  private ClassLoader libLoader = null;
-  private SolrResourceLoader loader = null;
-  
-  // no one else can make the registry
-  private MultiCore() { }
+  public MultiCore() {
+  }
   
   //-------------------------------------------------------------------
   // Initialization / Cleanup
   //-------------------------------------------------------------------
   
   /**
-   * Load a config file listing the available solr cores
+   * Load a config file listing the available solr cores.
+   * @param dir the home directory of all resources.
+   * @param configFile the configuration file
+   * @throws javax.xml.parsers.ParserConfigurationException
+   * @throws java.io.IOException
+   * @throws org.xml.sax.SAXException
    */
   public void load(String dir, File configFile ) throws ParserConfigurationException, IOException, SAXException {
     this.configFile = configFile;
@@ -94,7 +97,7 @@
       }
       
       if( adminPath != null ) {
-        multiCoreHandler = new MultiCoreHandler();
+        multiCoreHandler = this.createMultiCoreHandler();
       }
       
       NodeList nodes = (NodeList)cfg.evaluate("multicore/core", XPathConstants.NODESET);
@@ -135,7 +138,9 @@
     enabled = true;
   }
   
-  /** Stops all cores. */
+  /**
+   * Stops all cores.
+   */
   public void shutdown() {
     synchronized(cores) {
       for(Map.Entry<String,CoreDescriptor> e : cores.entrySet()) {
@@ -154,15 +159,11 @@
     shutdown();
   }
   
-  //-------------------------------------------------------------------
-  //
-  //-------------------------------------------------------------------
-  
-  /** Get the singleton */
-  public static MultiCore getRegistry() {
-    return instance;
-  }
-  
+  /**
+   * Registers a SolrCore descriptor in the registry.
+   * @param descr the Solr core descriptor
+   * @return a previous descriptor having the same name if it existed, null otherwise
+   */
   public CoreDescriptor register( CoreDescriptor descr ) {
     if( descr == null ) {
       throw new RuntimeException( "Can not register a null core." );
@@ -186,6 +187,12 @@
     }
   }
   
+
+  /**
+   * Swaps two SolrCore descriptors.
+   * @param c0
+   * @param c1
+   */
   public void swap(CoreDescriptor c0, CoreDescriptor c1) {
     if( c0 == null || c1 == null ) {
       throw new RuntimeException( "Can not swap a null core." );
@@ -235,10 +242,11 @@
   }
   
   /**
+   * Recreates a SolrCore.
    * While the new core is loading, requests will continue to be dispatched to
    * and processed by the old core
    * 
-   * @param core
+   * @param core the SolrCore to reload
    * @throws ParserConfigurationException
    * @throws IOException
    * @throws SAXException
@@ -314,6 +322,49 @@
     this.adminPath = adminPath;
   }
   
+  /**
+   * Sets the preferred core used to handle MultiCore admin tasks.
+   * Note that getAdminCore is not symmetrical to this method since
+   * it will allways return an opened SolrCore.
+   * This however can be useful implementing a "metacore" (a core of cores).
+   */
+  public void setAdminCore(SolrCore core) {
+    adminCore = new java.lang.ref.WeakReference<SolrCore>(core);
+  }
+
+  /**
+   * Gets a core to handle MultiCore admin tasks (@see SolrDispatchFilter).
+   * This makes the best attempt to reuse the same opened SolrCore accross calls.
+   */
+  public SolrCore getAdminCore() {
+    SolrCore core = adminCore != null ? adminCore.get() : null;
+    if (core == null || core.isClosed()) {
+      for (CoreDescriptor descr : this.cores.values()) {
+        core = descr.getCore();
+        if (core == null || core.isClosed()) {
+          core = null;
+        } else {
+          break;
+        }
+      }
+      setAdminCore(core);
+    }
+    return core;
+  }
+
+  /** 
+   * Creates a MultiCoreHandler for this MultiCore.
+   * @return a MultiCoreHandler
+   */
+  public MultiCoreHandler createMultiCoreHandler() {
+    return new MultiCoreHandler() {
+      @Override
+      public MultiCore getMultiCore() {
+        return MultiCore.this;
+      }
+    };
+  }
+ 
   public MultiCoreHandler getMultiCoreHandler() {
     return multiCoreHandler;
   }
@@ -439,4 +490,5 @@
       throw xforward;
     }
   }
+ 
 }

Modified: lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java?rev=635334&r1=635333&r2=635334&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java Sun Mar  9 12:29:04 2008
@@ -32,7 +32,6 @@
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.StringTokenizer;
-import java.util.logging.Logger;
 import java.util.logging.Level;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;

Modified: lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java?rev=635334&r1=635333&r2=635334&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java Sun Mar  9 12:29:04 2008
@@ -467,6 +467,10 @@
     }
   }
 
+  public boolean isClosed() {
+    return _searcher == null;
+  }
+  
   @Override
   protected void finalize() { close(); }
 
@@ -926,7 +930,7 @@
     synchronized (searcherLock) {
       if (_searcher != null) {
         _searcher.decref();   // dec refcount for this._searcher
-        _searcher=null;
+        _searcher=null; // isClosed() does check this
         infoRegistry.remove("currentSearcher");
       }
     }

Added: lucene/solr/trunk/src/java/org/apache/solr/core/SolrMultiCore.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrMultiCore.java?rev=635334&view=auto
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/SolrMultiCore.java (added)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrMultiCore.java Sun Mar  9 12:29:04 2008
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.core;
+
+/**
+ * A MultiCore singleton.
+ * Marked as deprecated to avoid usage proliferation of core code that would
+ * assume MultiCore being a singleton.  In solr 2.0, the MultiCore factory
+ * should be popluated with a standard tool like spring.  Until then, this is
+ * a simple static factory that should not be used widely. 
+ * 
+ * @version $Id$
+ * @since solr 1.3
+ */
+@Deprecated
+public final class SolrMultiCore extends MultiCore
+{
+  private static MultiCore instance = null;
+  
+  // no one else can make the registry
+  private SolrMultiCore() {}
+  
+  /** Returns a default MultiCore singleton.
+   * @return
+   */
+  public static synchronized MultiCore getInstance() {
+    if (instance == null) {
+      instance = new SolrMultiCore();
+    }
+    return instance;
+  }
+}

Modified: lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java?rev=635334&r1=635333&r2=635334&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java Sun Mar  9 12:29:04 2008
@@ -39,7 +39,7 @@
  * @version $Id$
  * @since solr 1.3
  */
-public class MultiCoreHandler extends RequestHandlerBase
+public abstract class MultiCoreHandler extends RequestHandlerBase
 {
   public MultiCoreHandler()
   {
@@ -56,11 +56,18 @@
         "it is a special Handler configured directly by the RequestDispatcher" );
   }
   
+  /**
+   * The instance of multicore this handler handles.
+   * This should be the MultiCore instance that created this handler.
+   * @return a MultiCore instance
+   */
+  public abstract MultiCore getMultiCore();
+  
   @Override
   public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception 
   {
     // Make sure the manager is enabled
-    MultiCore manager = MultiCore.getRegistry();
+    MultiCore manager = getMultiCore();
     if( !manager.isEnabled() ) {
       throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
           "MultiCore support must be enabled at startup." );

Modified: lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java?rev=635334&r1=635333&r2=635334&view=diff
==============================================================================
--- lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java (original)
+++ lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java Sun Mar  9 12:29:04 2008
@@ -21,7 +21,6 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.util.Collection;
 import java.util.WeakHashMap;
 import java.util.logging.Logger;
 import java.util.logging.Level;
@@ -74,23 +73,12 @@
       this.pathPrefix = config.getInitParameter( "path-prefix" );
       this.solrConfigFilename = config.getInitParameter("solrconfig-filename");
       
-      multicore = MultiCore.getRegistry();
-      if( multicore.isEnabled() ) {
-        log.info( "Using existing multicore configuration" );
-      }
-      else {
-        String instanceDir = SolrResourceLoader.locateInstanceDir();
-        File multiconfig = new File( instanceDir, "multicore.xml" );
-        log.info( "looking for multicore.xml: "+multiconfig.getAbsolutePath() );
-        if( multiconfig.exists() ) {
-          multicore.load( instanceDir, multiconfig );
-        }
-      }
+      // multicore instantiation
+      this.multicore = initMultiCore(config);
       
+      if(multicore != null && multicore.isEnabled() ) {
       abortOnConfigurationError = false;
-      if( multicore.isEnabled() ) {
         singlecore = null;
-        
         // if any core aborts on startup, then abort
         for( SolrCore c : multicore.getCores() ) {
           if( c.getSolrConfig().getBool( "abortOnConfigurationError",false) ) {
@@ -100,11 +88,10 @@
         }
       }
       else {
-        if (this.solrConfigFilename==null) {
-          singlecore = new SolrCore( null, null, new SolrConfig(), null );
-        } else {
-          singlecore = new SolrCore( null, null, new SolrConfig(this.solrConfigFilename), null);
-        }
+        SolrConfig cfg = this.solrConfigFilename == null? new SolrConfig() : new SolrConfig(this.solrConfigFilename);
+        singlecore = new SolrCore( null, null, cfg, null );
+        abortOnConfigurationError = cfg.getBool(
+                "abortOnConfigurationError", abortOnConfigurationError);
       }
       log.info("user.dir=" + System.getProperty("user.dir"));
     }
@@ -123,10 +110,9 @@
       out.println( "Check your log files for more detailed information on what may be wrong.\n" );
       out.println( "If you want solr to continue after configuration errors, change: \n");
       out.println( " <abortOnConfigurationError>false</abortOnConfigurationError>\n" );
-      if( multicore.isEnabled() ) {
+      if (multicore != null && multicore.isEnabled()) {
         out.println( "in multicore.xml\n" );
-      } 
-      else {
+      } else {
         out.println( "in solrconfig.xml\n" );
       }
       
@@ -148,24 +134,53 @@
     log.info("SolrDispatchFilter.init() done");
   }
 
+  /**
+   * Initializes the multicore instance.
+   * @param config the filter configuration
+   * @return the multicore instance or null
+   * @throws java.lang.Exception
+   */
+  protected MultiCore initMultiCore(FilterConfig config) throws Exception {
+    @SuppressWarnings("deprecation") // since SolrDispatchFilter can be derived & initMultiCore can be overriden
+    MultiCore mcore = org.apache.solr.core.SolrMultiCore.getInstance();
+    if (mcore.isEnabled()) {
+      log.info("Using existing multicore configuration");
+    } else {
+      // multicore load
+      String instanceDir = SolrResourceLoader.locateInstanceDir();
+      File fconf = new File(instanceDir, "multicore.xml");
+      log.info("looking for multicore.xml: " + fconf.getAbsolutePath());
+      if (fconf.exists()) {
+        mcore.load(instanceDir, fconf);
+      }
+    }
+    return mcore;
+  }
+
+  
   public void destroy() {
+    if (multicore != null) {
     multicore.shutdown();
+      multicore = null;
+    }
     if( singlecore != null ) {
       singlecore.close();
+      singlecore = null;
     }
   }
   
-  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
-  {
+  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
     if( abortErrorMessage != null ) {
       ((HttpServletResponse)response).sendError( 500, abortErrorMessage );
       return;
     }
     
     if( request instanceof HttpServletRequest) {
-      SolrQueryRequest solrReq = null;
       HttpServletRequest req = (HttpServletRequest)request;
       HttpServletResponse resp = (HttpServletResponse)response;
+      SolrRequestHandler handler = null;
+      SolrQueryRequest solrReq = null;
+
       try {
         String path = req.getServletPath();    
         if( req.getPathInfo() != null ) {
@@ -183,133 +198,118 @@
         }
         
         // By default use the single core.  If multicore is enabled, look for one.
-        SolrRequestHandler handler = null;
-        SolrCore core = singlecore;
-        if( core == null ) {
-          // Perhaps this is a multi-core admin page?
-          if( path.equals( "/" ) ) {
-            chain.doFilter(request, response);
-            return;  
-          }
+        final SolrCore core;
+        if (multicore != null && multicore.isEnabled()) {
+          // if this is the multi-core admin page, it will handle it
           if( path.equals( multicore.getAdminPath() ) ) {
             handler = multicore.getMultiCoreHandler();
-            
-            // pick a core to use for output
-            Collection<SolrCore> cores = multicore.getCores();
-            if( cores != null && cores.size() > 0 ) {
-              core = cores.iterator().next();
-            }
+            // pick a core to use for output generation
+            core = multicore.getAdminCore();
             if( core == null ) {
               throw new RuntimeException( "Can not find a valid core for the multicore admin handler" );
             }
-          }
-          else {
+          } else {
+            //otherwise, we should find a core from the path
             idx = path.indexOf( "/", 1 );
-            if( idx <= 1 ) {
-              idx = path.length();
-            }
-            
-            // try to get the corename as a request parameter first
-            String corename = path.substring( 1, idx );
-            path = path.substring( idx );
-            core = multicore.getCore( corename );
-            
-            if( path.length() == 0 ) {
-              path = "/";
-            }
-            
-            if( core == null ) {
-              throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown core: "+corename );
+            if( idx > 1 ) {
+              // try to get the corename as a request parameter first
+              String corename = path.substring( 1, idx );
+              path = path.substring( idx );
+              core = multicore.getCore( corename );
+            } else {
+              core = null;
             }
           }
         }
-        
-        SolrRequestParsers parser = parsers.get( core );
-        if( parser == null ) {
-          parser = new SolrRequestParsers( core.getSolrConfig() );
-          parsers.put( core, parser );
-        }
-        
-        // Only try to parse the handler *if* a valid core exists
-        // when multi-core is enabled, the path can lead to a null core.
-        if( handler == null && path.length() > 1 ) { // don't match "" or "/" as valid path
-          handler = core.getRequestHandler( path );
-        }
-        if( handler == null && parser.isHandleSelect() ) {
-          if( "/select".equals( path ) || "/select/".equals( path ) ) {
-            solrReq = parser.parse( core, path, req );
-            String qt = solrReq.getParams().get( CommonParams.QT );
-            if( qt != null && qt.startsWith( "/" ) ) {
-              throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query type.  Do not use /select to access: "+qt);
-            }
-            handler = core.getRequestHandler( qt );
-            if( handler == null ) {
-              throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+qt);
-            }
-          }
+        else {
+          core = singlecore;
         }
         
-        if( handler != null ) {          
-          if( solrReq == null ) {
-            solrReq = parser.parse( core, path, req );
+        // With a valid core...
+        if( core != null ) {
+          final SolrConfig config = core.getSolrConfig();
+          // get or create/cache the parser for the core
+          SolrRequestParsers parser = null;
+          parser = parsers.get(core);
+          if( parser == null ) {
+            parser = new SolrRequestParsers(config);
+            parsers.put( core, parser );
           }
           
-          final SolrConfig conf = core.getSolrConfig();
-          final Method reqMethod = Method.getMethod(req.getMethod());
-
-          if (Method.POST != reqMethod) {
-            HttpCacheHeaderUtil.setCacheControlHeader(conf, resp);
-          }
-            
-          // unless we have been explicitly told not to, do cache validation
-          if (!conf.getHttpCachingConfig().isNever304()) {
-            // if we've confirmed cache validation, return immediately
-            if (HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req,resp)) {
-              return;
+          // Determine the handler from the url path if not set
+          // (we might already have selected the multicore handler)
+          if( handler == null && path.length() > 1 ) { // don't match "" or "/" as valid path
+            handler = core.getRequestHandler( path );
+            // no handler yet but allowed to handle select; let's check
+            if( handler == null && parser.isHandleSelect() ) {
+              if( "/select".equals( path ) || "/select/".equals( path ) ) {
+                solrReq = parser.parse( core, path, req );
+                String qt = solrReq.getParams().get( CommonParams.QT );
+                if( qt != null && qt.startsWith( "/" ) ) {
+                  throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query type.  Do not use /select to access: "+qt);
+                }
+                handler = core.getRequestHandler( qt );
+                if( handler == null ) {
+                  throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+qt);
+                }      
+              }
             }
           }
           
-          SolrQueryResponse solrRsp = new SolrQueryResponse();
-          /* even for HEAD requests, we need to execute the handler to
-           * ensure we don't get an error (and to make sure the correct 
-           * QueryResponseWriter is selectedand we get the correct
-           * Content-Type)
-           */
-          this.execute( req, handler, solrReq, solrRsp );
-          if( solrRsp.getException() != null ) {
-            sendError( (HttpServletResponse)response, solrRsp.getException() );
-            return;
-          }
-          
-          // Now write it out
-          QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
-          response.setContentType(responseWriter.getContentType(solrReq, solrRsp));
-          if (Method.HEAD == Method.getMethod(req.getMethod())) {
-            // nothing to write out, waited this long just to get ContentType
-            return; 
+            // With a valid handler and a valid core...
+          if( handler != null ) {          
+            // if not a /select, create the request
+            if( solrReq == null ) {
+              solrReq = parser.parse( core, path, req );
+            }
+            
+            final Method reqMethod = Method.getMethod(req.getMethod());
+            if (Method.POST != reqMethod) {
+              HttpCacheHeaderUtil.setCacheControlHeader(config, resp);
+            }
+            // unless we have been explicitly told not to, do cache validation
+            // if we fail cache validation, execute the query
+            if (config.getHttpCachingConfig().isNever304() ||
+                !HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req, resp)) {
+                SolrQueryResponse solrRsp = new SolrQueryResponse();
+                /* even for HEAD requests, we need to execute the handler to
+                 * ensure we don't get an error (and to make sure the correct 
+                 * QueryResponseWriter is selectedand we get the correct
+                 * Content-Type)
+                 */
+                this.execute( req, handler, solrReq, solrRsp );
+                if( solrRsp.getException() != null ) {
+                  sendError( (HttpServletResponse)response, solrRsp.getException() );
+                }
+                else {
+                  // Now write it out
+                  QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
+                  response.setContentType(responseWriter.getContentType(solrReq, solrRsp));
+                        if (Method.HEAD != Method.getMethod(req.getMethod())) {
+                  PrintWriter out = response.getWriter();
+                  responseWriter.write(out, solrReq, solrRsp);
+                }
+                //else http HEAD request, nothing to write out, waited this long just to get ContentType
+              }
+            }
+            return; // we are done with a valid handler
           }
-          
-          PrintWriter out = response.getWriter();
-          responseWriter.write(out, solrReq, solrRsp);
-          return;
-        }
-        // otherwise, let's ensure the core is in the SolrCore request attribute so
-        // the servlet/jsp can retrieve it
-        else {
-          req.setAttribute("org.apache.solr.SolrCore", core);
-
-          // Let each core have its own admin page...
-          if( singlecore == null && path.startsWith( "/admin" ) ) {
-            req.getRequestDispatcher( path ).forward( request, response );
-            return; 
+          // otherwise (we have a core), let's ensure the core is in the SolrCore request attribute so
+          // a servlet/jsp can retrieve it
+          else {
+            req.setAttribute("org.apache.solr.SolrCore", core);
+              // Modify the request so each core gets its own /admin
+            if( singlecore == null && path.startsWith( "/admin" ) ) {
+              req.getRequestDispatcher( path ).forward( request, response );
+              return; 
+            }
           }
         }
-      }
-      catch( Throwable ex ) {
+        log.info("no handler or core retrieved for " + path + ", follow through...");
+      } catch (Throwable ex) {
         sendError( (HttpServletResponse)response, ex );
         return;
-      }
-      finally {
+      } finally {
         if( solrReq != null ) {
           solrReq.close();
         }
@@ -326,8 +326,7 @@
     sreq.getCore().execute( handler, sreq, rsp );
   }
   
-  protected void sendError(HttpServletResponse res, Throwable ex) throws IOException 
-  {
+  protected void sendError(HttpServletResponse res, Throwable ex) throws IOException {
     int code=500;
     String trace = "";
     if( ex instanceof SolrException ) {



Re: svn commit: r635334 - in /lucene/solr/trunk: client/java/solrj/src/org/apache/solr/client/solrj/embedded/ client/java/solrj/test/org/apache/solr/client/solrj/ client/java/solrj/test/org/apache/solr/client/solrj/embedded/ src/java/org/apache/solr/core/ ...

Posted by Grant Ingersoll <gs...@apache.org>.
I'm getting:

HTTP ERROR: 500

PWC6033: Unable to compile class for JSP

PWC6197: An error occurred at line: 50 in the jsp file: /admin/index.jsp
PWC6199: Generated servlet error:
The method getRegistry() is undefined for the type MultiCore


RequestURI=/solr/admin/
Caused by:

org.apache.jasper.JasperException: PWC6033: Unable to compile class  
for JSP

PWC6197: An error occurred at line: 50 in the jsp file: /admin/index.jsp
PWC6199: Generated servlet error:
The method getRegistry() is undefined for the type MultiCore


	at  
org 
.apache 
.jasper 
.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:94)



Looks like getRegistry() was removed.  I'm not sure on the  
replacement, just yet, but can look into it if no one else sees it  
right off hand..

-Grant

On Mar 9, 2008, at 3:29 PM, ryan@apache.org wrote:

> Author: ryan
> Date: Sun Mar  9 12:29:04 2008
> New Revision: 635334
>
> URL: http://svn.apache.org/viewvc?rev=635334&view=rev
> Log:
> SOLR-350 -- make MultiCore subclassable so to allow custom  
> persistance methods (for example, SQL)
>
> Added:
>    lucene/solr/trunk/src/java/org/apache/solr/core/SolrMultiCore.java
> Modified:
>    lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/ 
> solrj/embedded/EmbeddedSolrServer.java
>    lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/ 
> solrj/MultiCoreExampleTestBase.java
>    lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/ 
> solrj/embedded/MultiCoreEmbeddedTest.java
>    lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java
>    lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java
>    lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
>    lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ 
> MultiCoreHandler.java
>    lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/ 
> SolrDispatchFilter.java
>
> Modified: lucene/solr/trunk/client/java/solrj/src/org/apache/solr/ 
> client/solrj/embedded/EmbeddedSolrServer.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java?rev=635334&r1=635333&r2=635334&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/ 
> solrj/embedded/EmbeddedSolrServer.java (original)
> +++ lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/ 
> solrj/embedded/EmbeddedSolrServer.java Sun Mar  9 12:29:04 2008
> @@ -54,22 +54,31 @@
>   protected ModifiableSolrParams _invariantParams;
>   protected ResponseParser _processor;
>
> -  protected final SolrCore core;
> +  protected final MultiCore multicore; // either multicore
> +  protected final SolrCore core; // or single core
>   protected final SolrRequestParsers parser;
>   protected final String coreName;  // use MultiCore registry
>
>   public EmbeddedSolrServer( SolrCore core )
>   {
> +    if ( core == null ) {
> +      throw new NullPointerException("SolrCore instance required");
> +    }
>     this.core = core;
> +    this.multicore = null;
>     this.coreName = null;
>     this.parser = init();
>   }
>
> -  public EmbeddedSolrServer( String coreName )
> +  public EmbeddedSolrServer(  MultiCore multicore, String coreName )
>   {
> +    if ( multicore == null ) {
> +      throw new NullPointerException("MultiCore instance required");
> +    }
>     this.core = null;
> +    this.multicore = multicore;
>     this.coreName = coreName;
> -    SolrCore c = MultiCore.getRegistry().getCore( coreName );
> +    SolrCore c = multicore.getCore( coreName );
>     if( c == null ) {
>       throw new RuntimeException( "Unknown core: "+coreName );
>     }
> @@ -96,7 +105,6 @@
>     }
>
>     // Check for multicore action
> -    MultiCore multicore = MultiCore.getRegistry();
>     SolrCore core = this.core;
>     if( core == null ) {
>       core = multicore.getCore( coreName );
> @@ -126,7 +134,7 @@
>       }
>       // Perhaps the path is to manage the cores
>       if( handler == null &&
> -          coreName != null &&
> +          multicore != null &&
>           path.equals( multicore.getAdminPath() ) &&
>           multicore.isEnabled() ) {
>         handler = multicore.getMultiCoreHandler();
>
> Modified: lucene/solr/trunk/client/java/solrj/test/org/apache/solr/ 
> client/solrj/MultiCoreExampleTestBase.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java?rev=635334&r1=635333&r2=635334&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/ 
> solrj/MultiCoreExampleTestBase.java (original)
> +++ lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/ 
> solrj/MultiCoreExampleTestBase.java Sun Mar  9 12:29:04 2008
> @@ -25,7 +25,7 @@
> import org.apache.solr.client.solrj.request.UpdateRequest.ACTION;
> import org.apache.solr.client.solrj.response.MultiCoreResponse;
> import org.apache.solr.common.SolrInputDocument;
> -import org.apache.solr.core.SolrCore;
> +import org.apache.solr.core.MultiCore;
>
>
> /**
> @@ -34,6 +34,9 @@
>  */
> public abstract class MultiCoreExampleTestBase extends  
> SolrExampleTestBase
> {
> +  @SuppressWarnings("deprecation")
> +  protected static final MultiCore multicore =   
> org.apache.solr.core.SolrMultiCore.getInstance();
> +
>   @Override public String getSolrHome() { return "../../../example/ 
> multicore/"; }
>
>   @Override public String getSchemaFile()     { return getSolrHome() 
> +"core0/conf/schema.xml";     }
>
> Modified: lucene/solr/trunk/client/java/solrj/test/org/apache/solr/ 
> client/solrj/embedded/MultiCoreEmbeddedTest.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java?rev=635334&r1=635333&r2=635334&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/ 
> solrj/embedded/MultiCoreEmbeddedTest.java (original)
> +++ lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/ 
> solrj/embedded/MultiCoreEmbeddedTest.java Sun Mar  9 12:29:04 2008
> @@ -21,7 +21,6 @@
>
> import org.apache.solr.client.solrj.MultiCoreExampleTestBase;
> import org.apache.solr.client.solrj.SolrServer;
> -import org.apache.solr.core.MultiCore;
>
> /**
>  * This runs SolrServer test using
> @@ -37,24 +36,24 @@
>
>     File home = new File( getSolrHome() );
>     File f = new File( home, "multicore.xml" );
> -    MultiCore.getRegistry().load( getSolrHome(), f );
> +    multicore.load( getSolrHome(), f );
>   }
>
>   @Override
>   protected SolrServer getSolrCore0()
>   {
> -    return new EmbeddedSolrServer( "core0" );
> +    return new EmbeddedSolrServer( multicore, "core0" );
>   }
>
>   @Override
>   protected SolrServer getSolrCore1()
>   {
> -    return new EmbeddedSolrServer( "core1" );
> +    return new EmbeddedSolrServer( multicore, "core1" );
>   }
>
>   @Override
>   protected SolrServer getSolrAdmin()
>   {
> -    return new EmbeddedSolrServer( "core0" );
> +    return new EmbeddedSolrServer( multicore, "core0" );
>   }
> }
>
> Modified: lucene/solr/trunk/src/java/org/apache/solr/core/ 
> MultiCore.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java?rev=635334&r1=635333&r2=635334&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java  
> (original)
> +++ lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java  
> Sun Mar  9 12:29:04 2008
> @@ -49,30 +49,33 @@
>  */
> public class MultiCore
> {
> -  private static Logger log =  
> Logger.getLogger(MultiCore.class.getName());
> -  private static final MultiCore instance = new MultiCore();
> +  protected static Logger log =  
> Logger.getLogger(MultiCore.class.getName());
>
> -  // Synchronized map of all cores
> -  private final Map<String, CoreDescriptor> cores = new  
> LinkedHashMap<String, CoreDescriptor>();
> +  protected final Map<String, CoreDescriptor> cores = new  
> LinkedHashMap<String, CoreDescriptor>();
> +  protected boolean enabled = false;
> +  protected boolean persistent = false;
> +  protected String adminPath = null;
> +  protected MultiCoreHandler multiCoreHandler = null;
> +  protected File configFile = null;
> +  protected String libDir = null;
> +  protected ClassLoader libLoader = null;
> +  protected SolrResourceLoader loader = null;
> +  protected java.lang.ref.WeakReference<SolrCore> adminCore = null;
>
> -  private boolean enabled = false;
> -  private boolean persistent = false;
> -  private String adminPath = null;
> -  private MultiCoreHandler multiCoreHandler = null;
> -  private File configFile = null;
> -  private String libDir = null;
> -  private ClassLoader libLoader = null;
> -  private SolrResourceLoader loader = null;
> -
> -  // no one else can make the registry
> -  private MultiCore() { }
> +  public MultiCore() {
> +  }
>
>   //-------------------------------------------------------------------
>   // Initialization / Cleanup
>   //-------------------------------------------------------------------
>
>   /**
> -   * Load a config file listing the available solr cores
> +   * Load a config file listing the available solr cores.
> +   * @param dir the home directory of all resources.
> +   * @param configFile the configuration file
> +   * @throws javax.xml.parsers.ParserConfigurationException
> +   * @throws java.io.IOException
> +   * @throws org.xml.sax.SAXException
>    */
>   public void load(String dir, File configFile ) throws  
> ParserConfigurationException, IOException, SAXException {
>     this.configFile = configFile;
> @@ -94,7 +97,7 @@
>       }
>
>       if( adminPath != null ) {
> -        multiCoreHandler = new MultiCoreHandler();
> +        multiCoreHandler = this.createMultiCoreHandler();
>       }
>
>       NodeList nodes = (NodeList)cfg.evaluate("multicore/core",  
> XPathConstants.NODESET);
> @@ -135,7 +138,9 @@
>     enabled = true;
>   }
>
> -  /** Stops all cores. */
> +  /**
> +   * Stops all cores.
> +   */
>   public void shutdown() {
>     synchronized(cores) {
>       for(Map.Entry<String,CoreDescriptor> e : cores.entrySet()) {
> @@ -154,15 +159,11 @@
>     shutdown();
>   }
>
> -  //-------------------------------------------------------------------
> -  //
> -  //-------------------------------------------------------------------
> -
> -  /** Get the singleton */
> -  public static MultiCore getRegistry() {
> -    return instance;
> -  }
> -
> +  /**
> +   * Registers a SolrCore descriptor in the registry.
> +   * @param descr the Solr core descriptor
> +   * @return a previous descriptor having the same name if it  
> existed, null otherwise
> +   */
>   public CoreDescriptor register( CoreDescriptor descr ) {
>     if( descr == null ) {
>       throw new RuntimeException( "Can not register a null core." );
> @@ -186,6 +187,12 @@
>     }
>   }
>
> +
> +  /**
> +   * Swaps two SolrCore descriptors.
> +   * @param c0
> +   * @param c1
> +   */
>   public void swap(CoreDescriptor c0, CoreDescriptor c1) {
>     if( c0 == null || c1 == null ) {
>       throw new RuntimeException( "Can not swap a null core." );
> @@ -235,10 +242,11 @@
>   }
>
>   /**
> +   * Recreates a SolrCore.
>    * While the new core is loading, requests will continue to be  
> dispatched to
>    * and processed by the old core
>    *
> -   * @param core
> +   * @param core the SolrCore to reload
>    * @throws ParserConfigurationException
>    * @throws IOException
>    * @throws SAXException
> @@ -314,6 +322,49 @@
>     this.adminPath = adminPath;
>   }
>
> +  /**
> +   * Sets the preferred core used to handle MultiCore admin tasks.
> +   * Note that getAdminCore is not symmetrical to this method since
> +   * it will allways return an opened SolrCore.
> +   * This however can be useful implementing a "metacore" (a core  
> of cores).
> +   */
> +  public void setAdminCore(SolrCore core) {
> +    adminCore = new java.lang.ref.WeakReference<SolrCore>(core);
> +  }
> +
> +  /**
> +   * Gets a core to handle MultiCore admin tasks (@see  
> SolrDispatchFilter).
> +   * This makes the best attempt to reuse the same opened SolrCore  
> accross calls.
> +   */
> +  public SolrCore getAdminCore() {
> +    SolrCore core = adminCore != null ? adminCore.get() : null;
> +    if (core == null || core.isClosed()) {
> +      for (CoreDescriptor descr : this.cores.values()) {
> +        core = descr.getCore();
> +        if (core == null || core.isClosed()) {
> +          core = null;
> +        } else {
> +          break;
> +        }
> +      }
> +      setAdminCore(core);
> +    }
> +    return core;
> +  }
> +
> +  /**
> +   * Creates a MultiCoreHandler for this MultiCore.
> +   * @return a MultiCoreHandler
> +   */
> +  public MultiCoreHandler createMultiCoreHandler() {
> +    return new MultiCoreHandler() {
> +      @Override
> +      public MultiCore getMultiCore() {
> +        return MultiCore.this;
> +      }
> +    };
> +  }
> +
>   public MultiCoreHandler getMultiCoreHandler() {
>     return multiCoreHandler;
>   }
> @@ -439,4 +490,5 @@
>       throw xforward;
>     }
>   }
> +
> }
>
> Modified: lucene/solr/trunk/src/java/org/apache/solr/core/ 
> SolrConfig.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java?rev=635334&r1=635333&r2=635334&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java  
> (original)
> +++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java  
> Sun Mar  9 12:29:04 2008
> @@ -32,7 +32,6 @@
> import java.util.Collection;
> import java.util.HashSet;
> import java.util.StringTokenizer;
> -import java.util.logging.Logger;
> import java.util.logging.Level;
> import java.util.regex.Pattern;
> import java.util.regex.Matcher;
>
> Modified: lucene/solr/trunk/src/java/org/apache/solr/core/ 
> SolrCore.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java?rev=635334&r1=635333&r2=635334&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java  
> (original)
> +++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java  
> Sun Mar  9 12:29:04 2008
> @@ -467,6 +467,10 @@
>     }
>   }
>
> +  public boolean isClosed() {
> +    return _searcher == null;
> +  }
> +
>   @Override
>   protected void finalize() { close(); }
>
> @@ -926,7 +930,7 @@
>     synchronized (searcherLock) {
>       if (_searcher != null) {
>         _searcher.decref();   // dec refcount for this._searcher
> -        _searcher=null;
> +        _searcher=null; // isClosed() does check this
>         infoRegistry.remove("currentSearcher");
>       }
>     }
>
> Added: lucene/solr/trunk/src/java/org/apache/solr/core/ 
> SolrMultiCore.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrMultiCore.java?rev=635334&view=auto
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- lucene/solr/trunk/src/java/org/apache/solr/core/ 
> SolrMultiCore.java (added)
> +++ lucene/solr/trunk/src/java/org/apache/solr/core/ 
> SolrMultiCore.java Sun Mar  9 12:29:04 2008
> @@ -0,0 +1,47 @@
> +/**
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed  
> with
> + * this work for additional information regarding copyright  
> ownership.
> + * The ASF licenses this file to You under the Apache License,  
> Version 2.0
> + * (the "License"); you may not use this file except in compliance  
> with
> + * the License.  You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,  
> software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or  
> implied.
> + * See the License for the specific language governing permissions  
> and
> + * limitations under the License.
> + */
> +
> +package org.apache.solr.core;
> +
> +/**
> + * A MultiCore singleton.
> + * Marked as deprecated to avoid usage proliferation of core code  
> that would
> + * assume MultiCore being a singleton.  In solr 2.0, the MultiCore  
> factory
> + * should be popluated with a standard tool like spring.  Until  
> then, this is
> + * a simple static factory that should not be used widely.
> + *
> + * @version $Id$
> + * @since solr 1.3
> + */
> +@Deprecated
> +public final class SolrMultiCore extends MultiCore
> +{
> +  private static MultiCore instance = null;
> +
> +  // no one else can make the registry
> +  private SolrMultiCore() {}
> +
> +  /** Returns a default MultiCore singleton.
> +   * @return
> +   */
> +  public static synchronized MultiCore getInstance() {
> +    if (instance == null) {
> +      instance = new SolrMultiCore();
> +    }
> +    return instance;
> +  }
> +}
>
> Modified: lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ 
> MultiCoreHandler.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java?rev=635334&r1=635333&r2=635334&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ 
> MultiCoreHandler.java (original)
> +++ lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ 
> MultiCoreHandler.java Sun Mar  9 12:29:04 2008
> @@ -39,7 +39,7 @@
>  * @version $Id$
>  * @since solr 1.3
>  */
> -public class MultiCoreHandler extends RequestHandlerBase
> +public abstract class MultiCoreHandler extends RequestHandlerBase
> {
>   public MultiCoreHandler()
>   {
> @@ -56,11 +56,18 @@
>         "it is a special Handler configured directly by the  
> RequestDispatcher" );
>   }
>
> +  /**
> +   * The instance of multicore this handler handles.
> +   * This should be the MultiCore instance that created this handler.
> +   * @return a MultiCore instance
> +   */
> +  public abstract MultiCore getMultiCore();
> +
>   @Override
>   public void handleRequestBody(SolrQueryRequest req,  
> SolrQueryResponse rsp) throws Exception
>   {
>     // Make sure the manager is enabled
> -    MultiCore manager = MultiCore.getRegistry();
> +    MultiCore manager = getMultiCore();
>     if( !manager.isEnabled() ) {
>       throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
>           "MultiCore support must be enabled at startup." );
>
> Modified: lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/ 
> SolrDispatchFilter.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java?rev=635334&r1=635333&r2=635334&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/ 
> SolrDispatchFilter.java (original)
> +++ lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/ 
> SolrDispatchFilter.java Sun Mar  9 12:29:04 2008
> @@ -21,7 +21,6 @@
> import java.io.IOException;
> import java.io.PrintWriter;
> import java.io.StringWriter;
> -import java.util.Collection;
> import java.util.WeakHashMap;
> import java.util.logging.Logger;
> import java.util.logging.Level;
> @@ -74,23 +73,12 @@
>       this.pathPrefix = config.getInitParameter( "path-prefix" );
>       this.solrConfigFilename = config.getInitParameter("solrconfig- 
> filename");
>
> -      multicore = MultiCore.getRegistry();
> -      if( multicore.isEnabled() ) {
> -        log.info( "Using existing multicore configuration" );
> -      }
> -      else {
> -        String instanceDir = SolrResourceLoader.locateInstanceDir();
> -        File multiconfig = new File( instanceDir, "multicore.xml" );
> -        log.info( "looking for multicore.xml:  
> "+multiconfig.getAbsolutePath() );
> -        if( multiconfig.exists() ) {
> -          multicore.load( instanceDir, multiconfig );
> -        }
> -      }
> +      // multicore instantiation
> +      this.multicore = initMultiCore(config);
>
> +      if(multicore != null && multicore.isEnabled() ) {
>       abortOnConfigurationError = false;
> -      if( multicore.isEnabled() ) {
>         singlecore = null;
> -
>         // if any core aborts on startup, then abort
>         for( SolrCore c : multicore.getCores() ) {
>            
> if( c.getSolrConfig().getBool( "abortOnConfigurationError",false) ) {
> @@ -100,11 +88,10 @@
>         }
>       }
>       else {
> -        if (this.solrConfigFilename==null) {
> -          singlecore = new SolrCore( null, null, new SolrConfig(),  
> null );
> -        } else {
> -          singlecore = new SolrCore( null, null, new  
> SolrConfig(this.solrConfigFilename), null);
> -        }
> +        SolrConfig cfg = this.solrConfigFilename == null? new  
> SolrConfig() : new SolrConfig(this.solrConfigFilename);
> +        singlecore = new SolrCore( null, null, cfg, null );
> +        abortOnConfigurationError = cfg.getBool(
> +                "abortOnConfigurationError",  
> abortOnConfigurationError);
>       }
>       log.info("user.dir=" + System.getProperty("user.dir"));
>     }
> @@ -123,10 +110,9 @@
>       out.println( "Check your log files for more detailed  
> information on what may be wrong.\n" );
>       out.println( "If you want solr to continue after configuration  
> errors, change: \n");
>       out.println( " <abortOnConfigurationError>false</ 
> abortOnConfigurationError>\n" );
> -      if( multicore.isEnabled() ) {
> +      if (multicore != null && multicore.isEnabled()) {
>         out.println( "in multicore.xml\n" );
> -      }
> -      else {
> +      } else {
>         out.println( "in solrconfig.xml\n" );
>       }
>
> @@ -148,24 +134,53 @@
>     log.info("SolrDispatchFilter.init() done");
>   }
>
> +  /**
> +   * Initializes the multicore instance.
> +   * @param config the filter configuration
> +   * @return the multicore instance or null
> +   * @throws java.lang.Exception
> +   */
> +  protected MultiCore initMultiCore(FilterConfig config) throws  
> Exception {
> +    @SuppressWarnings("deprecation") // since SolrDispatchFilter  
> can be derived & initMultiCore can be overriden
> +    MultiCore mcore =  
> org.apache.solr.core.SolrMultiCore.getInstance();
> +    if (mcore.isEnabled()) {
> +      log.info("Using existing multicore configuration");
> +    } else {
> +      // multicore load
> +      String instanceDir = SolrResourceLoader.locateInstanceDir();
> +      File fconf = new File(instanceDir, "multicore.xml");
> +      log.info("looking for multicore.xml: " +  
> fconf.getAbsolutePath());
> +      if (fconf.exists()) {
> +        mcore.load(instanceDir, fconf);
> +      }
> +    }
> +    return mcore;
> +  }
> +
> +
>   public void destroy() {
> +    if (multicore != null) {
>     multicore.shutdown();
> +      multicore = null;
> +    }
>     if( singlecore != null ) {
>       singlecore.close();
> +      singlecore = null;
>     }
>   }
>
> -  public void doFilter(ServletRequest request, ServletResponse  
> response, FilterChain chain) throws IOException, ServletException
> -  {
> +  public void doFilter(ServletRequest request, ServletResponse  
> response, FilterChain chain) throws IOException, ServletException {
>     if( abortErrorMessage != null ) {
>       ((HttpServletResponse)response).sendError( 500,  
> abortErrorMessage );
>       return;
>     }
>
>     if( request instanceof HttpServletRequest) {
> -      SolrQueryRequest solrReq = null;
>       HttpServletRequest req = (HttpServletRequest)request;
>       HttpServletResponse resp = (HttpServletResponse)response;
> +      SolrRequestHandler handler = null;
> +      SolrQueryRequest solrReq = null;
> +
>       try {
>         String path = req.getServletPath();
>         if( req.getPathInfo() != null ) {
> @@ -183,133 +198,118 @@
>         }
>
>         // By default use the single core.  If multicore is enabled,  
> look for one.
> -        SolrRequestHandler handler = null;
> -        SolrCore core = singlecore;
> -        if( core == null ) {
> -          // Perhaps this is a multi-core admin page?
> -          if( path.equals( "/" ) ) {
> -            chain.doFilter(request, response);
> -            return;
> -          }
> +        final SolrCore core;
> +        if (multicore != null && multicore.isEnabled()) {
> +          // if this is the multi-core admin page, it will handle it
>           if( path.equals( multicore.getAdminPath() ) ) {
>             handler = multicore.getMultiCoreHandler();
> -
> -            // pick a core to use for output
> -            Collection<SolrCore> cores = multicore.getCores();
> -            if( cores != null && cores.size() > 0 ) {
> -              core = cores.iterator().next();
> -            }
> +            // pick a core to use for output generation
> +            core = multicore.getAdminCore();
>             if( core == null ) {
>               throw new RuntimeException( "Can not find a valid core  
> for the multicore admin handler" );
>             }
> -          }
> -          else {
> +          } else {
> +            //otherwise, we should find a core from the path
>             idx = path.indexOf( "/", 1 );
> -            if( idx <= 1 ) {
> -              idx = path.length();
> -            }
> -
> -            // try to get the corename as a request parameter first
> -            String corename = path.substring( 1, idx );
> -            path = path.substring( idx );
> -            core = multicore.getCore( corename );
> -
> -            if( path.length() == 0 ) {
> -              path = "/";
> -            }
> -
> -            if( core == null ) {
> -              throw new  
> SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown core:  
> "+corename );
> +            if( idx > 1 ) {
> +              // try to get the corename as a request parameter first
> +              String corename = path.substring( 1, idx );
> +              path = path.substring( idx );
> +              core = multicore.getCore( corename );
> +            } else {
> +              core = null;
>             }
>           }
>         }
> -
> -        SolrRequestParsers parser = parsers.get( core );
> -        if( parser == null ) {
> -          parser = new SolrRequestParsers( core.getSolrConfig() );
> -          parsers.put( core, parser );
> -        }
> -
> -        // Only try to parse the handler *if* a valid core exists
> -        // when multi-core is enabled, the path can lead to a null  
> core.
> -        if( handler == null && path.length() > 1 ) { // don't match  
> "" or "/" as valid path
> -          handler = core.getRequestHandler( path );
> -        }
> -        if( handler == null && parser.isHandleSelect() ) {
> -          if( "/select".equals( path ) || "/ 
> select/".equals( path ) ) {
> -            solrReq = parser.parse( core, path, req );
> -            String qt = solrReq.getParams().get( CommonParams.QT );
> -            if( qt != null && qt.startsWith( "/" ) ) {
> -              throw new  
> SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query  
> type.  Do not use /select to access: "+qt);
> -            }
> -            handler = core.getRequestHandler( qt );
> -            if( handler == null ) {
> -              throw new  
> SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown  
> handler: "+qt);
> -            }
> -          }
> +        else {
> +          core = singlecore;
>         }
>
> -        if( handler != null ) {
> -          if( solrReq == null ) {
> -            solrReq = parser.parse( core, path, req );
> +        // With a valid core...
> +        if( core != null ) {
> +          final SolrConfig config = core.getSolrConfig();
> +          // get or create/cache the parser for the core
> +          SolrRequestParsers parser = null;
> +          parser = parsers.get(core);
> +          if( parser == null ) {
> +            parser = new SolrRequestParsers(config);
> +            parsers.put( core, parser );
>           }
>
> -          final SolrConfig conf = core.getSolrConfig();
> -          final Method reqMethod = Method.getMethod(req.getMethod());
> -
> -          if (Method.POST != reqMethod) {
> -            HttpCacheHeaderUtil.setCacheControlHeader(conf, resp);
> -          }
> -
> -          // unless we have been explicitly told not to, do cache  
> validation
> -          if (!conf.getHttpCachingConfig().isNever304()) {
> -            // if we've confirmed cache validation, return  
> immediately
> -            if  
> (HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req,resp)) {
> -              return;
> +          // Determine the handler from the url path if not set
> +          // (we might already have selected the multicore handler)
> +          if( handler == null && path.length() > 1 ) { // don't  
> match "" or "/" as valid path
> +            handler = core.getRequestHandler( path );
> +            // no handler yet but allowed to handle select; let's  
> check
> +            if( handler == null && parser.isHandleSelect() ) {
> +              if( "/select".equals( path ) || "/ 
> select/".equals( path ) ) {
> +                solrReq = parser.parse( core, path, req );
> +                String qt =  
> solrReq.getParams().get( CommonParams.QT );
> +                if( qt != null && qt.startsWith( "/" ) ) {
> +                  throw new  
> SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query  
> type.  Do not use /select to access: "+qt);
> +                }
> +                handler = core.getRequestHandler( qt );
> +                if( handler == null ) {
> +                  throw new  
> SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown  
> handler: "+qt);
> +                }
> +              }
>             }
>           }
>
> -          SolrQueryResponse solrRsp = new SolrQueryResponse();
> -          /* even for HEAD requests, we need to execute the handler  
> to
> -           * ensure we don't get an error (and to make sure the  
> correct
> -           * QueryResponseWriter is selectedand we get the correct
> -           * Content-Type)
> -           */
> -          this.execute( req, handler, solrReq, solrRsp );
> -          if( solrRsp.getException() != null ) {
> -            sendError( (HttpServletResponse)response,  
> solrRsp.getException() );
> -            return;
> -          }
> -
> -          // Now write it out
> -          QueryResponseWriter responseWriter =  
> core.getQueryResponseWriter(solrReq);
> -           
> response.setContentType(responseWriter.getContentType(solrReq,  
> solrRsp));
> -          if (Method.HEAD == Method.getMethod(req.getMethod())) {
> -            // nothing to write out, waited this long just to get  
> ContentType
> -            return;
> +            // With a valid handler and a valid core...
> +          if( handler != null ) {
> +            // if not a /select, create the request
> +            if( solrReq == null ) {
> +              solrReq = parser.parse( core, path, req );
> +            }
> +
> +            final Method reqMethod =  
> Method.getMethod(req.getMethod());
> +            if (Method.POST != reqMethod) {
> +              HttpCacheHeaderUtil.setCacheControlHeader(config,  
> resp);
> +            }
> +            // unless we have been explicitly told not to, do cache  
> validation
> +            // if we fail cache validation, execute the query
> +            if (config.getHttpCachingConfig().isNever304() ||
> +                ! 
> HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req, resp)) {
> +                SolrQueryResponse solrRsp = new SolrQueryResponse();
> +                /* even for HEAD requests, we need to execute the  
> handler to
> +                 * ensure we don't get an error (and to make sure  
> the correct
> +                 * QueryResponseWriter is selectedand we get the  
> correct
> +                 * Content-Type)
> +                 */
> +                this.execute( req, handler, solrReq, solrRsp );
> +                if( solrRsp.getException() != null ) {
> +                  sendError( (HttpServletResponse)response,  
> solrRsp.getException() );
> +                }
> +                else {
> +                  // Now write it out
> +                  QueryResponseWriter responseWriter =  
> core.getQueryResponseWriter(solrReq);
> +                   
> response.setContentType(responseWriter.getContentType(solrReq,  
> solrRsp));
> +                        if (Method.HEAD !=  
> Method.getMethod(req.getMethod())) {
> +                  PrintWriter out = response.getWriter();
> +                  responseWriter.write(out, solrReq, solrRsp);
> +                }
> +                //else http HEAD request, nothing to write out,  
> waited this long just to get ContentType
> +              }
> +            }
> +            return; // we are done with a valid handler
>           }
> -
> -          PrintWriter out = response.getWriter();
> -          responseWriter.write(out, solrReq, solrRsp);
> -          return;
> -        }
> -        // otherwise, let's ensure the core is in the SolrCore  
> request attribute so
> -        // the servlet/jsp can retrieve it
> -        else {
> -          req.setAttribute("org.apache.solr.SolrCore", core);
> -
> -          // Let each core have its own admin page...
> -          if( singlecore == null && path.startsWith( "/admin" ) ) {
> -            req.getRequestDispatcher( path ).forward( request,  
> response );
> -            return;
> +          // otherwise (we have a core), let's ensure the core is  
> in the SolrCore request attribute so
> +          // a servlet/jsp can retrieve it
> +          else {
> +            req.setAttribute("org.apache.solr.SolrCore", core);
> +              // Modify the request so each core gets its own /admin
> +            if( singlecore == null && path.startsWith( "/admin" ) ) {
> +              req.getRequestDispatcher( path ).forward( request,  
> response );
> +              return;
> +            }
>           }
>         }
> -      }
> -      catch( Throwable ex ) {
> +        log.info("no handler or core retrieved for " + path + ",  
> follow through...");
> +      } catch (Throwable ex) {
>         sendError( (HttpServletResponse)response, ex );
>         return;
> -      }
> -      finally {
> +      } finally {
>         if( solrReq != null ) {
>           solrReq.close();
>         }
> @@ -326,8 +326,7 @@
>     sreq.getCore().execute( handler, sreq, rsp );
>   }
>
> -  protected void sendError(HttpServletResponse res, Throwable ex)  
> throws IOException
> -  {
> +  protected void sendError(HttpServletResponse res, Throwable ex)  
> throws IOException {
>     int code=500;
>     String trace = "";
>     if( ex instanceof SolrException ) {
>
>

--------------------------
Grant Ingersoll
http://www.lucenebootcamp.com
Next Training: April 7, 2008 at ApacheCon Europe in Amsterdam

Lucene Helpful Hints:
http://wiki.apache.org/lucene-java/BasicsOfPerformance
http://wiki.apache.org/lucene-java/LuceneFAQ