You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by si...@apache.org on 2010/10/20 14:44:39 UTC

svn commit: r1025539 [7/10] - in /lucene/dev/branches/docvalues: ./ lucene/ lucene/contrib/ lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ lucene/contrib/highlighter/src/test/ lucene/contrib/instantiated/src/test/org/apache...

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/CoreContainer.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/CoreContainer.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/CoreContainer.java Wed Oct 20 12:44:28 2010
@@ -21,6 +21,7 @@ import java.io.*;
 import java.nio.channels.FileChannel;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeoutException;
 import java.text.SimpleDateFormat;
 
 import org.slf4j.Logger;
@@ -31,13 +32,19 @@ import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathExpressionException;
 
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.cloud.SolrZkServer;
+import org.apache.solr.cloud.ZkController;
+import org.apache.solr.cloud.ZkSolrResourceLoader;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.cloud.ZooKeeperException;
 import org.apache.solr.common.params.CoreAdminParams;
 import org.apache.solr.common.util.DOMUtil;
 import org.apache.solr.common.util.XML;
 import org.apache.solr.common.util.FileUtils;
 import org.apache.solr.handler.admin.CoreAdminHandler;
 import org.apache.solr.schema.IndexSchema;
+import org.apache.zookeeper.KeeperException;
 import org.apache.commons.io.IOUtils;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -58,6 +65,9 @@ public class CoreContainer 
   protected boolean persistent = false;
   protected String adminPath = null;
   protected String managementPath = null;
+  protected String hostPort;
+  protected String hostContext;
+  protected String host;
   protected CoreAdminHandler coreAdminHandler = null;
   protected File configFile = null;
   protected String libDir = null;
@@ -68,13 +78,118 @@ public class CoreContainer 
   protected String adminHandler;
   protected boolean shareSchema;
   protected String solrHome;
+  @Deprecated
   protected String solrConfigFilenameOverride;
-  private String defaultCoreName = "";
-  
+  protected String defaultCoreName = "";
+  private ZkController zkController;
+  private SolrZkServer zkServer;
+
+  private String zkHost;
+
+  {
+    log.info("New CoreContainer: solrHome=" + solrHome + " instance="+System.identityHashCode(this));
+  }
+
   public CoreContainer() {
     solrHome = SolrResourceLoader.locateSolrHome();
   }
 
+  /**
+   * Initalize CoreContainer directly from the constructor
+   *
+   * @param dir
+   * @param configFile
+   * @throws ParserConfigurationException
+   * @throws IOException
+   * @throws SAXException
+   */
+  public CoreContainer(String dir, File configFile) throws ParserConfigurationException, IOException, SAXException
+  {
+    this.load(dir, configFile);
+  }
+
+  /**
+   * Minimal CoreContainer constructor.
+   * @param loader the CoreContainer resource loader
+   */
+  public CoreContainer(SolrResourceLoader loader) {
+    this.loader = loader;
+    this.solrHome = loader.getInstanceDir();
+  }
+
+  public CoreContainer(String solrHome) {
+    this.solrHome = solrHome;
+  }
+
+  protected void initZooKeeper(String zkHost, int zkClientTimeout) {
+    // if zkHost sys property is not set, we are not using ZooKeeper
+    String zookeeperHost;
+    if(zkHost == null) {
+      zookeeperHost = System.getProperty("zkHost");
+    } else {
+      zookeeperHost = zkHost;
+    }
+
+    String zkRun = System.getProperty("zkRun");
+
+    if (zkRun == null && zookeeperHost == null)
+        return;  // not in zk mode
+
+    zkServer = new SolrZkServer(zkRun, zookeeperHost, solrHome, hostPort);
+    zkServer.parseConfig();
+    zkServer.start();
+
+    // set client from server config if not already set
+    if (zookeeperHost == null) {
+      zookeeperHost = zkServer.getClientString();
+    }
+
+    int zkClientConnectTimeout = 5000;
+
+    if (zookeeperHost != null) {
+      // we are ZooKeeper enabled
+      try {
+        // If this is an ensemble, allow for a long connect time for other servers to come up
+        if (zkRun != null && zkServer.getServers().size() > 1) {
+          zkClientConnectTimeout = 24 * 60 * 60 * 1000;  // 1 day for embedded ensemble
+          log.info("Zookeeper client=" + zookeeperHost + "  Waiting for a quorum.");
+        } else {
+          log.info("Zookeeper client=" + zookeeperHost);          
+        }
+        zkController = new ZkController(zookeeperHost, zkClientTimeout, zkClientConnectTimeout, host, hostPort, hostContext);
+        
+        String confDir = System.getProperty("bootstrap_confdir");
+        if(confDir != null) {
+          File dir = new File(confDir);
+          if(!dir.isDirectory()) {
+            throw new IllegalArgumentException("bootstrap_confdir must be a directory of configuration files");
+          }
+          String confName = System.getProperty(ZkController.COLLECTION_PARAM_PREFIX+ZkController.CONFIGNAME_PROP, "configuration1");
+          zkController.uploadConfigDir(dir, confName);
+        }
+      } catch (InterruptedException e) {
+        // Restore the interrupted status
+        Thread.currentThread().interrupt();
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+            "", e);
+      } catch (TimeoutException e) {
+        log.error("Could not connect to ZooKeeper", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+            "", e);
+      } catch (IOException e) {
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+            "", e);
+      } catch (KeeperException e) {
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+            "", e);
+      }
+    }
+    
+  }
+
   public Properties getContainerProperties() {
     return containerProperties;
   }
@@ -82,6 +197,7 @@ public class CoreContainer 
   // Helper class to initialize the CoreContainer
   public static class Initializer {
     protected String solrConfigFilename = null;
+    protected String dataDir = null; // override datadir for single core mode
 
     /**
      * @deprecated all cores now abort on configuration error regardless of configuration
@@ -106,7 +222,8 @@ public class CoreContainer 
     public String getSolrConfigFilename() {
       return solrConfigFilename;
     }
-   @Deprecated
+
+    @Deprecated
     public void setSolrConfigFilename(String solrConfigFilename) {
       this.solrConfigFilename = solrConfigFilename;
     }
@@ -116,14 +233,16 @@ public class CoreContainer 
         ParserConfigurationException, SAXException {
       CoreContainer cores = null;
       String solrHome = SolrResourceLoader.locateSolrHome();
+      // TODO : fix broken logic confusing solr.xml with solrconfig.xml
       File fconf = new File(solrHome, solrConfigFilename == null ? "solr.xml"
           : solrConfigFilename);
       log.info("looking for solr.xml: " + fconf.getAbsolutePath());
       cores = new CoreContainer();
-      cores.solrConfigFilenameOverride = solrConfigFilename;
+      
       if (fconf.exists()) {
         cores.load(solrHome, fconf);
       } else {
+        log.info("no solr.xml file found - using default");
         cores.load(solrHome, new ByteArrayInputStream(DEF_SOLR_XML.getBytes()));
         cores.configFile = fconf;
       }
@@ -156,32 +275,7 @@ public class CoreContainer 
     return p;
   }
 
-  /**
-   * Initalize CoreContainer directly from the constructor
-   * 
-   * @param dir
-   * @param configFile
-   * @throws ParserConfigurationException
-   * @throws IOException
-   * @throws SAXException
-   */
-  public CoreContainer(String dir, File configFile) throws ParserConfigurationException, IOException, SAXException 
-  {
-    this.load(dir, configFile);
-  }
-  
-  /**
-   * Minimal CoreContainer constructor. 
-   * @param loader the CoreContainer resource loader
-   */
-  public CoreContainer(SolrResourceLoader loader) {
-    this.loader = loader;
-    this.solrHome = loader.getInstanceDir();
-  }
 
-  public CoreContainer(String solrHome) {
-    this.solrHome = solrHome;
-  }
 
   //-------------------------------------------------------------------
   // Initialization / Cleanup
@@ -219,15 +313,29 @@ public class CoreContainer 
       if(dcoreName != null) {
         defaultCoreName = dcoreName;
       }
-      persistent = cfg.getBool( "solr/@persistent", false );
-      libDir     = cfg.get(     "solr/@sharedLib", null);
-      adminPath  = cfg.get(     "solr/cores/@adminPath", null );
-      shareSchema = cfg.getBool("solr/cores/@shareSchema", false );
+      persistent = cfg.getBool("solr/@persistent", false);
+      libDir = cfg.get("solr/@sharedLib", null);
+      zkHost = cfg.get("solr/@zkHost" , null);
+      adminPath = cfg.get("solr/cores/@adminPath", null);
+      shareSchema = cfg.getBool("solr/cores/@shareSchema", false);
+      int zkClientTimeout = cfg.getInt("solr/cores/@zkClientTimeout", 10000);
+
+      hostPort = System.getProperty("hostPort");
+      if (hostPort == null) {
+        hostPort = cfg.get("solr/cores/@hostPort", "8983");
+      }
+
+      hostContext = cfg.get("solr/cores/@hostContext", "solr");
+      host = cfg.get("solr/cores/@host", null);
+
       if(shareSchema){
         indexSchemaCache = new ConcurrentHashMap<String ,IndexSchema>();
       }
       adminHandler  = cfg.get("solr/cores/@adminHandler", null );
       managementPath  = cfg.get("solr/cores/@managementPath", null );
+      
+      zkClientTimeout = Integer.parseInt(System.getProperty("zkClientTimeout", Integer.toString(zkClientTimeout)));
+      initZooKeeper(zkHost, zkClientTimeout);
 
       if (libDir != null) {
         File f = FileUtils.resolvePath(new File(dir), libDir);
@@ -249,25 +357,9 @@ public class CoreContainer 
         SolrConfig.severeErrors.add(e);
         SolrException.logOnce(log,null,e);
       }
-      
-      // before looping over each core, let's check the names and fail 
-      // fast if the same one is reused multiple times.
-      { // local scope, won't need these vars again
-        NodeList nodes = (NodeList)cfg.evaluate("solr/cores/core/@name", 
-                                                XPathConstants.NODESET);
-        Set<String> names = new HashSet<String>();
-        for (int i=0; i<nodes.getLength(); i++) {
-          String name = DOMUtil.getText(nodes.item(i));
-          if (names.contains(name)) {
-            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
-                                    "Multiple cores found with same name: " + 
-                                    name);
-          }
-          names.add(name);
-        }
-      }
 
       NodeList nodes = (NodeList)cfg.evaluate("solr/cores/core", XPathConstants.NODESET);
+      boolean defaultCoreFound = false;
       for (int i=0; i<nodes.getLength(); i++) {
         Node node = nodes.item(i);
         try {
@@ -282,12 +374,12 @@ public class CoreContainer 
             // be mapped to this.
             name="";
           }
-
           CoreDescriptor p = new CoreDescriptor(this, name, DOMUtil.getAttr(node, "instanceDir", null));
 
           // deal with optional settings
           String opt = DOMUtil.getAttr(node, "config", null);
-          if(solrConfigFilenameOverride != null && name.equals("")) {
+
+          if(solrConfigFilenameOverride != null) {
             p.setConfigName(solrConfigFilenameOverride);
           } else if (opt != null) {
             p.setConfigName(opt);
@@ -296,6 +388,16 @@ public class CoreContainer 
           if (opt != null) {
             p.setSchemaName(opt);
           }
+          if (zkController != null) {
+            opt = DOMUtil.getAttr(node, "shard", null);
+            if (opt != null && opt.length() > 0) {
+              p.getCloudDescriptor().setShardId(opt);
+            }
+            opt = DOMUtil.getAttr(node, "collection", null);
+            if (opt != null) {
+              p.getCloudDescriptor().setCollectionName(opt);
+            }
+          }
           opt = DOMUtil.getAttr(node, "properties", null);
           if (opt != null) {
             p.setPropertiesName(opt);
@@ -315,13 +417,35 @@ public class CoreContainer 
           SolrException.logOnce(log,null,ex);
         }
       }
-    }
-
-    finally {
+    } finally {
       if (cfgis != null) {
         try { cfgis.close(); } catch (Exception xany) {}
       }
     }
+    
+    
+    if(zkController != null) {
+      try {
+        synchronized (zkController.getZkStateReader().getUpdateLock()) {
+          zkController.getZkStateReader().makeShardZkNodeWatches(false);
+          zkController.getZkStateReader().updateCloudState(true);
+        }
+      } catch (InterruptedException e) {
+        // Restore the interrupted status
+        Thread.currentThread().interrupt();
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+            "", e);
+      } catch (KeeperException e) {
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+            "", e);
+      } catch (IOException e) {
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+            "", e);
+      }
+    }
   }
 
   private Properties readProperties(Config cfg, Node node) throws XPathExpressionException {
@@ -339,6 +463,7 @@ public class CoreContainer 
    * Stops all cores.
    */
   public void shutdown() {
+    log.info("Shutting down CoreContainer instance="+System.identityHashCode(this));    
     synchronized(cores) {
       try {
         for(SolrCore core : cores.values()) {
@@ -346,6 +471,12 @@ public class CoreContainer 
         }
         cores.clear();
       } finally {
+        if(zkController != null) {
+          zkController.close();
+        }
+        if (zkServer != null) {
+          zkServer.stop();
+        }
         isShutDown = true;
       }
     }
@@ -355,7 +486,7 @@ public class CoreContainer 
   protected void finalize() throws Throwable {
     try {
       if(!isShutDown){
-        log.error("CoreContainer was not shutdown prior to finalize(), indicates a bug -- POSSIBLE RESOURCE LEAK!!!");
+        log.error("CoreContainer was not shutdown prior to finalize(), indicates a bug -- POSSIBLE RESOURCE LEAK!!!  instance=" + System.identityHashCode(this));
         shutdown();
       }
     } finally {
@@ -385,6 +516,24 @@ public class CoreContainer 
       core.setName(name);
     }
 
+    if (zkController != null) {
+      try {
+        zkController.register(core.getName(), core.getCoreDescriptor().getCloudDescriptor(), true);
+      } catch (InterruptedException e) {
+        // Restore the interrupted status
+        Thread.currentThread().interrupt();
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "",
+            e);
+      } catch (KeeperException e) {
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "",
+            e);
+      } catch (IOException e) {
+        log.error("", e);
+        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "", e);
+      }
+    }
 
     if( old == null || old == core) {
       log.info( "registering core: "+name );
@@ -427,32 +576,88 @@ public class CoreContainer 
     String instanceDir = idir.getPath();
     
     // Initialize the solr config
-    SolrResourceLoader solrLoader = new SolrResourceLoader(instanceDir, libLoader, getCoreProps(instanceDir, dcore.getPropertiesName(),dcore.getCoreProperties()));
-    SolrConfig config = new SolrConfig(solrLoader, dcore.getConfigName(), null);
-
+    SolrResourceLoader solrLoader = null;
+    
+    SolrConfig config = null;
+    String zkConfigName = null;
+    if(zkController == null) {
+      solrLoader = new SolrResourceLoader(instanceDir, libLoader, getCoreProps(instanceDir, dcore.getPropertiesName(),dcore.getCoreProperties()));
+      config = new SolrConfig(solrLoader, dcore.getConfigName(), null);
+    } else {
+      try {
+        String collection = dcore.getCloudDescriptor().getCollectionName();
+        zkController.createCollectionZkNode(dcore.getCloudDescriptor());
+        // zkController.createCollectionZkNode(collection);
+        zkConfigName = zkController.readConfigName(collection);
+        if (zkConfigName == null) {
+          log.error("Could not find config name for collection:" + collection);
+          throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+              "Could not find config name for collection:" + collection);
+        }
+        solrLoader = new ZkSolrResourceLoader(instanceDir, zkConfigName, libLoader, getCoreProps(instanceDir, dcore.getPropertiesName(),dcore.getCoreProperties()), zkController);
+        config = getSolrConfigFromZk(zkConfigName, dcore.getConfigName(), solrLoader);
+      } catch (KeeperException e) {
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+            "", e);
+      } catch (InterruptedException e) {
+        // Restore the interrupted status
+        Thread.currentThread().interrupt();
+        log.error("", e);
+        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+            "", e);
+      }
+    }
+    
     IndexSchema schema = null;
-    if(indexSchemaCache != null){
-      //schema sharing is enabled. so check if it already is loaded
-      File schemaFile = new File(dcore.getSchemaName());
-      if (!schemaFile.isAbsolute()) {
-        schemaFile = new File(solrLoader.getInstanceDir() + "conf" + File.separator + dcore.getSchemaName());
-      }
-      if(schemaFile. exists()){
-        String key = schemaFile.getAbsolutePath()+":"+new SimpleDateFormat("yyyyMMddHHmmss", Locale.US).format(new Date(schemaFile.lastModified()));
-        schema = indexSchemaCache.get(key);
-        if(schema == null){
-          log.info("creating new schema object for core: " + dcore.name);
-          schema = new IndexSchema(config, dcore.getSchemaName(), null);
-          indexSchemaCache.put(key,schema);
-        } else {
-          log.info("re-using schema object for core: " + dcore.name);
+    if (indexSchemaCache != null) {
+      if (zkController != null) {
+        File schemaFile = new File(dcore.getSchemaName());
+        if (!schemaFile.isAbsolute()) {
+          schemaFile = new File(solrLoader.getInstanceDir() + "conf"
+              + File.separator + dcore.getSchemaName());
+        }
+        if (schemaFile.exists()) {
+          String key = schemaFile.getAbsolutePath()
+              + ":"
+              + new SimpleDateFormat("yyyyMMddHHmmss", Locale.US).format(new Date(
+                  schemaFile.lastModified()));
+          schema = indexSchemaCache.get(key);
+          if (schema == null) {
+            log.info("creating new schema object for core: " + dcore.name);
+            schema = new IndexSchema(config, dcore.getSchemaName(), null);
+            indexSchemaCache.put(key, schema);
+          } else {
+            log.info("re-using schema object for core: " + dcore.name);
+          }
         }
+      } else {
+        // TODO: handle caching from ZooKeeper - perhaps using ZooKeepers versioning
+        // Don't like this cache though - how does it empty as last modified changes?
       }
     }
     if(schema == null){
-      schema = new IndexSchema(config, dcore.getSchemaName(), null);
+      if(zkController != null) {
+        try {
+          schema = getSchemaFromZk(zkConfigName, dcore.getSchemaName(), config, solrLoader);
+        } catch (KeeperException e) {
+          log.error("", e);
+          throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+              "", e);
+        } catch (InterruptedException e) {
+          // Restore the interrupted status
+          Thread.currentThread().interrupt();
+          log.error("", e);
+          throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+              "", e);
+        }
+      } else {
+        schema = new IndexSchema(config, dcore.getSchemaName(), null);
+      }
     }
-    SolrCore core = new SolrCore(dcore.getName(), null, config, schema, dcore);
+    String dataDir = null;
+
+    SolrCore core = new SolrCore(dcore.getName(), dataDir, config, schema, dcore);
     return core;
   }
     
@@ -744,6 +949,18 @@ public class CoreContainer 
     }
     opt = dcore.dataDir;
     if (opt != null) writeAttribute(w,"dataDir",opt);
+
+    CloudDescriptor cd = dcore.getCloudDescriptor();
+    if (cd != null) {
+      opt = cd.getShardId();
+      if (opt != null)
+        writeAttribute(w,"shard",opt);
+      // only write out the collection name if it's not the default (the core name)
+      opt = cd.getCollectionName();
+      if (opt != null && !opt.equals(dcore.name))
+        writeAttribute(w,"collection",opt);
+    }
+
     if (dcore.getCoreProperties() == null || dcore.getCoreProperties().isEmpty())
       w.write("/>\n"); // core
     else  {
@@ -801,6 +1018,37 @@ public class CoreContainer 
   public String getSolrHome() {
     return solrHome;
   }
+  
+  public boolean isZooKeeperAware() {
+    return zkController != null;
+  }
+  
+  public ZkController getZkController() {
+    return zkController;
+  }
+  
+  private SolrConfig getSolrConfigFromZk(String zkConfigName, String solrConfigFileName,
+      SolrResourceLoader resourceLoader) throws IOException,
+      ParserConfigurationException, SAXException, KeeperException,
+      InterruptedException {
+    byte[] config = zkController.getConfigFileData(zkConfigName, solrConfigFileName);
+    InputStream is = new ByteArrayInputStream(config);
+    SolrConfig cfg = solrConfigFileName == null ? new SolrConfig(
+        resourceLoader, SolrConfig.DEFAULT_CONF_FILE, is) : new SolrConfig(
+        resourceLoader, solrConfigFileName, is);
+
+    return cfg;
+  }
+  
+  private IndexSchema getSchemaFromZk(String zkConfigName, String schemaName,
+      SolrConfig config, SolrResourceLoader resourceLoader)
+      throws KeeperException, InterruptedException {
+    byte[] configBytes = zkController.getConfigFileData(zkConfigName, schemaName);
+    InputStream is = new ByteArrayInputStream(configBytes);
+    IndexSchema schema = new IndexSchema(config, schemaName, is);
+    return schema;
+  }
+  
   private static final String DEF_SOLR_XML ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
           "<solr persistent=\"false\">\n" +
           "  <cores adminPath=\"/admin/cores\" defaultCoreName=\"" + DEFAULT_DEFAULT_CORE_NAME + "\">\n" +

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/CoreDescriptor.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/CoreDescriptor.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/CoreDescriptor.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/CoreDescriptor.java Wed Oct 20 12:44:28 2010
@@ -20,6 +20,8 @@ package org.apache.solr.core;
 import java.util.Properties;
 import java.io.File;
 
+import org.apache.solr.cloud.CloudDescriptor;
+
 /**
  * A Solr core descriptor
  *
@@ -34,10 +36,20 @@ public class CoreDescriptor {
   protected String schemaName;
   private final CoreContainer coreContainer;
   private Properties coreProperties;
+  
+  private CloudDescriptor cloudDesc;
 
   public CoreDescriptor(CoreContainer coreContainer, String name, String instanceDir) {
     this.coreContainer = coreContainer;
     this.name = name;
+    
+    if(coreContainer.getZkController() != null) {
+      this.cloudDesc = new CloudDescriptor();
+      // cloud collection defaults to core name
+      cloudDesc.setCollectionName(name == "" ? coreContainer.getDefaultCoreName() : name);
+      this.cloudDesc.setShardId(coreContainer.getZkController().getNodeName() + "_" + name);
+    }
+    
     if (name == null) {
       throw new RuntimeException("Core needs a name");
     }
@@ -112,6 +124,10 @@ public class CoreDescriptor {
     // normalize zero length to null.
     if (dataDir != null && dataDir.length()==0) dataDir=null;
   }
+  
+  public boolean usingDefaultDataDir() {
+    return this.dataDir == null;
+  }
 
   /**@return the core instance directory. */
   public String getInstanceDir() {
@@ -171,4 +187,12 @@ public class CoreDescriptor {
         this.coreProperties.putAll(coreProperties);
     }
   }
+
+  public CloudDescriptor getCloudDescriptor() {
+    return cloudDesc;
+  }
+  
+  public void setCloudDescriptor(CloudDescriptor cloudDesc) {
+    this.cloudDesc = cloudDesc;
+  }
 }

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/IndexReaderFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/JmxMonitoredMap.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Oct 20 12:44:28 2010
@@ -1 +1 @@
-Id
+Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/PluginInfo.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Oct 20 12:44:28 2010
@@ -1 +1 @@
-Id
+Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/RAMDirectoryFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/RefCntRamDirectory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/SolrCore.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/SolrCore.java Wed Oct 20 12:44:28 2010
@@ -512,7 +512,8 @@ public final class SolrCore implements S
     this.setName( name );
     resourceLoader = config.getResourceLoader();
     if (dataDir == null){
-      dataDir =  config.getDataDir();
+      // nocommit: why did solrconfig override core descriptor !?
+      if(cd.usingDefaultDataDir()) dataDir = config.getDataDir();
       if(dataDir == null) dataDir = cd.getDataDir();
     }
 
@@ -684,6 +685,19 @@ public final class SolrCore implements S
       return;
     }
     log.info(logid+" CLOSING SolrCore " + this);
+
+
+    if( closeHooks != null ) {
+       for( CloseHook hook : closeHooks ) {
+         try {
+           hook.close( this );
+         } catch (Throwable e) {
+           SolrException.log(log, e);           
+         }
+      }
+    }
+
+
     try {
       infoRegistry.clear();
     } catch (Exception e) {
@@ -695,20 +709,27 @@ public final class SolrCore implements S
       SolrException.log(log,e);
     }
     try {
-      closeSearcher();
+      searcherExecutor.shutdown();
+      if (!searcherExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
+        log.error("Timeout waiting for searchExecutor to terminate");
+      }
     } catch (Exception e) {
       SolrException.log(log,e);
     }
     try {
-      searcherExecutor.shutdown();
+      // Since we waited for the searcherExecutor to shut down,
+      // there should be no more searchers warming in the background
+      // that we need to take care of.
+      //
+      // For the case that a searcher was registered *before* warming
+      // then the searchExecutor will throw an exception when getSearcher()
+      // tries to use it, and the exception handling code should close it.
+      closeSearcher();
     } catch (Exception e) {
       SolrException.log(log,e);
     }
-    if( closeHooks != null ) {
-       for( CloseHook hook : closeHooks ) {
-         hook.close( this );
-      }
-    }
+
+
   }
 
   /** Current core usage count. */
@@ -833,7 +854,6 @@ public final class SolrCore implements S
     addIfNotPresent(components,HighlightComponent.COMPONENT_NAME,HighlightComponent.class);
     addIfNotPresent(components,QueryComponent.COMPONENT_NAME,QueryComponent.class);
     addIfNotPresent(components,FacetComponent.COMPONENT_NAME,FacetComponent.class);
-    addIfNotPresent(components,PivotFacetComponent.COMPONENT_NAME,PivotFacetComponent.class);
     addIfNotPresent(components,MoreLikeThisComponent.COMPONENT_NAME,MoreLikeThisComponent.class);
     addIfNotPresent(components,StatsComponent.COMPONENT_NAME,StatsComponent.class);
     addIfNotPresent(components,DebugComponent.COMPONENT_NAME,DebugComponent.class);
@@ -842,6 +862,9 @@ public final class SolrCore implements S
   private <T> void addIfNotPresent(Map<String ,T> registry, String name, Class<? extends  T> c){
     if(!registry.containsKey(name)){
       T searchComp = (T) resourceLoader.newInstance(c.getName());
+      if (searchComp instanceof NamedListInitializedPlugin){
+        ((NamedListInitializedPlugin)searchComp).init( new NamedList() );
+      }
       registry.put(name, searchComp);
       if (searchComp instanceof SolrInfoMBean){
         infoRegistry.put(((SolrInfoMBean)searchComp).getName(), (SolrInfoMBean)searchComp);
@@ -1272,6 +1295,18 @@ public final class SolrCore implements S
         _searcher = newSearcherHolder;
         SolrIndexSearcher newSearcher = newSearcherHolder.get();
 
+        /***
+        // a searcher may have been warming asynchronously while the core was being closed.
+        // if this happens, just close the searcher.
+        if (isClosed()) {
+          // NOTE: this should not happen now - see close() for details.
+          // *BUT* if we left it enabled, this could still happen before
+          // close() stopped the executor - so disable this test for now.
+          log.error("Ignoring searcher register on closed core:" + newSearcher);
+          _searcher.decref();
+        }
+        ***/
+
         newSearcher.register(); // register subitems (caches)
         log.info(logid+"Registered new searcher " + newSearcher);
 
@@ -1556,12 +1591,10 @@ public final class SolrCore implements S
         
         // Hide everything...
         Set<String> hide = new HashSet<String>();
-        File configdir = new File( solrConfig.getResourceLoader().getConfigDir() ); 
-        if( configdir.exists() && configdir.isDirectory() ) {
-          for( String file : configdir.list() ) {
-            hide.add( file.toUpperCase(Locale.ENGLISH) );
-          }
-        }
+
+        for (String file : solrConfig.getResourceLoader().listConfigDir()) {
+          hide.add(file.toUpperCase(Locale.ENGLISH));
+        }    
         
         // except the "gettable" list
         StringTokenizer st = new StringTokenizer( gettable );
@@ -1588,16 +1621,7 @@ public final class SolrCore implements S
           "solrconfig.xml uses deprecated <bool name='facet.sort'>. Please "+
           "update your config to use <string name='facet.sort'>.");
     }
-
-    if (!solrConfig.getBool("abortOnConfigurationError",true))
-      throw new SolrException(ErrorCode.SERVER_ERROR,
-                              "Setting abortOnConfigurationError==false is no longer supported");
-    if (null != solrConfig.getVal("abortOnConfigurationError", false))
-      log.warn("The abortOnConfigurationError option is no longer supported "+
-               "in solrconfig.xml.  Setting it has no effect.");
-    
-  }
-  
+  } 
 
   public CoreDescriptor getCoreDescriptor() {
     return coreDescriptor;

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/SolrResourceLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/SolrResourceLoader.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/SolrResourceLoader.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/core/SolrResourceLoader.java Wed Oct 20 12:44:28 2010
@@ -69,7 +69,7 @@ public class SolrResourceLoader implemen
   static final String base = "org.apache" + "." + project;
   static final String[] packages = {"","analysis.","schema.","handler.","search.","update.","core.","response.","request.","update.processor.","util.", "spelling.", "handler.component.", "handler.dataimport." };
 
-  private URLClassLoader classLoader;
+  protected URLClassLoader classLoader;
   private final String instanceDir;
   private String dataDir;
   
@@ -205,6 +205,15 @@ public class SolrResourceLoader implemen
   public  static String normalizeDir(String path) {
     return ( path != null && (!(path.endsWith("/") || path.endsWith("\\"))) )? path + File.separator : path;
   }
+  
+  public String[] listConfigDir() {
+    File configdir = new File(getConfigDir());
+    if( configdir.exists() && configdir.isDirectory() ) {
+      return configdir.list();
+    } else {
+      return new String[0];
+    }
+  }
 
   public String getConfigDir() {
     return instanceDir + "conf/";

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/AnalysisRequestHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/AnalysisRequestHandler.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/AnalysisRequestHandler.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/AnalysisRequestHandler.java Wed Oct 20 12:44:28 2010
@@ -227,17 +227,17 @@ public class AnalysisRequestHandler exte
 
   @Override
   public String getVersion() {
-    return "$Revision:$";
+    return "$Revision$";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id:$";
+    return "$Id$";
   }
 
   @Override
   public String getSource() {
-    return "$URL:$";
+    return "$URL$";
   }
 
 }

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/AnalysisRequestHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/ContentStreamHandlerBase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/ContentStreamLoader.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/RequestHandlerBase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/SpellCheckerRequestHandler.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Oct 20 12:44:28 2010
@@ -1 +1 @@
-URL Revision Id
+Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/XMLLoader.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java Wed Oct 20 12:44:28 2010
@@ -23,6 +23,7 @@ import org.apache.solr.common.params.Sol
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.XML;
 import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequestBase;
 import org.apache.solr.response.SolrQueryResponse;
@@ -117,15 +118,13 @@ public class XmlUpdateRequestHandler ext
    */
   @Deprecated
   public void doLegacyUpdate(Reader input, Writer output) {
-    try {
-      SolrCore core = SolrCore.getSolrCore();
+    SolrCore core = SolrCore.getSolrCore();
+    SolrQueryRequest req = new LocalSolrQueryRequest(core, new HashMap<String,String[]>());
 
+    try {
       // Old style requests do not choose a custom handler
       UpdateRequestProcessorChain processorFactory = core.getUpdateProcessingChain(null);
 
-      SolrParams params = new MapSolrParams(new HashMap<String, String>());
-      SolrQueryRequestBase req = new SolrQueryRequestBase(core, params) {
-      };
       SolrQueryResponse rsp = new SolrQueryResponse(); // ignored
       XMLStreamReader parser = inputFactory.createXMLStreamReader(input);
       UpdateRequestProcessor processor = processorFactory.createProcessor(req, rsp);
@@ -142,6 +141,9 @@ public class XmlUpdateRequestHandler ext
         log.error("Error writing to output stream: " + ee);
       }
     }
+    finally {
+      req.close();
+    }
   }
   //////////////////////// SolrInfoMBeans methods //////////////////////
 

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java Wed Oct 20 12:44:28 2010
@@ -17,6 +17,7 @@
 
 package org.apache.solr.handler.admin;
 
+import org.apache.solr.cloud.CloudDescriptor;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CoreAdminParams;
 import org.apache.solr.common.params.CoreAdminParams.CoreAdminAction;
@@ -177,6 +178,7 @@ public class CoreAdminHandler extends Re
     SolrParams required = params.required();
     String cname = required.get(CoreAdminParams.CORE);
     SolrCore core = coreContainer.getCore(cname);
+    SolrQueryRequest wrappedReq = null;
     if (core != null) {
       try {
         doPersist = coreContainer.isPersistent();
@@ -191,12 +193,13 @@ public class CoreAdminHandler extends Re
 
         UpdateRequestProcessorChain processorChain =
                 core.getUpdateProcessingChain(params.get(UpdateParams.UPDATE_PROCESSOR));
-        SolrQueryRequest wrappedReq = new LocalSolrQueryRequest(core, req.getParams());
+        wrappedReq = new LocalSolrQueryRequest(core, req.getParams());
         UpdateRequestProcessor processor =
                 processorChain.createProcessor(wrappedReq, rsp);
         processor.processMergeIndexes(new MergeIndexesCommand(dirs));
       } finally {
         core.close();
+        wrappedReq.close();
       }
     }
     return doPersist;
@@ -228,7 +231,14 @@ public class CoreAdminHandler extends Re
     try {
       SolrParams params = req.getParams();
       String name = params.get(CoreAdminParams.NAME);
-      CoreDescriptor dcore = new CoreDescriptor(coreContainer, name, params.get(CoreAdminParams.INSTANCE_DIR));
+
+      String instanceDir = params.get(CoreAdminParams.INSTANCE_DIR);
+      if (instanceDir == null) {
+        // instanceDir = coreContainer.getSolrHome() + "/" + name;
+        instanceDir = name; // bare name is already relative to solr home
+      }
+
+      CoreDescriptor dcore = new CoreDescriptor(coreContainer, name, instanceDir);
 
       //  fillup optional parameters
       String opts = params.get(CoreAdminParams.CONFIG);
@@ -243,6 +253,19 @@ public class CoreAdminHandler extends Re
       if (opts != null)
         dcore.setDataDir(opts);
 
+      CloudDescriptor cd = dcore.getCloudDescriptor();
+      if (cd != null) {
+        cd.setParams(req.getParams());
+
+        opts = params.get(CoreAdminParams.COLLECTION);
+        if (opts != null)
+          cd.setCollectionName(opts);
+        
+        opts = params.get(CoreAdminParams.SHARD);
+        if (opts != null)
+          cd.setShardId(opts);
+      }
+
       dcore.setCoreProperties(null);
       SolrCore core = coreContainer.create(dcore);
       coreContainer.register(name, core, false);

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/FacetComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/FacetComponent.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/FacetComponent.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/FacetComponent.java Wed Oct 20 12:44:28 2010
@@ -41,10 +41,20 @@ import org.apache.lucene.queryParser.Par
  * @version $Id$
  * @since solr 1.3
  */
-public class  FacetComponent extends SearchComponent
+public class FacetComponent extends SearchComponent
 {
   public static final String COMPONENT_NAME = "facet";
 
+  static final String PIVOT_KEY = "facet_pivot";
+
+  PivotFacetHelper pivotHelper;
+
+  @Override
+  public void init( NamedList args )
+  {
+    pivotHelper = new PivotFacetHelper(); // Maybe this would configurable?
+  }
+
   @Override
   public void prepare(ResponseBuilder rb) throws IOException
   {
@@ -68,8 +78,17 @@ public class  FacetComponent extends Sea
               params,
               rb );
 
+      NamedList counts = f.getFacetCounts();
+      String[] pivots = params.getParams( FacetParams.FACET_PIVOT );
+      if( pivots != null && pivots.length > 0 ) {
+        NamedList v = pivotHelper.process(rb, params, pivots);
+        if( v != null ) {
+          counts.add( PIVOT_KEY, v );
+        }
+      }
+      
       // TODO ???? add this directly to the response, or to the builder?
-      rb.rsp.add( "facet_counts", f.getFacetCounts() );
+      rb.rsp.add( "facet_counts", counts );
     }
   }
 

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/FieldFacetStats.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/QueryComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/QueryComponent.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/QueryComponent.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/QueryComponent.java Wed Oct 20 12:44:28 2010
@@ -22,12 +22,19 @@ import org.apache.lucene.index.Term;
 import org.apache.lucene.queryParser.ParseException;
 import org.apache.lucene.search.*;
 import org.apache.lucene.util.BytesRef;
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.cloud.ZkController;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.cloud.CloudState;
+import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.cloud.ZkNodeProps;
+import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.*;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.StrUtils;
+import org.apache.solr.core.CoreDescriptor;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.schema.FieldType;
@@ -110,11 +117,116 @@ public class QueryComponent extends Sear
       throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
     }
 
-    // TODO: temporary... this should go in a different component.
+    checkDistributed(rb);
+  }
+
+
+  // TODO: this could go in a different component, or in SearchHandler
+  // check if this is a distributed request and set info on the response builder
+  void checkDistributed(ResponseBuilder rb) {
+    SolrQueryRequest req = rb.req;
+    SolrParams params = req.getParams();
+
+    rb.isDistrib = params.getBool("distrib",false);
     String shards = params.get(ShardParams.SHARDS);
-    if (shards != null) {
-      List<String> lst = StrUtils.splitSmart(shards, ",", true);
-      rb.shards = lst.toArray(new String[lst.size()]);
+
+    // for back compat, a shards param with URLs like localhost:8983/solr will mean that this
+    // search is distributed.
+    boolean hasShardURL = shards != null && shards.indexOf('/') > 0;
+    rb.isDistrib = hasShardURL | rb.isDistrib;
+
+    if (rb.isDistrib) {
+      // since the cost of grabbing cloud state is still up in the air, we grab it only
+      // if we need it.
+      CloudState cloudState = null;
+      Map<String,Slice> slices = null;
+      CoreDescriptor coreDescriptor = req.getCore().getCoreDescriptor();
+      CloudDescriptor cloudDescriptor = coreDescriptor.getCloudDescriptor();
+      ZkController zkController = coreDescriptor.getCoreContainer().getZkController();
+
+
+      if (shards != null) {
+        List<String> lst = StrUtils.splitSmart(shards, ",", true);
+        rb.shards = lst.toArray(new String[lst.size()]);
+        rb.slices = new String[rb.shards.length];
+
+        if (zkController != null) {
+          // figure out which shards are slices
+          for (int i=0; i<rb.shards.length; i++) {
+            if (rb.shards[i].indexOf('/') < 0) {
+              // this is a logical shard
+              rb.slices[i] = rb.shards[i];
+              rb.shards[i] = null;
+            }
+          }
+        }
+      } else if (zkController != null) {
+        // we weren't provided with a list of slices to query, so find the list that will cover the complete index
+
+        cloudState =  zkController.getCloudState();
+
+        // TODO: check "collection" for which collection(s) to search.. but for now, just default
+        // to the collection for this core.
+        // This can be more efficient... we only record the name, even though we have the
+        // shard info we need in the next step of mapping slice->shards
+        slices = cloudState.getSlices(cloudDescriptor.getCollectionName());
+        rb.slices = slices.keySet().toArray(new String[slices.size()]);
+        rb.shards = new String[rb.slices.length];
+        
+        /***
+         rb.slices = new String[slices.size()];
+         for (int i=0; i<rb.slices.length; i++) {
+         rb.slices[i] = slices.get(i).getName();
+         }
+         ***/
+      }
+
+      //
+      // Map slices to shards
+      //
+      if (zkController != null) {
+        for (int i=0; i<rb.shards.length; i++) {
+          if (rb.shards[i] == null) {
+            if (cloudState == null) {
+              cloudState =  zkController.getCloudState();
+              slices = cloudState.getSlices(cloudDescriptor.getCollectionName());
+            }
+            String sliceName = rb.slices[i];
+
+            Slice slice = slices.get(sliceName);
+
+            if (slice==null) {
+              // Treat this the same as "all servers down" for a slice, and let things continue
+              // if partial results are acceptable
+              rb.shards[i] = "";
+              continue;
+              // throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "no such shard: " + sliceName);
+            }
+
+            Map<String, ZkNodeProps> sliceShards = slice.getShards();
+
+            // For now, recreate the | delimited list of equivalent servers
+            Set<String> liveNodes = cloudState.getLiveNodes();
+            StringBuilder sliceShardsStr = new StringBuilder();
+            boolean first = true;
+            for (ZkNodeProps nodeProps : sliceShards.values()) {
+              if (!liveNodes.contains(nodeProps.get(ZkStateReader.NODE_NAME)))
+                continue;
+              if (first) {
+                first = false;
+              } else {
+                sliceShardsStr.append('|');
+              }
+              String url = nodeProps.get("url");
+              if (url.startsWith("http://"))
+                url = url.substring(7);
+              sliceShardsStr.append(url);
+            }
+
+            rb.shards[i] = sliceShardsStr.toString();
+          }
+        }
+      }
     }
     String shards_rows = params.get(ShardParams.SHARDS_ROWS);
     if(shards_rows != null) {

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/QueryElevationComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/QueryElevationComponent.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/QueryElevationComponent.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/QueryElevationComponent.java Wed Oct 20 12:44:28 2010
@@ -32,7 +32,6 @@ import java.util.WeakHashMap;
 
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.QueryElevationParams;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,6 +47,7 @@ import org.apache.lucene.index.IndexRead
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.*;
 import org.apache.lucene.util.StringHelper;
+import org.apache.solr.cloud.ZkController;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.SolrParams;
@@ -172,19 +172,30 @@ public class QueryElevationComponent ext
               "QueryElevationComponent must specify argument: '"+CONFIG_FILE
               +"' -- path to elevate.xml" );
         }
-        File fC = new File( core.getResourceLoader().getConfigDir(), f );
-        File fD = new File( core.getDataDir(), f );
-        if( fC.exists() == fD.exists() ) {
-          throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
-              "QueryElevationComponent missing config file: '"+f + "\n"
-              +"either: "+fC.getAbsolutePath() + " or " + fD.getAbsolutePath() + " must exist, but not both." );
-        }
-        if( fC.exists() ) {
-          log.info( "Loading QueryElevation from: "+fC.getAbsolutePath() );
-          Config cfg = new Config( core.getResourceLoader(), f );
-          elevationCache.put(null, loadElevationMap( cfg ));
+        boolean exists = false;
+
+        // check if using ZooKeeper
+        ZkController zkController = core.getCoreDescriptor().getCoreContainer().getZkController();
+        if(zkController != null) {
+          // TODO : shouldn't have to keep reading the config name when it has been read before
+          exists = zkController.configFileExists(zkController.readConfigName(core.getCoreDescriptor().getCloudDescriptor().getCollectionName()), f);
+        } else {
+          File fC = new File( core.getResourceLoader().getConfigDir(), f );
+          File fD = new File( core.getDataDir(), f );
+          if( fC.exists() == fD.exists() ) {
+            throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
+                "QueryElevationComponent missing config file: '"+f + "\n"
+                +"either: "+fC.getAbsolutePath() + " or " + fD.getAbsolutePath() + " must exist, but not both." );
+          }
+          if( fC.exists() ) {
+            exists = true;
+            log.info( "Loading QueryElevation from: "+ fC.getAbsolutePath() );
+            Config cfg = new Config( core.getResourceLoader(), f );
+            elevationCache.put(null, loadElevationMap( cfg ));
+          } 
         }
-        else {
+        
+        if (!exists){
           // preload the first data
           RefCounted<SolrIndexSearcher> searchHolder = null;
           try {

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ResponseBuilder.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ResponseBuilder.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ResponseBuilder.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ResponseBuilder.java Wed Oct 20 12:44:28 2010
@@ -26,15 +26,11 @@ import org.apache.solr.request.SolrQuery
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.search.DocListAndSet;
 import org.apache.solr.search.QParser;
-import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.search.SortSpec;
-import org.apache.solr.util.SolrPluginUtils;
+import org.apache.solr.search.SolrIndexSearcher;
 
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * This class is experimental and will be changing in the future.
@@ -42,9 +38,8 @@ import java.util.Set;
  * @version $Id$
  * @since solr 1.3
  */
-public class ResponseBuilder {
-
-
+public class ResponseBuilder
+{
   public SolrQueryRequest req;
   public SolrQueryResponse rsp;
   public boolean doHighlights;
@@ -101,7 +96,9 @@ public class ResponseBuilder {
   public int stage;  // What stage is this current request at?
 
   //The address of the Shard
+  boolean isDistrib; // is this a distributed search?
   public String[] shards;
+  public String[] slices; // the optional logical ids of the shards
   public int shards_rows = -1;
   public int shards_start = -1;
   public List<ShardRequest> outgoing;  // requests to be sent

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/SearchHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/SearchHandler.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/SearchHandler.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/SearchHandler.java Wed Oct 20 12:44:28 2010
@@ -17,32 +17,53 @@
 
 package org.apache.solr.handler.component;
 
-import org.apache.solr.handler.RequestHandlerBase;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.RTimer;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.Future;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrResponse;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
+import org.apache.solr.client.solrj.impl.LBHttpSolrServer;
+import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.ShardParams;
-import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.RTimer;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.common.util.StrUtils;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.RequestHandlerBase;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.client.solrj.SolrServer;
-import org.apache.solr.client.solrj.SolrRequest;
-import org.apache.solr.client.solrj.SolrResponse;
-import org.apache.solr.client.solrj.request.QueryRequest;
-import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
-
 import org.apache.solr.util.SolrPluginUtils;
 import org.apache.solr.util.plugin.SolrCoreAware;
-import org.apache.solr.core.SolrCore;
-import org.apache.lucene.queryParser.ParseException;
-import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
-import org.apache.commons.httpclient.HttpClient;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import java.util.*;
-import java.util.concurrent.*;
 
 /**
  *
@@ -199,7 +220,7 @@ public class SearchHandler extends Reque
       subt.stop();
     }
 
-    if (rb.shards == null) {
+    if (!rb.isDistrib) {
       // a normal non-distributed request
 
       // The semantics of debugging vs not debugging are different enough that
@@ -265,6 +286,7 @@ public class SearchHandler extends Reque
             for (String shard : sreq.actualShards) {
               ModifiableSolrParams params = new ModifiableSolrParams(sreq.params);
               params.remove(ShardParams.SHARDS);      // not a top-level request
+              params.remove("distrib");               // not a top-level request
               params.remove("indent");
               params.remove(CommonParams.HEADER_ECHO_PARAMS);
               params.set(ShardParams.IS_SHARD, true);  // a sub (shard) request
@@ -367,6 +389,8 @@ class HttpCommComponent {
 
 
   static HttpClient client;
+  static Random r = new Random();
+  static LBHttpSolrServer loadbalancer;
 
   static {
     MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
@@ -375,12 +399,29 @@ class HttpCommComponent {
     mgr.getParams().setConnectionTimeout(SearchHandler.connectionTimeout);
     mgr.getParams().setSoTimeout(SearchHandler.soTimeout);
     // mgr.getParams().setStaleCheckingEnabled(false);
-    client = new HttpClient(mgr);    
+
+    client = new HttpClient(mgr);
+
+    // prevent retries  (note: this didn't work when set on mgr.. needed to be set on client)
+    DefaultHttpMethodRetryHandler retryhandler = new DefaultHttpMethodRetryHandler(0, false);
+    client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryhandler);
+
+    try {
+      loadbalancer = new LBHttpSolrServer(client);
+    } catch (MalformedURLException e) {
+      // should be impossible since we're not passing any URLs here
+      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,e);
+    }
   }
 
   CompletionService<ShardResponse> completionService = new ExecutorCompletionService<ShardResponse>(commExecutor);
   Set<Future<ShardResponse>> pending = new HashSet<Future<ShardResponse>>();
 
+  // maps "localhost:8983|localhost:7574" to a shuffled List("http://localhost:8983","http://localhost:7574")
+  // This is primarily to keep track of what order we should use to query the replicas of a shard
+  // so that we use the same replica for all phases of a distributed request.
+  Map<String,List<String>> shardToURLs = new HashMap<String,List<String>>();
+
   HttpCommComponent() {
   }
 
@@ -404,7 +445,36 @@ class HttpCommComponent {
     }
   }
 
+
+  // Not thread safe... don't use in Callable.
+  // Don't modify the returned URL list.
+  private List<String> getURLs(String shard) {
+    List<String> urls = shardToURLs.get(shard);
+    if (urls==null) {
+      urls = StrUtils.splitSmart(shard,"|",true);
+
+      // convert shard to URL
+      for (int i=0; i<urls.size(); i++) {
+        urls.set(i, SearchHandler.scheme + urls.get(i));
+      }
+
+      //
+      // Shuffle the list instead of use round-robin by default.
+      // This prevents accidental synchronization where multiple shards could get in sync
+      // and query the same replica at the same time.
+      //
+      if (urls.size() > 1)
+        Collections.shuffle(urls, r);
+      shardToURLs.put(shard, urls);
+    }
+    return urls;
+  }
+
+
   void submit(final ShardRequest sreq, final String shard, final ModifiableSolrParams params) {
+    // do this outside of the callable for thread safety reasons
+    final List<String> urls = getURLs(shard);
+
     Callable<ShardResponse> task = new Callable<ShardResponse>() {
       public ShardResponse call() throws Exception {
 
@@ -416,13 +486,9 @@ class HttpCommComponent {
         long startTime = System.currentTimeMillis();
 
         try {
-          // String url = "http://" + shard + "/select";
-          String url = SearchHandler.scheme + shard;
-
           params.remove(CommonParams.WT); // use default (currently javabin)
           params.remove(CommonParams.VERSION);
 
-          SolrServer server = new CommonsHttpSolrServer(url, client);
           // SolrRequest req = new QueryRequest(SolrRequest.METHOD.POST, "/select");
           // use generic request to avoid extra processing of queries
           QueryRequest req = new QueryRequest(params);
@@ -430,10 +496,24 @@ class HttpCommComponent {
 
           // no need to set the response parser as binary is the default
           // req.setResponseParser(new BinaryResponseParser());
-          // srsp.rsp = server.request(req);
-          // srsp.rsp = server.query(sreq.params);
 
-          ssr.nl = server.request(req);
+          // if there are no shards available for a slice, urls.size()==0
+          if (urls.size()==0) {
+            // TODO: what's the right error code here? We should use the same thing when
+            // all of the servers for a shard are down.
+            throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, "no servers hosting shard: " + shard);
+          }
+
+          if (urls.size() <= 1) {
+            String url = urls.get(0);
+            srsp.setShardAddress(url);
+            SolrServer server = new CommonsHttpSolrServer(url, client);
+            ssr.nl = server.request(req);
+          } else {
+            LBHttpSolrServer.Rsp rsp = loadbalancer.request(new LBHttpSolrServer.Req(req, urls));
+            ssr.nl = rsp.getResponse();
+            srsp.setShardAddress(rsp.getServer());
+          }
         } catch (Throwable th) {
           srsp.setException(th);
           if (th instanceof SolrException) {

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ShardRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ShardRequest.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ShardRequest.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ShardRequest.java Wed Oct 20 12:44:28 2010
@@ -41,8 +41,6 @@ public class ShardRequest {
   public int purpose;  // the purpose of this request
 
   public String[] shards;  // the shards this request should be sent to, null for all
-// TODO: how to request a specific shard address?
-
 
   public ModifiableSolrParams params;
 

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ShardResponse.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ShardResponse.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ShardResponse.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/ShardResponse.java Wed Oct 20 12:44:28 2010
@@ -79,4 +79,9 @@ public final class ShardResponse {
   {
     this.rspCode = rspCode;
   }
+
+  /** What was the shard address that returned this response.  Example:  "http://localhost:8983/solr" */
+  public String getShardAddress() { return this.shardAddress; }
+
+  void setShardAddress(String addr) { this.shardAddress = addr; }
 }

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/StatsComponent.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/StatsValues.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/TermVectorComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/TermVectorComponent.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/TermVectorComponent.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/TermVectorComponent.java Wed Oct 20 12:44:28 2010
@@ -383,11 +383,11 @@ public class TermVectorComponent extends
   }
 
   public String getSourceId() {
-    return "$Id:$";
+    return "$Id$";
   }
 
   public String getSource() {
-    return "$Revision:$";
+    return "$URL$";
   }
 
   public String getDescription() {

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/TermVectorComponent.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/TermsComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/TermsComponent.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/TermsComponent.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/handler/component/TermsComponent.java Wed Oct 20 12:44:28 2010
@@ -61,6 +61,7 @@ public class TermsComponent extends Sear
     // TODO: temporary... this should go in a different component.
     String shards = params.get(ShardParams.SHARDS);
     if (shards != null) {
+      rb.isDistrib = true;
       if (params.get(ShardParams.SHARDS_QT) == null) {
         throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No shards.qt parameter specified");
       }
@@ -298,9 +299,6 @@ public class TermsComponent extends Sear
     // base shard request on original parameters
     sreq.params = new ModifiableSolrParams(params);
 
-    // don't pass through the shards param
-    sreq.params.remove(ShardParams.SHARDS);
-
     // remove any limits for shards, we want them to return all possible
     // responses
     // we want this so we can calculate the correct counts
@@ -310,11 +308,6 @@ public class TermsComponent extends Sear
     sreq.params.set(TermsParams.TERMS_LIMIT, -1);
     sreq.params.set(TermsParams.TERMS_SORT, TermsParams.TERMS_SORT_INDEX);
 
-    // TODO: is there a better way to handle this?
-    String qt = params.get(CommonParams.QT);
-    if (qt != null) {
-      sreq.params.add(CommonParams.QT, qt);
-    }
     return sreq;
   }
 

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/highlight/SingleFragListBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/BinaryQueryResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/BinaryResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/JSONResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/PHPResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/PHPSerializedResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/PythonResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/QueryResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/RawResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/RubyResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/ServletSolrParams.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/SimpleFacets.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/SolrQueryResponse.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/TextResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/XMLResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/request/XSLTResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/BaseResponseWriter.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Oct 20 12:44:28 2010
@@ -1 +1 @@
-Id
+Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/GenericBinaryResponseWriter.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Oct 20 12:44:28 2010
@@ -1 +1 @@
-Id
+Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/GenericTextResponseWriter.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Oct 20 12:44:28 2010
@@ -1 +1 @@
-Id
+Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/JSONResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/PageTool.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/PythonResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/RubyResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/SolrParamResourceLoader.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/SolrVelocityResourceLoader.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/TextResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/VelocityResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/response/XSLTResponseWriter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/AbstractSubTypeFieldType.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/BinaryField.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/ByteField.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/ByteField.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/ByteField.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/ByteField.java Wed Oct 20 12:44:28 2010
@@ -30,7 +30,7 @@ import java.io.IOException;
 import java.util.Map;
 
 /**
- * @version $Id:$
+ * @version $Id$
  */
 public class ByteField extends FieldType {
   protected void init(IndexSchema schema, Map<String, String> args) {

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/ByteField.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/CoordinateFieldType.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/GeoHashField.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/LatLonType.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/PointType.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/SchemaAware.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/ShortField.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/SimilarityFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/schema/SpatialQueryable.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/DocSetHitCollector.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/FieldQParserPlugin.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/FunctionQParserPlugin.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/MutableValueLong.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/RawQParserPlugin.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/SolrFilter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java Wed Oct 20 12:44:28 2010
@@ -37,6 +37,7 @@ import org.apache.lucene.util.OpenBitSet
 import java.io.IOException;
 import java.net.URL;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.solr.search.function.ValueSource;
 import org.slf4j.Logger;
@@ -51,6 +52,12 @@ import org.slf4j.LoggerFactory;
  * @since solr 0.9
  */
 public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
+
+  // These should *only* be used for debugging or monitoring purposes
+  public static final AtomicLong numOpens = new AtomicLong();
+  public static final AtomicLong numCloses = new AtomicLong();
+
+
   private static Logger log = LoggerFactory.getLogger(SolrIndexSearcher.class);
   private final SolrCore core;
   private final IndexSchema schema;
@@ -191,6 +198,9 @@ public class SolrIndexSearcher extends I
     optimizer = solrConfig.filtOptEnabled ? new LuceneQueryOptimizer(solrConfig.filtOptCacheSize,solrConfig.filtOptThreshold) : null;
 
     fieldNames = r.getFieldNames(IndexReader.FieldOption.ALL);
+
+    // do this at the end since an exception in the constructor means we won't close    
+    numOpens.incrementAndGet();
   }
 
 
@@ -239,6 +249,9 @@ public class SolrIndexSearcher extends I
     for (SolrCache cache : cacheList) {
       cache.close();
     }
+
+    // do this at the end so it only gets done if there are no exceptions
+    numCloses.incrementAndGet();
   }
 
   /** Direct access to the IndexReader used by this searcher */

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/SpatialFilterQParser.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/SpatialFilterQParserPlugin.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/SpatialOptions.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/TermQParserPlugin.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/ByteFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/ByteFieldSource.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/ByteFieldSource.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/ByteFieldSource.java Wed Oct 20 12:44:28 2010
@@ -32,7 +32,7 @@ import java.util.Map;
  * using <code>getInts()</code>
  * and makes those values available as other numeric types, casting as needed. *
  *
- * @version $Id: IntFieldSource.java 555343 2007-07-11 17:46:25Z hossman $
+ * @version $Id$
  */
 
 public class ByteFieldSource extends NumericFieldCacheSource<ByteValues> {

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/ByteFieldSource.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java Wed Oct 20 12:44:28 2010
@@ -34,7 +34,7 @@ import java.util.Map;
  * using <code>getFloats()</code>
  * and makes those values available as other numeric types, casting as needed.
  *
- * @version $Id:$
+ * @version $Id$
  */
 
 public class DoubleFieldSource extends NumericFieldCacheSource<DoubleValues> {

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/DoubleFieldSource.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/JoinDocFreqValueSource.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/LiteralValueSource.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/LongFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/LongFieldSource.java?rev=1025539&r1=1025538&r2=1025539&view=diff
==============================================================================
--- lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/LongFieldSource.java (original)
+++ lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/LongFieldSource.java Wed Oct 20 12:44:28 2010
@@ -32,7 +32,7 @@ import java.util.Map;
  * using <code>getFloats()</code>
  * and makes those values available as other numeric types, casting as needed.
  *
- * @version $Id: FloatFieldSource.java 555343 2007-07-11 17:46:25Z hossman $
+ * @version $Id$
  */
 
 public class LongFieldSource extends NumericFieldCacheSource<LongValues> {

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/LongFieldSource.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/MultiFloatFunction.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: lucene/dev/branches/docvalues/solr/src/java/org/apache/solr/search/function/MultiValueSource.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL