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 2012/08/13 15:53:27 UTC

svn commit: r1372423 [41/45] - in /lucene/dev/branches/LUCENE-2878: ./ dev-tools/ dev-tools/eclipse/ dev-tools/idea/.idea/libraries/ dev-tools/maven/ dev-tools/maven/lucene/ dev-tools/maven/lucene/analysis/common/ dev-tools/maven/lucene/analysis/icu/ d...

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java Mon Aug 13 13:52:46 2012
@@ -17,16 +17,18 @@ package org.apache.solr.cloud;
  * limitations under the License.
  */
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.http.client.HttpClient;
+import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrServer;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.RequestRecovery;
 import org.apache.solr.common.SolrException;
-import org.apache.solr.common.cloud.CloudState;
+import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.Slice;
 import org.apache.solr.common.cloud.ZkCoreNodeProps;
 import org.apache.solr.common.cloud.ZkNodeProps;
@@ -63,12 +65,14 @@ public class SyncStrategy {
     shardHandler = new HttpShardHandlerFactory().getShardHandler(client);
   }
   
-  private static class SyncShardRequest extends ShardRequest {
+  private static class ShardCoreRequest extends ShardRequest {
     String coreName;
+    public String baseUrl;
   }
   
   public boolean sync(ZkController zkController, SolrCore core,
       ZkNodeProps leaderProps) {
+    log.info("Sync replicas to " + ZkCoreNodeProps.getCoreUrl(leaderProps));
     // TODO: look at our state usage of sync
     // zkController.publish(core, ZkStateReader.SYNC);
     
@@ -104,23 +108,19 @@ public class SyncStrategy {
       if (!success
           && !areAnyOtherReplicasActive(zkController, leaderProps, collection,
               shardId)) {
-//        System.out
-//            .println("wasnt a success but no on else i active! I am the leader");
-        
+        log.info("Sync was not a success but no on else i active! I am the leader");
         success = true;
       }
       
       if (success) {
-        // solrcloud_debug
-        // System.out.println("Sync success");
-        // we are the leader - tell all of our replias to sync with us
+        log.info("Sync Success - now sync replicas to me");
         
         syncToMe(zkController, collection, shardId, leaderProps);
         
       } else {
+        SolrException.log(log, "Sync Failed");
         
-        // solrcloud_debug
-        // System.out.println("Sync failure");
+        // lets see who seems ahead...
       }
       
     } catch (Exception e) {
@@ -132,8 +132,8 @@ public class SyncStrategy {
   
   private boolean areAnyOtherReplicasActive(ZkController zkController,
       ZkNodeProps leaderProps, String collection, String shardId) {
-    CloudState cloudState = zkController.getZkStateReader().getCloudState();
-    Map<String,Slice> slices = cloudState.getSlices(collection);
+    ClusterState clusterState = zkController.getZkStateReader().getClusterState();
+    Map<String,Slice> slices = clusterState.getSlices(collection);
     Slice slice = slices.get(shardId);
     Map<String,ZkNodeProps> shards = slice.getShards();
     for (Map.Entry<String,ZkNodeProps> shard : shards.entrySet()) {
@@ -142,10 +142,10 @@ public class SyncStrategy {
 //          + state
 //          + shard.getValue().get(ZkStateReader.NODE_NAME_PROP)
 //          + " live: "
-//          + cloudState.liveNodesContain(shard.getValue().get(
+//          + clusterState.liveNodesContain(shard.getValue().get(
 //              ZkStateReader.NODE_NAME_PROP)));
       if ((state.equals(ZkStateReader.ACTIVE))
-          && cloudState.liveNodesContain(shard.getValue().get(
+          && clusterState.liveNodesContain(shard.getValue().get(
               ZkStateReader.NODE_NAME_PROP))
           && !new ZkCoreNodeProps(shard.getValue()).getCoreUrl().equals(
               new ZkCoreNodeProps(leaderProps).getCoreUrl())) {
@@ -162,11 +162,7 @@ public class SyncStrategy {
         .getReplicaProps(collection, shardId,
             props.get(ZkStateReader.NODE_NAME_PROP),
             props.get(ZkStateReader.CORE_NAME_PROP), ZkStateReader.ACTIVE); // TODO:
-    // should
-    // there
-    // be a
-    // state
-    // filter?
+    // TODO should there be a state filter?
     
     if (nodes == null) {
       // I have no replicas
@@ -197,19 +193,17 @@ public class SyncStrategy {
             leaderProps.get(ZkStateReader.NODE_NAME_PROP),
             leaderProps.get(ZkStateReader.CORE_NAME_PROP), ZkStateReader.ACTIVE);
     if (nodes == null) {
-      // System.out.println("I have no replicas");
-      // I have no replicas
+      log.info(ZkCoreNodeProps.getCoreUrl(leaderProps) + " has no replicas");
       return;
     }
-    //System.out.println("tell my replicas to sync");
+
     ZkCoreNodeProps zkLeader = new ZkCoreNodeProps(leaderProps);
     for (ZkCoreNodeProps node : nodes) {
       try {
-//         System.out
-//             .println("try and ask " + node.getCoreUrl() + " to sync");
-        log.info("try and ask " + node.getCoreUrl() + " to sync");
-        requestSync(zkLeader.getCoreUrl(), node.getCoreName());
-
+        log.info(ZkCoreNodeProps.getCoreUrl(leaderProps) + ": try and ask " + node.getCoreUrl() + " to sync");
+        
+        requestSync(node.getBaseUrl(), node.getCoreUrl(), zkLeader.getCoreUrl(), node.getCoreName());
+        
       } catch (Exception e) {
         SolrException.log(log, "Error syncing replica to leader", e);
       }
@@ -220,24 +214,25 @@ public class SyncStrategy {
       ShardResponse srsp = shardHandler.takeCompletedOrError();
       if (srsp == null) break;
       boolean success = handleResponse(srsp);
-      //System.out.println("got response:" + success);
+      if (srsp.getException() != null) {
+        SolrException.log(log, "Sync request error: " + srsp.getException());
+      }
+      
       if (!success) {
          try {
-           log.info("Sync failed - asking replica to recover.");
-           //System.out.println("Sync failed - asking replica to recover.");
-           RequestRecovery recoverRequestCmd = new RequestRecovery();
-           recoverRequestCmd.setAction(CoreAdminAction.REQUESTRECOVERY);
-           recoverRequestCmd.setCoreName(((SyncShardRequest)srsp.getShardRequest()).coreName);
+           log.info(ZkCoreNodeProps.getCoreUrl(leaderProps) + ": Sync failed - asking replica (" + srsp.getShardAddress() + ") to recover.");
            
-           HttpSolrServer server = new HttpSolrServer(zkLeader.getBaseUrl());
-           server.request(recoverRequestCmd);
+           requestRecovery(((ShardCoreRequest)srsp.getShardRequest()).baseUrl, ((ShardCoreRequest)srsp.getShardRequest()).coreName);
+
          } catch (Exception e) {
-           log.info("Could not tell a replica to recover", e);
+           SolrException.log(log, ZkCoreNodeProps.getCoreUrl(leaderProps) + ": Could not tell a replica to recover", e);
          }
-         shardHandler.cancelAll();
-        break;
+      } else {
+        log.info(ZkCoreNodeProps.getCoreUrl(leaderProps) + ": " + " sync completed with " + srsp.getShardAddress());
       }
     }
+    
+
   }
   
   private boolean handleResponse(ShardResponse srsp) {
@@ -246,14 +241,19 @@ public class SyncStrategy {
     if (response == null) {
       return false;
     }
-    boolean success = (Boolean) response.get("sync");
+    Boolean success = (Boolean) response.get("sync");
+    
+    if (success == null) {
+      success = false;
+    }
     
     return success;
   }
 
-  private void requestSync(String replica, String coreName) {
-    SyncShardRequest sreq = new SyncShardRequest();
+  private void requestSync(String baseUrl, String replica, String leaderUrl, String coreName) {
+    ShardCoreRequest sreq = new ShardCoreRequest();
     sreq.coreName = coreName;
+    sreq.baseUrl = baseUrl;
     sreq.purpose = 1;
     // TODO: this sucks
     if (replica.startsWith("http://"))
@@ -264,11 +264,23 @@ public class SyncStrategy {
     sreq.params.set("qt","/get");
     sreq.params.set("distrib",false);
     sreq.params.set("getVersions",Integer.toString(100));
-    sreq.params.set("sync",replica);
+    sreq.params.set("sync",leaderUrl);
     
     shardHandler.submit(sreq, replica, sreq.params);
   }
   
+  private void requestRecovery(String baseUrl, String coreName) throws SolrServerException, IOException {
+    // TODO: do this in background threads
+    RequestRecovery recoverRequestCmd = new RequestRecovery();
+    recoverRequestCmd.setAction(CoreAdminAction.REQUESTRECOVERY);
+    recoverRequestCmd.setCoreName(coreName);
+    
+    HttpSolrServer server = new HttpSolrServer(baseUrl);
+    server.setConnectionTimeout(45000);
+    server.setSoTimeout(45000);
+    server.request(recoverRequestCmd);
+  }
+  
   public static ModifiableSolrParams params(String... params) {
     ModifiableSolrParams msp = new ModifiableSolrParams();
     for (int i = 0; i < params.length; i += 2) {

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkCLI.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkCLI.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkCLI.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkCLI.java Mon Aug 13 13:52:46 2012
@@ -163,7 +163,7 @@ public class ZkCLI {
       }
       SolrZkClient zkClient = null;
       try {
-        zkClient = new SolrZkClient(zkServerAddress, 15000, 5000,
+        zkClient = new SolrZkClient(zkServerAddress, 30000, 30000,
             new OnReconnect() {
               @Override
               public void command() {}

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkController.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkController.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkController.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkController.java Mon Aug 13 13:52:46 2012
@@ -38,7 +38,7 @@ import org.apache.solr.client.solrj.impl
 import org.apache.solr.client.solrj.request.CoreAdminRequest.WaitForState;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.cloud.CloudState;
+import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.OnReconnect;
 import org.apache.solr.common.cloud.SolrZkClient;
 import org.apache.solr.common.cloud.ZkCmdExecutor;
@@ -121,6 +121,8 @@ public final class ZkController {
   // may accept defaults or use mocks rather than pulling things from a CoreContainer
   private CoreContainer cc;
 
+  protected volatile Overseer overseer;
+
   /**
    * @param cc if null, recovery will not be enabled
    * @param zkServerAddress
@@ -170,36 +172,20 @@ public final class ZkController {
                 shardHandler = cc.getShardHandlerFactory().getShardHandler();
                 adminPath = cc.getAdminPath();
               }
-              
-              ElectionContext context = new OverseerElectionContext(
-                  shardHandler, adminPath,
-                  getNodeName(), zkStateReader);
+              ZkController.this.overseer = new Overseer(shardHandler, adminPath, zkStateReader);
+              ElectionContext context = new OverseerElectionContext(zkClient, overseer, getNodeName());
               overseerElector.joinElection(context);
               zkStateReader.createClusterStateWatchersAndUpdate();
               
-              List<CoreDescriptor> descriptors = registerOnReconnect
-                  .getCurrentDescriptors();
-              if (descriptors != null) {
-                // before registering as live, make sure everyone is in a
-                // down state
-                for (CoreDescriptor descriptor : descriptors) {
-                  final String coreZkNodeName = getNodeName() + "_"
-                      + descriptor.getName();
-                  try {
-                    publish(descriptor, ZkStateReader.DOWN);
-                    waitForLeaderToSeeDownState(descriptor, coreZkNodeName);
-                  } catch (Exception e) {
-                    SolrException.log(log, "", e);
-                  }
-                }
-              }
+              registerAllCoresAsDown(registerOnReconnect);
               
 
               // we have to register as live first to pick up docs in the buffer
               createEphemeralLiveNode();
               
+              List<CoreDescriptor> descriptors = registerOnReconnect.getCurrentDescriptors();
               // re register all descriptors
-              if (descriptors != null) {
+              if (descriptors  != null) {
                 for (CoreDescriptor descriptor : descriptors) {
                   // TODO: we need to think carefully about what happens when it was
                   // a leader that was expired - as well as what to do about leaders/overseers
@@ -228,7 +214,28 @@ public final class ZkController {
     cmdExecutor = new ZkCmdExecutor();
     leaderElector = new LeaderElector(zkClient);
     zkStateReader = new ZkStateReader(zkClient);
-    init();
+    
+    init(registerOnReconnect);
+  }
+
+  private void registerAllCoresAsDown(
+      final CurrentCoreDescriptorProvider registerOnReconnect) {
+    List<CoreDescriptor> descriptors = registerOnReconnect
+        .getCurrentDescriptors();
+    if (descriptors != null) {
+      // before registering as live, make sure everyone is in a
+      // down state
+      for (CoreDescriptor descriptor : descriptors) {
+        final String coreZkNodeName = getNodeName() + "_"
+            + descriptor.getName();
+        try {
+          publish(descriptor, ZkStateReader.DOWN);
+          waitForLeaderToSeeDownState(descriptor, coreZkNodeName);
+        } catch (Exception e) {
+          SolrException.log(log, "", e);
+        }
+      }
+    }
   }
 
   /**
@@ -236,6 +243,11 @@ public final class ZkController {
    */
   public void close() {
     try {
+      overseer.close();
+    } catch(Throwable t) {
+      log.error("Error closing overseer", t);
+    }
+    try {
       zkClient.close();
     } catch (InterruptedException e) {
       // Restore the interrupted status
@@ -262,8 +274,8 @@ public final class ZkController {
   /**
    * @return information about the cluster from ZooKeeper
    */
-  public CloudState getCloudState() {
-    return zkStateReader.getCloudState();
+  public ClusterState getClusterState() {
+    return zkStateReader.getClusterState();
   }
 
   /**
@@ -338,8 +350,9 @@ public final class ZkController {
     return zkServerAddress;
   }
 
-  private void init() {
-
+  private void init(CurrentCoreDescriptorProvider registerOnReconnect) {
+    registerAllCoresAsDown(registerOnReconnect);
+    
     try {
       // makes nodes zkNode
       cmdExecutor.ensureExists(ZkStateReader.LIVE_NODES_ZKNODE, zkClient);
@@ -358,8 +371,8 @@ public final class ZkController {
       }
       
       overseerElector = new LeaderElector(zkClient);
-      ElectionContext context = new OverseerElectionContext(shardHandler,
-          adminPath, getNodeName(), zkStateReader);
+      this.overseer = new Overseer(shardHandler, adminPath, zkStateReader);
+      ElectionContext context = new OverseerElectionContext(zkClient, overseer, getNodeName());
       overseerElector.setup(context);
       overseerElector.joinElection(context);
       zkStateReader.createClusterStateWatchersAndUpdate();
@@ -532,18 +545,18 @@ public final class ZkController {
     String leaderUrl = getLeaderProps(collection, cloudDesc.getShardId()).getCoreUrl();
     
     // now wait until our currently cloud state contains the latest leader
-    String cloudStateLeader = zkStateReader.getLeaderUrl(collection, cloudDesc.getShardId(), 30000);
+    String clusterStateLeader = zkStateReader.getLeaderUrl(collection, shardId, 30000);
     int tries = 0;
-    while (!leaderUrl.equals(cloudStateLeader)) {
+    while (!leaderUrl.equals(clusterStateLeader)) {
       if (tries == 60) {
         throw new SolrException(ErrorCode.SERVER_ERROR,
             "There is conflicting information about the leader of shard: "
-                + cloudDesc.getShardId());
+                + cloudDesc.getShardId() + " our state says:" + clusterStateLeader + " but zookeeper says:" + leaderUrl);
       }
       Thread.sleep(1000);
       tries++;
-      cloudStateLeader = zkStateReader.getLeaderUrl(collection,
-          cloudDesc.getShardId(), 30000);
+      clusterStateLeader = zkStateReader.getLeaderUrl(collection, shardId, 30000);
+      leaderUrl = getLeaderProps(collection, cloudDesc.getShardId()).getCoreUrl();
     }
     
     String ourUrl = ZkCoreNodeProps.getCoreUrl(baseUrl, coreName);
@@ -595,7 +608,7 @@ public final class ZkController {
     }
     
     // make sure we have an update cluster state right away
-    zkStateReader.updateCloudState(true);
+    zkStateReader.updateClusterState(true);
 
     return shardId;
   }
@@ -609,10 +622,10 @@ public final class ZkController {
    * @throws KeeperException
    * @throws InterruptedException
    */
-  private ZkCoreNodeProps getLeaderProps(final String collection, final String slice)
-      throws KeeperException, InterruptedException {
+  private ZkCoreNodeProps getLeaderProps(final String collection,
+      final String slice) throws KeeperException, InterruptedException {
     int iterCount = 60;
-    while (iterCount-- > 0)
+    while (iterCount-- > 0) {
       try {
         byte[] data = zkClient.getData(
             ZkStateReader.getShardLeadersPath(collection, slice), null, null,
@@ -623,6 +636,7 @@ public final class ZkController {
       } catch (NoNodeException e) {
         Thread.sleep(500);
       }
+    }
     throw new RuntimeException("Could not get leader props");
   }
 
@@ -727,7 +741,7 @@ public final class ZkController {
   }
 
   private boolean needsToBeAssignedShardId(final CoreDescriptor desc,
-      final CloudState state, final String shardZkNodeName) {
+      final ClusterState state, final String shardZkNodeName) {
 
     final CloudDescriptor cloudDesc = desc.getCloudDescriptor();
     
@@ -927,7 +941,7 @@ public final class ZkController {
     final String shardZkNodeName = getNodeName() + "_" + coreName;
     int retryCount = 120;
     while (retryCount-- > 0) {
-      final String shardId = zkStateReader.getCloudState().getShardId(
+      final String shardId = zkStateReader.getClusterState().getShardId(
           shardZkNodeName);
       if (shardId != null) {
         return shardId;
@@ -995,7 +1009,7 @@ public final class ZkController {
     // this also gets us our assigned shard id if it was not specified
     publish(cd, ZkStateReader.DOWN); 
     String shardZkNodeName = getCoreNodeName(cd);
-    if (cd.getCloudDescriptor().getShardId() == null && needsToBeAssignedShardId(cd, zkStateReader.getCloudState(), shardZkNodeName)) {
+    if (cd.getCloudDescriptor().getShardId() == null && needsToBeAssignedShardId(cd, zkStateReader.getClusterState(), shardZkNodeName)) {
       String shardId;
       shardId = doGetShardIdProcess(cd.getName(), cd.getCloudDescriptor());
       cd.getCloudDescriptor().setShardId(shardId);
@@ -1126,13 +1140,12 @@ public final class ZkController {
    */
   public static void bootstrapConf(SolrZkClient zkClient, Config cfg, String solrHome) throws IOException,
       KeeperException, InterruptedException {
-    
+    log.info("bootstraping config into ZooKeeper using solr.xml");
     NodeList nodes = (NodeList)cfg.evaluate("solr/cores/core", XPathConstants.NODESET);
 
     for (int i=0; i<nodes.getLength(); i++) {
       Node node = nodes.item(i);
       String rawName = DOMUtil.substituteProperty(DOMUtil.getAttr(node, "name", null), new Properties());
-
       String instanceDir = DOMUtil.getAttr(node, "instanceDir", null);
       File idir = new File(instanceDir);
       if (!idir.isAbsolute()) {
@@ -1143,7 +1156,7 @@ public final class ZkController {
         confName = rawName;
       }
       File udir = new File(idir, "conf");
-      SolrException.log(log, "Uploading directory " + udir + " with name " + confName + " for SolrCore " + rawName);
+      log.info("Uploading directory " + udir + " with name " + confName + " for SolrCore " + rawName);
       ZkController.uploadConfigDir(zkClient, udir, confName);
     }
   }

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java Mon Aug 13 13:52:46 2012
@@ -18,6 +18,7 @@ package org.apache.solr.cloud;
  */
 
 import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 import java.util.Properties;
@@ -69,7 +70,7 @@ public class ZkSolrResourceLoader extend
    * @return the stream for the named resource
    */
   @Override
-  public InputStream openResource(String resource) {
+  public InputStream openResource(String resource) throws IOException {
     InputStream is = null;
     String file = collectionZkPath + "/" + resource;
     try {
@@ -78,16 +79,16 @@ public class ZkSolrResourceLoader extend
         return new ByteArrayInputStream(bytes);
       }
     } catch (Exception e) {
-      throw new RuntimeException("Error opening " + file, e);
+      throw new IOException("Error opening " + file, e);
     }
     try {
       // delegate to the class loader (looking into $INSTANCE_DIR/lib jars)
       is = classLoader.getResourceAsStream(resource);
     } catch (Exception e) {
-      throw new RuntimeException("Error opening " + resource, e);
+      throw new IOException("Error opening " + resource, e);
     }
     if (is == null) {
-      throw new RuntimeException("Can't find resource '" + resource
+      throw new IOException("Can't find resource '" + resource
           + "' in classpath or '" + collectionZkPath + "', cwd="
           + System.getProperty("user.dir"));
     }

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/CoreContainer.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/CoreContainer.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/CoreContainer.java Mon Aug 13 13:52:46 2012
@@ -109,6 +109,10 @@ public class CoreContainer 
 
 
   protected final Map<String, SolrCore> cores = new LinkedHashMap<String, SolrCore>();
+
+  protected final Map<String,Exception> coreInitFailures = 
+    Collections.synchronizedMap(new LinkedHashMap<String,Exception>());
+  
   protected boolean persistent = false;
   protected String adminPath = null;
   protected String managementPath = null;
@@ -676,6 +680,7 @@ public class CoreContainer 
         throw new IllegalStateException("This CoreContainer has been shutdown");
       }
       old = cores.put(name, core);
+      coreInitFailures.remove(name);
       /*
       * set both the name of the descriptor and the name of the
       * core, since the descriptors name is used for persisting.
@@ -750,105 +755,136 @@ public class CoreContainer 
    * @throws org.xml.sax.SAXException
    */
   public SolrCore create(CoreDescriptor dcore)  throws ParserConfigurationException, IOException, SAXException {
-    // Make the instanceDir relative to the cores instanceDir if not absolute
-    File idir = new File(dcore.getInstanceDir());
-    if (!idir.isAbsolute()) {
-      idir = new File(solrHome, dcore.getInstanceDir());
-    }
-    String instanceDir = idir.getPath();
-    log.info("Creating SolrCore '{}' using instanceDir: {}", 
-             dcore.getName(), instanceDir);
-    // Initialize the solr config
-    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());
 
-        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) {
-      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.ROOT).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);
-          }
-        }
+    // :TODO: would be really nice if this method wrapped any underlying errors and only threw SolrException
+
+    final String name = dcore.getName();
+    Exception failure = null;
+
+    try {
+      // Make the instanceDir relative to the cores instanceDir if not absolute
+      File idir = new File(dcore.getInstanceDir());
+      if (!idir.isAbsolute()) {
+        idir = new File(solrHome, dcore.getInstanceDir());
+      }
+      String instanceDir = idir.getPath();
+      log.info("Creating SolrCore '{}' using instanceDir: {}", 
+               dcore.getName(), instanceDir);
+      // Initialize the solr config
+      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 {
-        // 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){
-      if(zkController != null) {
         try {
-          schema = getSchemaFromZk(zkConfigName, dcore.getSchemaName(), config, solrLoader);
+          String collection = dcore.getCloudDescriptor().getCollectionName();
+          zkController.createCollectionZkNode(dcore.getCloudDescriptor());
+          
+          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);
+                                       "", e);
         } catch (InterruptedException e) {
           // Restore the interrupted status
           Thread.currentThread().interrupt();
           log.error("", e);
           throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
-              "", e);
+                                       "", e);
+        }
+      }
+    
+      IndexSchema schema = null;
+      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.ROOT).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){
+        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);
         }
-      } else {
-        schema = new IndexSchema(config, dcore.getSchemaName(), null);
       }
-    }
 
-    SolrCore core = new SolrCore(dcore.getName(), null, config, schema, dcore);
+      SolrCore core = new SolrCore(dcore.getName(), null, config, schema, dcore);
 
-    if (zkController == null && core.getUpdateHandler().getUpdateLog() != null) {
-      // always kick off recovery if we are in standalone mode.
-      core.getUpdateHandler().getUpdateLog().recoverFromLog();
-    }
+      if (zkController == null && core.getUpdateHandler().getUpdateLog() != null) {
+        // always kick off recovery if we are in standalone mode.
+        core.getUpdateHandler().getUpdateLog().recoverFromLog();
+      }
+
+      return core;
 
-    return core;
+      // :TODO: Java7...
+      // http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
+    } catch (ParserConfigurationException e1) {
+      failure = e1;
+      throw e1;
+    } catch (IOException e2) {
+      failure = e2;
+      throw e2;
+    } catch (SAXException e3) {
+      failure = e3;
+      throw e3;
+    } catch (RuntimeException e4) {
+      failure = e4;
+      throw e4;
+    } finally {
+      synchronized (coreInitFailures) {
+        // remove first so insertion order is updated and newest is last
+        coreInitFailures.remove(name);
+        if (null != failure) {
+          coreInitFailures.put(name, failure);
+        }
+      }
+    }
   }
-    
+
   /**
    * @return a Collection of registered SolrCores
    */
@@ -886,6 +922,32 @@ public class CoreContainer 
     return lst;
   }
 
+  /**
+   * Returns an immutable Map of Exceptions that occured when initializing 
+   * SolrCores (either at startup, or do to runtime requests to create cores) 
+   * keyed off of the name (String) of the SolrCore that had the Exception 
+   * during initialization.
+   * <p>
+   * While the Map returned by this method is immutable and will not change 
+   * once returned to the client, the source data used to generate this Map 
+   * can be changed as various SolrCore operations are performed:
+   * </p>
+   * <ul>
+   *  <li>Failed attempts to create new SolrCores will add new Exceptions.</li>
+   *  <li>Failed attempts to re-create a SolrCore using a name already contained in this Map will replace the Exception.</li>
+   *  <li>Failed attempts to reload a SolrCore will cause an Exception to be added to this list -- even though the existing SolrCore with that name will continue to be available.</li>
+   *  <li>Successful attempts to re-created a SolrCore using a name already contained in this Map will remove the Exception.</li>
+   *  <li>Registering an existing SolrCore with a name already contained in this Map (ie: ALIAS or SWAP) will remove the Exception.</li>
+   * </ul>
+   */
+  public Map<String,Exception> getCoreInitFailures() {
+    synchronized ( coreInitFailures ) {
+      return Collections.unmodifiableMap(new LinkedHashMap<String,Exception>
+                                         (coreInitFailures));
+    }
+  }
+
+
   // ---------------- Core name related methods --------------- 
   /**
    * Recreates a SolrCore.
@@ -897,61 +959,90 @@ public class CoreContainer 
    * @throws IOException
    * @throws SAXException
    */
-
   public void reload(String name) throws ParserConfigurationException, IOException, SAXException {
-    name= checkDefault(name);
-    SolrCore core;
-    synchronized(cores) {
-      core = cores.get(name);
-    }
-    if (core == null)
-      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "No such core: " + name );
 
-    CoreDescriptor cd = core.getCoreDescriptor();
+    // :TODO: would be really nice if this method wrapped any underlying errors and only threw SolrException
+
+    Exception failure = null;
+    try {
+
+      name= checkDefault(name);
+      SolrCore core;
+      synchronized(cores) {
+        core = cores.get(name);
+      }
+      if (core == null)
+        throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "No such core: " + name );
+
+      CoreDescriptor cd = core.getCoreDescriptor();
   
-    File instanceDir = new File(cd.getInstanceDir());
-    if (!instanceDir.isAbsolute()) {
-      instanceDir = new File(getSolrHome(), cd.getInstanceDir());
-    }
+      File instanceDir = new File(cd.getInstanceDir());
+      if (!instanceDir.isAbsolute()) {
+        instanceDir = new File(getSolrHome(), cd.getInstanceDir());
+      }
 
-    log.info("Reloading SolrCore '{}' using instanceDir: {}", 
-             cd.getName(), instanceDir.getAbsolutePath());
+      log.info("Reloading SolrCore '{}' using instanceDir: {}", 
+               cd.getName(), instanceDir.getAbsolutePath());
     
-    SolrResourceLoader solrLoader;
-    if(zkController == null) {
-      solrLoader = new SolrResourceLoader(instanceDir.getAbsolutePath(), libLoader, getCoreProps(instanceDir.getAbsolutePath(), cd.getPropertiesName(),cd.getCoreProperties()));
-    } else {
-      try {
-        String collection = cd.getCloudDescriptor().getCollectionName();
-        zkController.createCollectionZkNode(cd.getCloudDescriptor());
+      SolrResourceLoader solrLoader;
+      if(zkController == null) {
+        solrLoader = new SolrResourceLoader(instanceDir.getAbsolutePath(), libLoader, getCoreProps(instanceDir.getAbsolutePath(), cd.getPropertiesName(),cd.getCoreProperties()));
+      } else {
+        try {
+          String collection = cd.getCloudDescriptor().getCollectionName();
+          zkController.createCollectionZkNode(cd.getCloudDescriptor());
 
-        String zkConfigName = zkController.readConfigName(collection);
-        if (zkConfigName == null) {
-          log.error("Could not find config name for collection:" + collection);
+          String 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.getAbsolutePath(), zkConfigName, libLoader, getCoreProps(instanceDir.getAbsolutePath(), cd.getPropertiesName(),cd.getCoreProperties()), zkController);
+        } catch (KeeperException e) {
+          log.error("", e);
           throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
-              "Could not find config name for collection:" + collection);
+                                       "", e);
+        } catch (InterruptedException e) {
+          // Restore the interrupted status
+          Thread.currentThread().interrupt();
+          log.error("", e);
+          throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
+                                       "", e);
         }
-        solrLoader = new ZkSolrResourceLoader(instanceDir.getAbsolutePath(), zkConfigName, libLoader, getCoreProps(instanceDir.getAbsolutePath(), cd.getPropertiesName(),cd.getCoreProperties()), zkController);
-      } 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);
       }
-    }
     
-    SolrCore newCore = core.reload(solrLoader);
-    // keep core to orig name link
-    String origName = coreToOrigName.remove(core);
-    if (origName != null) {
-      coreToOrigName.put(newCore, origName);
+      SolrCore newCore = core.reload(solrLoader, core);
+      // keep core to orig name link
+      String origName = coreToOrigName.remove(core);
+      if (origName != null) {
+        coreToOrigName.put(newCore, origName);
+      }
+      register(name, newCore, false);
+
+      // :TODO: Java7...
+      // http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
+    } catch (ParserConfigurationException e1) {
+      failure = e1;
+      throw e1;
+    } catch (IOException e2) {
+      failure = e2;
+      throw e2;
+    } catch (SAXException e3) {
+      failure = e3;
+      throw e3;
+    } catch (RuntimeException e4) {
+      failure = e4;
+      throw e4;
+    } finally {
+      synchronized (coreInitFailures) {
+        // remove first so insertion order is updated and newest is last
+        coreInitFailures.remove(name);
+        if (null != failure) {
+          coreInitFailures.put(name, failure);
+        }
+      }
     }
-    register(name, newCore, false);
   }
 
   private String checkDefault(String name) {

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java Mon Aug 13 13:52:46 2012
@@ -34,7 +34,7 @@ public abstract class DirectoryFactory i
   /**
    * Indicates a Directory will no longer be used, and when it's ref count
    * hits 0, it can be closed. On shutdown all directories will be closed
-   * with this has been called or not. This is simply to allow early cleanup.
+   * whether this has been called or not. This is simply to allow early cleanup.
    * 
    * @param directory
    * @throws IOException 

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrConfig.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrConfig.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrConfig.java Mon Aug 13 13:52:46 2012
@@ -436,9 +436,7 @@ public class SolrConfig extends Config {
    */
   public List<PluginInfo> getPluginInfos(String  type){
     List<PluginInfo> result = pluginStore.get(type);
-    return result == null ?
-            (List<PluginInfo>) Collections.EMPTY_LIST:
-            result; 
+    return result == null ? Collections.<PluginInfo>emptyList(): result; 
   }
   public PluginInfo getPluginInfo(String  type){
     List<PluginInfo> result = pluginStore.get(type);
@@ -446,29 +444,31 @@ public class SolrConfig extends Config {
   }
   
   private void initLibs() {
-    
     NodeList nodes = (NodeList) evaluate("lib", XPathConstants.NODESET);
-    if (nodes==null || nodes.getLength()==0)
-      return;
+    if (nodes == null || nodes.getLength() == 0) return;
     
     log.info("Adding specified lib dirs to ClassLoader");
     
-     for (int i=0; i<nodes.getLength(); i++) {
-       Node node = nodes.item(i);
-
-       String baseDir = DOMUtil.getAttr(node, "dir");
-       String path = DOMUtil.getAttr(node, "path");
-       if (null != baseDir) {
-         // :TODO: add support for a simpler 'glob' mutually eclusive of regex
-         String regex = DOMUtil.getAttr(node, "regex");
-         FileFilter filter = (null == regex) ? null : new RegexFileFilter(regex);
-         getResourceLoader().addToClassLoader(baseDir, filter);
-       } else if (null != path) {
-         getResourceLoader().addToClassLoader(path);
-       } else {
-         throw new RuntimeException
-           ("lib: missing mandatory attributes: 'dir' or 'path'");
-       }
-     }
+    try {
+      for (int i = 0; i < nodes.getLength(); i++) {
+        Node node = nodes.item(i);
+        
+        String baseDir = DOMUtil.getAttr(node, "dir");
+        String path = DOMUtil.getAttr(node, "path");
+        if (null != baseDir) {
+          // :TODO: add support for a simpler 'glob' mutually eclusive of regex
+          String regex = DOMUtil.getAttr(node, "regex");
+          FileFilter filter = (null == regex) ? null : new RegexFileFilter(regex);
+          getResourceLoader().addToClassLoader(baseDir, filter);
+        } else if (null != path) {
+          getResourceLoader().addToClassLoader(path);
+        } else {
+          throw new RuntimeException(
+              "lib: missing mandatory attributes: 'dir' or 'path'");
+        }
+      }
+    } finally {
+      getResourceLoader().reloadLuceneSPI();
+    }
   }
 }

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrCore.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrCore.java Mon Aug 13 13:52:46 2012
@@ -70,6 +70,7 @@ import org.apache.solr.update.processor.
 import org.apache.solr.update.processor.RunUpdateProcessorFactory;
 import org.apache.solr.update.processor.UpdateRequestProcessorChain;
 import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
+import org.apache.solr.util.DefaultSolrThreadFactory;
 import org.apache.solr.util.RefCounted;
 import org.apache.solr.util.plugin.NamedListInitializedPlugin;
 import org.apache.solr.util.plugin.PluginInfoInitialized;
@@ -357,7 +358,7 @@ public final class SolrCore implements S
     return responseWriters.put(name, responseWriter);
   }
   
-  public SolrCore reload(SolrResourceLoader resourceLoader) throws IOException,
+  public SolrCore reload(SolrResourceLoader resourceLoader, SolrCore prev) throws IOException,
       ParserConfigurationException, SAXException {
     // TODO - what if indexwriter settings have changed
     
@@ -368,8 +369,8 @@ public final class SolrCore implements S
         getSchema().getResourceName(), null);
     
     updateHandler.incref();
-    SolrCore core = new SolrCore(getName(), null, config,
-        schema, coreDescriptor, updateHandler);
+    SolrCore core = new SolrCore(getName(), getDataDir(), config,
+        schema, coreDescriptor, updateHandler, prev);
     return core;
   }
 
@@ -548,7 +549,7 @@ public final class SolrCore implements S
    * @since solr 1.3
    */
   public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema, CoreDescriptor cd) {
-    this(name, dataDir, config, schema, cd, null);
+    this(name, dataDir, config, schema, cd, null, null);
   }
   
   /**
@@ -561,7 +562,7 @@ public final class SolrCore implements S
    *
    *@since solr 1.3
    */
-  public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema, CoreDescriptor cd, UpdateHandler updateHandler) {
+  public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema, CoreDescriptor cd, UpdateHandler updateHandler, SolrCore prev) {
     coreDescriptor = cd;
     this.setName( name );
     resourceLoader = config.getResourceLoader();
@@ -640,10 +641,31 @@ public final class SolrCore implements S
         }
       });
 
+      // use the (old) writer to open the first searcher
+      RefCounted<IndexWriter> iwRef = null;
+      if (prev != null) {
+        iwRef = prev.getUpdateHandler().getSolrCoreState().getIndexWriter(null);
+        if (iwRef != null) {
+          final IndexWriter iw = iwRef.get();
+          newReaderCreator = new Callable<DirectoryReader>() {
+            @Override
+            public DirectoryReader call() throws Exception {
+              return DirectoryReader.open(iw, true);
+            }
+          };
+        }
+      }
+
       // Open the searcher *before* the update handler so we don't end up opening
       // one in the middle.
       // With lockless commits in Lucene now, this probably shouldn't be an issue anymore
-      getSearcher(false,false,null);
+
+      try {
+        getSearcher(false,false,null,true);
+      } finally {
+        newReaderCreator = null;
+        if (iwRef != null) iwRef.decref();
+      }
 
       String updateHandlerClass = solrConfig.getUpdateHandlerInfo().className;
 
@@ -1049,7 +1071,8 @@ public final class SolrCore implements S
   private final LinkedList<RefCounted<SolrIndexSearcher>> _searchers = new LinkedList<RefCounted<SolrIndexSearcher>>();
   private final LinkedList<RefCounted<SolrIndexSearcher>> _realtimeSearchers = new LinkedList<RefCounted<SolrIndexSearcher>>();
 
-  final ExecutorService searcherExecutor = Executors.newSingleThreadExecutor();
+  final ExecutorService searcherExecutor = Executors.newSingleThreadExecutor(
+      new DefaultSolrThreadFactory("searcherExecutor"));
   private int onDeckSearchers;  // number of searchers preparing
   // Lock ordering: one can acquire the openSearcherLock and then the searcherLock, but not vice-versa.
   private Object searcherLock = new Object();  // the sync object for the searcher
@@ -1057,7 +1080,7 @@ public final class SolrCore implements S
   private final int maxWarmingSearchers;  // max number of on-deck searchers allowed
 
   private RefCounted<SolrIndexSearcher> realtimeSearcher;
-
+  private Callable<DirectoryReader> newReaderCreator;
 
   /**
   * Return a registered {@link RefCounted}&lt;{@link SolrIndexSearcher}&gt; with
@@ -1208,9 +1231,20 @@ public final class SolrCore implements S
         tmp = new SolrIndexSearcher(this, schema, (realtime ? "realtime":"main"), newReader, true, !realtime, true, directoryFactory);
 
       } else {
+        // newestSearcher == null at this point
+
+        if (newReaderCreator != null) {
+          // this is set in the constructor if there is a currently open index writer
+          // so that we pick up any uncommitted changes and so we don't go backwards
+          // in time on a core reload
+          DirectoryReader newReader = newReaderCreator.call();
+          tmp = new SolrIndexSearcher(this, schema, (realtime ? "realtime":"main"), newReader, true, !realtime, true, directoryFactory);
+        } else {
+         // normal open that happens at startup
         // verbose("non-reopen START:");
         tmp = new SolrIndexSearcher(this, newIndexDir, schema, getSolrConfig().indexConfig, "main", true, directoryFactory);
         // verbose("non-reopen DONE: searcher=",tmp);
+        }
       }
 
       List<RefCounted<SolrIndexSearcher>> searcherList = realtime ? _realtimeSearchers : _searchers;

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java Mon Aug 13 13:52:46 2012
@@ -17,23 +17,27 @@
 
 package org.apache.solr.core;
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileFilter;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.lucene.analysis.util.CharFilterFactory;
 import org.apache.lucene.analysis.util.ResourceLoaderAware;
 import org.apache.lucene.analysis.util.TokenFilterFactory;
 import org.apache.lucene.analysis.util.TokenizerFactory;
+import org.apache.lucene.codecs.Codec;
+import org.apache.lucene.codecs.PostingsFormat;
+import org.apache.lucene.util.hash.HashFunction;
+import org.apache.lucene.analysis.util.WordlistLoader;
 import org.apache.solr.common.ResourceLoader;
 import org.apache.solr.handler.admin.CoreAdminHandler;
 import org.apache.solr.handler.component.ShardHandlerFactory;
@@ -42,7 +46,6 @@ import org.slf4j.LoggerFactory;
 
 import java.nio.charset.CharacterCodingException;
 import java.nio.charset.Charset;
-import java.nio.charset.CodingErrorAction;
 import java.lang.reflect.Constructor;
 
 import javax.naming.Context;
@@ -108,7 +111,7 @@ public class SolrResourceLoader implemen
     
     this.classLoader = createClassLoader(null, parent);
     addToClassLoader("./lib/", null);
-    
+    reloadLuceneSPI();
     this.coreProperties = coreProperties;
   }
 
@@ -129,7 +132,8 @@ public class SolrResourceLoader implemen
    * Adds every file/dir found in the baseDir which passes the specified Filter
    * to the ClassLoader used by this ResourceLoader.  This method <b>MUST</b>
    * only be called prior to using this ResourceLoader to get any resources, otherwise
-   * it's behavior will be non-deterministic.
+   * it's behavior will be non-deterministic. You also have to {link @reloadLuceneSPI}
+   * before using this ResourceLoader.
    *
    * @param baseDir base directory whose children (either jars or directories of
    *                classes) will be in the classpath, will be resolved relative
@@ -145,7 +149,8 @@ public class SolrResourceLoader implemen
    * Adds the specific file/dir specified to the ClassLoader used by this
    * ResourceLoader.  This method <b>MUST</b>
    * only be called prior to using this ResourceLoader to get any resources, otherwise
-   * it's behavior will be non-deterministic.
+   * it's behavior will be non-deterministic. You also have to {link #reloadLuceneSPI()}
+   * before using this ResourceLoader.
    *
    * @param path A jar file (or directory of classes) to be added to the classpath,
    *             will be resolved relative the instance dir.
@@ -164,6 +169,24 @@ public class SolrResourceLoader implemen
     }
   }
   
+  /**
+   * Reloads all Lucene SPI implementations using the new classloader.
+   * This method must be called after {@link #addToClassLoader(String)}
+   * and {@link #addToClassLoader(String,FileFilter)} before using
+   * this ResourceLoader.
+   */
+  void reloadLuceneSPI() {
+    // Hash functions:
+    HashFunction.reloadHashFunctions(this.classLoader);
+    // Codecs:
+    PostingsFormat.reloadPostingsFormats(this.classLoader);
+    Codec.reloadCodecs(this.classLoader);
+    // Analysis:
+    CharFilterFactory.reloadCharFilters(this.classLoader);
+    TokenFilterFactory.reloadTokenFilters(this.classLoader);
+    TokenizerFactory.reloadTokenizers(this.classLoader);
+  }
+  
   private static URLClassLoader replaceClassLoader(final URLClassLoader oldLoader,
                                                    final File base,
                                                    final FileFilter filter) {
@@ -248,7 +271,7 @@ public class SolrResourceLoader implemen
    * Override this method to customize loading schema resources.
    *@return the stream for the named schema
    */
-  public InputStream openSchema(String name) {
+  public InputStream openSchema(String name) throws IOException {
     return openResource(name);
   }
   
@@ -256,7 +279,7 @@ public class SolrResourceLoader implemen
    * Override this method to customize loading config resources.
    *@return the stream for the named configuration
    */
-  public InputStream openConfig(String name) {
+  public InputStream openConfig(String name) throws IOException {
     return openResource(name);
   }
   
@@ -268,7 +291,7 @@ public class SolrResourceLoader implemen
    * Override this method to customize loading resources.
    *@return the stream for the named resource
    */
-  public InputStream openResource(String resource) {
+  public InputStream openResource(String resource) throws IOException {
     InputStream is=null;
     try {
       File f0 = new File(resource);
@@ -288,10 +311,10 @@ public class SolrResourceLoader implemen
       if (is == null)
         is = classLoader.getResourceAsStream(getConfigDir() + resource);
     } catch (Exception e) {
-      throw new RuntimeException("Error opening " + resource, e);
+      throw new IOException("Error opening " + resource, e);
     }
     if (is==null) {
-      throw new RuntimeException("Can't find resource '" + resource + "' in classpath or '" + getConfigDir() + "', cwd="+System.getProperty("user.dir"));
+      throw new IOException("Can't find resource '" + resource + "' in classpath or '" + getConfigDir() + "', cwd="+System.getProperty("user.dir"));
     }
     return is;
   }
@@ -333,41 +356,23 @@ public class SolrResourceLoader implemen
 
 
   public List<String> getLines(String resource, Charset charset) throws IOException{
-    BufferedReader input = null;
-    ArrayList<String> lines;
     try {
-      input = new BufferedReader(new InputStreamReader(openResource(resource),
-          charset.newDecoder()
-          .onMalformedInput(CodingErrorAction.REPORT)
-          .onUnmappableCharacter(CodingErrorAction.REPORT)));
-
-      lines = new ArrayList<String>();
-      for (String word=null; (word=input.readLine())!=null;) {
-        // skip initial bom marker
-        if (lines.isEmpty() && word.length() > 0 && word.charAt(0) == '\uFEFF')
-          word = word.substring(1);
-        // skip comments
-        if (word.startsWith("#")) continue;
-        word=word.trim();
-        // skip blank lines
-        if (word.length()==0) continue;
-        lines.add(word);
-      }
+      return WordlistLoader.getLines(openResource(resource), charset);
     } catch (CharacterCodingException ex) {
       throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, 
-          "Error loading resource (wrong encoding?): " + resource, ex);
-    } finally {
-      if (input != null)
-        input.close();
+         "Error loading resource (wrong encoding?): " + resource, ex);
     }
-    return lines;
   }
 
   /*
    * A static map of short class name to fully qualified class name 
    */
-  private static Map<String, String> classNameCache = new ConcurrentHashMap<String, String>();
+  private static final Map<String, String> classNameCache = new ConcurrentHashMap<String, String>();
 
+  // Using this pattern, legacy analysis components from previous Solr versions are identified and delegated to SPI loader:
+  private static final Pattern legacyAnalysisPattern = 
+      Pattern.compile("((\\Q"+base+".analysis.\\E)|(\\Q"+project+".\\E))([\\p{L}_$][\\p{L}\\p{N}_$]+?)(TokenFilter|Filter|Tokenizer|CharFilter)Factory");
+      
   /**
    * This method loads a class either with it's FQN or a short-name (solr.class-simplename or class-simplename).
    * It tries to load the class with the name that is given first and if it fails, it tries all the known
@@ -394,6 +399,27 @@ public class SolrResourceLoader implemen
       }
     }
     Class<? extends T> clazz = null;
+    
+    // first try legacy analysis patterns, now replaced by Lucene's Analysis package:
+    final Matcher m = legacyAnalysisPattern.matcher(cname);
+    if (m.matches()) {
+      final String name = m.group(4);
+      log.trace("Trying to load class from analysis SPI using name='{}'", name);
+      try {
+        if (CharFilterFactory.class.isAssignableFrom(expectedType)) {
+          return clazz = CharFilterFactory.lookupClass(name).asSubclass(expectedType);
+        } else if (TokenizerFactory.class.isAssignableFrom(expectedType)) {
+          return clazz = TokenizerFactory.lookupClass(name).asSubclass(expectedType);
+        } else if (TokenFilterFactory.class.isAssignableFrom(expectedType)) {
+          return clazz = TokenFilterFactory.lookupClass(name).asSubclass(expectedType);
+        } else {
+          log.warn("'{}' looks like an analysis factory, but caller requested different class type: {}", cname, expectedType.getName());
+        }
+      } catch (IllegalArgumentException ex) { 
+        // ok, we fall back to legacy loading
+      }
+    }
+    
     // first try cname == full name
     try {
       return Class.forName(cname, true, classLoader).asSubclass(expectedType);
@@ -425,6 +451,12 @@ public class SolrResourceLoader implemen
       }
     }
   }
+  
+  static final String empty[] = new String[0];
+  
+  public <T> T newInstance(String name, Class<T> expectedType) {
+    return newInstance(name, expectedType, empty);
+  }
 
   public <T> T newInstance(String cname, Class<T> expectedType, String ... subpackages) {
     Class<? extends T> clazz = findClass(cname, expectedType, subpackages);
@@ -568,7 +600,7 @@ public class SolrResourceLoader implemen
   /**
    * Tell all {@link ResourceLoaderAware} instances about the loader
    */
-  public void inform( ResourceLoader loader ) 
+  public void inform( ResourceLoader loader ) throws IOException
   {
 
      // make a copy to avoid potential deadlock of a callback adding to the list

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java Mon Aug 13 13:52:46 2012
@@ -887,7 +887,7 @@ public class ReplicationHandler extends 
           }
 
           // reboot the writer on the new index
-          core.getUpdateHandler().newIndexWriter();
+          core.getUpdateHandler().newIndexWriter(true);
 
         } catch (IOException e) {
           LOG.warn("Unable to get IndexCommit on startup", e);

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/SnapPuller.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/SnapPuller.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/SnapPuller.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/SnapPuller.java Mon Aug 13 13:52:46 2012
@@ -31,6 +31,7 @@ import org.apache.solr.common.params.Com
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.FastInputStream;
+import org.apache.solr.util.DefaultSolrThreadFactory;
 import org.apache.solr.util.FileUtils;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.core.CachingDirectoryFactory.CloseListener;
@@ -178,7 +179,8 @@ public class SnapPuller {
         }
       }
     };
-    executorService = Executors.newSingleThreadScheduledExecutor();
+    executorService = Executors.newSingleThreadScheduledExecutor(
+        new DefaultSolrThreadFactory("snapPuller"));
     long initialDelay = pollInterval - (System.currentTimeMillis() % pollInterval);
     executorService.scheduleAtFixedRate(task, initialDelay, pollInterval, TimeUnit.MILLISECONDS);
     LOG.info("Poll Scheduled at an interval of " + pollInterval + "ms");
@@ -311,7 +313,7 @@ public class SnapPuller {
       LOG.info("Number of files in latest index in master: " + filesToDownload.size());
 
       // Create the sync service
-      fsyncService = Executors.newSingleThreadExecutor();
+      fsyncService = Executors.newSingleThreadExecutor(new DefaultSolrThreadFactory("fsyncService"));
       // use a synchronized list because the list is read by other threads (to show details)
       filesDownloaded = Collections.synchronizedList(new ArrayList<Map<String, Object>>());
       // if the generateion of master is older than that of the slave , it means they are not compatible to be copied
@@ -324,7 +326,8 @@ public class SnapPuller {
       successfulInstall = false;
       boolean deleteTmpIdxDir = true;
 
-      final File indexDir = new File(core.getIndexDir());
+      // make sure it's the newest known index dir...
+      final File indexDir = new File(core.getNewIndexDir());
       Directory oldDirectory = null;
       try {
         downloadIndexFiles(isFullCopyNeeded, tmpIndexDir, latestGeneration);
@@ -534,7 +537,7 @@ public class SnapPuller {
     SolrQueryRequest req = new LocalSolrQueryRequest(solrCore,
         new ModifiableSolrParams());
     // reboot the writer on the new index and get a new searcher
-    solrCore.getUpdateHandler().newIndexWriter();
+    solrCore.getUpdateHandler().newIndexWriter(true);
     
     try {
       // first try to open an NRT searcher so that the new 

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java Mon Aug 13 13:52:46 2012
@@ -17,9 +17,17 @@ package org.apache.solr.handler.admin;
  * limitations under the License.
  */
 
+import java.io.IOException;
+
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrServer;
+import org.apache.solr.client.solrj.request.CoreAdminRequest;
+import org.apache.solr.client.solrj.request.CoreAdminRequest.RequestSyncShard;
 import org.apache.solr.cloud.Overseer;
 import org.apache.solr.cloud.OverseerCollectionProcessor;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.cloud.ClusterState;
+import org.apache.solr.common.cloud.ZkCoreNodeProps;
 import org.apache.solr.common.cloud.ZkNodeProps;
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.CollectionParams.CollectionAction;
@@ -103,6 +111,10 @@ public class CollectionsHandler extends 
           this.handleReloadAction(req, rsp);
           break;
         }
+        case SYNCSHARD: {
+          this.handleSyncShardAction(req, rsp);
+          break;
+        }
         
         default: {
           throw new RuntimeException("Unknown action: " + action);
@@ -123,6 +135,24 @@ public class CollectionsHandler extends 
     // TODO: what if you want to block until the collection is available?
     coreContainer.getZkController().getOverseerCollectionQueue().offer(ZkStateReader.toJSON(m));
   }
+  
+  private void handleSyncShardAction(SolrQueryRequest req, SolrQueryResponse rsp) throws KeeperException, InterruptedException, SolrServerException, IOException {
+    log.info("Syncing shard : " + req.getParamString());
+    String collection = req.getParams().required().get("collection");
+    String shard = req.getParams().required().get("shard");
+    
+    ClusterState clusterState = coreContainer.getZkController().getClusterState();
+    
+    ZkNodeProps leaderProps = clusterState.getLeader(collection, shard);
+    ZkCoreNodeProps nodeProps = new ZkCoreNodeProps(leaderProps);
+    
+    HttpSolrServer server = new HttpSolrServer(nodeProps.getBaseUrl());
+    RequestSyncShard reqSyncShard = new CoreAdminRequest.RequestSyncShard();
+    reqSyncShard.setCollection(collection);
+    reqSyncShard.setShard(shard);
+    reqSyncShard.setCoreName(nodeProps.getCoreName());
+    server.request(reqSyncShard);
+  }
 
 
   private void handleDeleteAction(SolrQueryRequest req, SolrQueryResponse rsp) throws KeeperException, InterruptedException {

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java Mon Aug 13 13:52:46 2012
@@ -19,8 +19,11 @@ package org.apache.solr.handler.admin;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Properties;
 
 import org.apache.commons.io.FileUtils;
@@ -28,9 +31,11 @@ import org.apache.lucene.index.Directory
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.IOUtils;
 import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.cloud.SyncStrategy;
+import org.apache.solr.cloud.ZkController;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.cloud.CloudState;
+import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.Slice;
 import org.apache.solr.common.cloud.ZkNodeProps;
 import org.apache.solr.common.cloud.ZkStateReader;
@@ -47,8 +52,6 @@ import org.apache.solr.core.CoreDescript
 import org.apache.solr.core.DirectoryFactory;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.handler.RequestHandlerBase;
-import org.apache.solr.handler.component.ShardHandler;
-import org.apache.solr.handler.component.ShardHandlerFactory;
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
@@ -69,8 +72,6 @@ import org.slf4j.LoggerFactory;
 public class CoreAdminHandler extends RequestHandlerBase {
   protected static Logger log = LoggerFactory.getLogger(CoreAdminHandler.class);
   protected final CoreContainer coreContainer;
-  private ShardHandlerFactory shardHandlerFactory;
-  private ShardHandler shardHandler;
 
   public CoreAdminHandler() {
     super();
@@ -87,8 +88,6 @@ public class CoreAdminHandler extends Re
    */
   public CoreAdminHandler(final CoreContainer coreContainer) {
     this.coreContainer = coreContainer;
-    shardHandlerFactory = coreContainer.getShardHandlerFactory();
-    shardHandler = shardHandlerFactory.getShardHandler();
   }
 
 
@@ -182,6 +181,11 @@ public class CoreAdminHandler extends Re
           break;
         }
         
+        case REQUESTSYNCSHARD: {
+          this.handleRequestSyncAction(req, rsp);
+          break;
+        }
+        
         default: {
           doPersist = this.handleCustomAction(req, rsp);
           break;
@@ -564,13 +568,19 @@ public class CoreAdminHandler extends Re
     String cname = params.get(CoreAdminParams.CORE);
     boolean doPersist = false;
     NamedList<Object> status = new SimpleOrderedMap<Object>();
+    Map<String,Exception> allFailures = coreContainer.getCoreInitFailures();
     try {
       if (cname == null) {
         rsp.add("defaultCoreName", coreContainer.getDefaultCoreName());
         for (String name : coreContainer.getCoreNames()) {
           status.add(name, getCoreStatus(coreContainer, name));
         }
+        rsp.add("initFailures", allFailures);
       } else {
+        Map failures = allFailures.containsKey(cname)
+          ? Collections.singletonMap(cname, allFailures.get(cname))
+          : Collections.emptyMap();
+        rsp.add("initFailures", failures);
         status.add(cname, getCoreStatus(coreContainer, cname));
       }
       rsp.add("status", status);
@@ -655,7 +665,7 @@ public class CoreAdminHandler extends Re
   protected void handleRequestRecoveryAction(SolrQueryRequest req,
       SolrQueryResponse rsp) throws IOException {
     final SolrParams params = req.getParams();
-    
+    log.info("It has been requested that we recover");
     String cname = params.get(CoreAdminParams.CORE);
     if (cname == null) {
       cname = "";
@@ -664,6 +674,15 @@ public class CoreAdminHandler extends Re
     try {
       core = coreContainer.getCore(cname);
       if (core != null) {
+        // try to publish as recovering right away
+        try {
+          coreContainer.getZkController().publish(core.getCoreDescriptor(), ZkStateReader.RECOVERING);
+        } catch (KeeperException e) {
+          SolrException.log(log, "", e);
+        } catch (InterruptedException e) {
+          SolrException.log(log, "", e);
+        }
+        
         core.getUpdateHandler().getSolrCoreState().doRecovery(coreContainer, cname);
       } else {
         SolrException.log(log, "Cound not find core to call recovery:" + cname);
@@ -676,6 +695,48 @@ public class CoreAdminHandler extends Re
     }
   }
   
+  protected void handleRequestSyncAction(SolrQueryRequest req,
+      SolrQueryResponse rsp) throws IOException {
+    final SolrParams params = req.getParams();
+
+    log.info("I have been requested to sync up my shard");
+    ZkController zkController = coreContainer.getZkController();
+    if (zkController == null) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Only valid for SolrCloud");
+    }
+    
+    String cname = params.get(CoreAdminParams.CORE);
+    if (cname == null) {
+      throw new IllegalArgumentException(CoreAdminParams.CORE + " is required");
+    }
+    SolrCore core = null;
+    try {
+      core = coreContainer.getCore(cname);
+      if (core != null) {
+        SyncStrategy syncStrategy = new SyncStrategy();
+
+        Map<String,String> props = new HashMap<String,String>();
+        props.put(ZkStateReader.BASE_URL_PROP, zkController.getBaseUrl());
+        props.put(ZkStateReader.CORE_NAME_PROP, cname);
+        props.put(ZkStateReader.NODE_NAME_PROP, zkController.getNodeName());
+        
+        boolean success = syncStrategy.sync(zkController, core, new ZkNodeProps(props));
+        if (!success) {
+          throw new SolrException(ErrorCode.SERVER_ERROR, "Sync Failed");
+        }
+      } else {
+        SolrException.log(log, "Cound not find core to call sync:" + cname);
+      }
+    } finally {
+      // no recoveryStrat close for now
+      if (core != null) {
+        core.close();
+      }
+    }
+    
+
+  }
+  
   protected void handleWaitForStateAction(SolrQueryRequest req,
       SolrQueryResponse rsp) throws IOException, InterruptedException {
     final SolrParams params = req.getParams();
@@ -707,16 +768,16 @@ public class CoreAdminHandler extends Re
           // to accept updates
           CloudDescriptor cloudDescriptor = core.getCoreDescriptor()
               .getCloudDescriptor();
-          CloudState cloudState = coreContainer.getZkController()
-              .getCloudState();
+          ClusterState clusterState = coreContainer.getZkController()
+              .getClusterState();
           String collection = cloudDescriptor.getCollectionName();
-          Slice slice = cloudState.getSlice(collection,
+          Slice slice = clusterState.getSlice(collection,
               cloudDescriptor.getShardId());
           if (slice != null) {
             ZkNodeProps nodeProps = slice.getShards().get(coreNodeName);
             if (nodeProps != null) {
               state = nodeProps.get(ZkStateReader.STATE_PROP);
-              live = cloudState.liveNodesContain(nodeName);
+              live = clusterState.liveNodesContain(nodeName);
               if (nodeProps != null && state.equals(waitForState)) {
                 if (checkLive == null) {
                   break;

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java Mon Aug 13 13:52:46 2012
@@ -390,7 +390,7 @@ public class LukeRequestHandler extends 
       docsEnum = reader.termDocsEnum(reader.getLiveDocs(),
           term.field(),
           new BytesRef(term.text()),
-          false);
+          0);
       if (docsEnum != null) {
         int docId;
         if ((docId = docsEnum.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java Mon Aug 13 13:52:46 2012
@@ -144,6 +144,9 @@ public class ShowFileRequestHandler exte
       if (fname.indexOf("..") >= 0) {
         throw new SolrException(ErrorCode.FORBIDDEN, "Invalid path: " + fname);
       }
+      if (fname.startsWith("/")) { // Only files relative to conf are valid
+        fname = fname.substring(1);
+      }
       adminFile = confPath + "/" + fname;
     }
     

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java Mon Aug 13 13:52:46 2012
@@ -41,7 +41,7 @@ import org.apache.solr.cloud.CloudDescri
 import org.apache.solr.cloud.ZkController;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.cloud.CloudState;
+import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.Slice;
 import org.apache.solr.common.cloud.ZkCoreNodeProps;
 import org.apache.solr.common.cloud.ZkNodeProps;
@@ -255,7 +255,7 @@ public class HttpShardHandler extends Sh
     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;
+      ClusterState clusterState = null;
       Map<String,Slice> slices = null;
       CoreDescriptor coreDescriptor = req.getCore().getCoreDescriptor();
       CloudDescriptor cloudDescriptor = coreDescriptor.getCloudDescriptor();
@@ -280,7 +280,7 @@ public class HttpShardHandler extends Sh
       } 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();
+        clusterState =  zkController.getClusterState();
 
         // 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
@@ -301,12 +301,12 @@ public class HttpShardHandler extends Sh
           // cloud state and add them to the Map 'slices'.
           for (int i = 0; i < collectionList.size(); i++) {
             String collection = collectionList.get(i);
-            ClientUtils.appendMap(collection, slices, cloudState.getSlices(collection));
+            ClientUtils.appendMap(collection, slices, clusterState.getSlices(collection));
           }
         } else {
           // If no collections were specified, default to the collection for
           // this core.
-          slices = cloudState.getSlices(cloudDescriptor.getCollectionName());
+          slices = clusterState.getSlices(cloudDescriptor.getCollectionName());
           if (slices == null) {
             throw new SolrException(ErrorCode.BAD_REQUEST,
                 "Could not find collection:"
@@ -334,9 +334,9 @@ public class HttpShardHandler extends Sh
       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());
+            if (clusterState == null) {
+              clusterState =  zkController.getClusterState();
+              slices = clusterState.getSlices(cloudDescriptor.getCollectionName());
             }
             String sliceName = rb.slices[i];
 
@@ -353,7 +353,7 @@ public class HttpShardHandler extends Sh
             Map<String, ZkNodeProps> sliceShards = slice.getShards();
 
             // For now, recreate the | delimited list of equivalent servers
-            Set<String> liveNodes = cloudState.getLiveNodes();
+            Set<String> liveNodes = clusterState.getLiveNodes();
             StringBuilder sliceShardsStr = new StringBuilder();
             boolean first = true;
             for (ZkNodeProps nodeProps : sliceShards.values()) {

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java Mon Aug 13 13:52:46 2012
@@ -543,7 +543,7 @@ public class QueryElevationComponent ext
         for (String id : elevations.ids) {
           term.copyChars(id);
           if (seen.contains(id) == false  && termsEnum.seekExact(term, false)) {
-            docsEnum = termsEnum.docs(liveDocs, docsEnum, false);
+            docsEnum = termsEnum.docs(liveDocs, docsEnum, 0);
             if (docsEnum != null) {
               int docId = docsEnum.nextDoc();
               if (docId == DocIdSetIterator.NO_MORE_DOCS ) continue;  // must have been deleted

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java Mon Aug 13 13:52:46 2012
@@ -352,14 +352,14 @@ public class RealTimeGetComponent extend
 
       String collection = cloudDescriptor.getCollectionName();
 
-      CloudState cloudState = zkController.getCloudState();
+      ClusterState clusterState = zkController.getClusterState();
       
       Map<String, List<String>> shardToId = new HashMap<String, List<String>>();
       for (String id : allIds) {
         BytesRef br = new BytesRef();
         sf.getType().readableToIndexed(id, br);
         int hash = Hash.murmurhash3_x86_32(br.bytes, br.offset, br.length, 0);
-        String shard = cloudState.getShard(hash,  collection);
+        String shard = clusterState.getShard(hash,  collection);
 
         List<String> idsForShard = shardToId.get(shard);
         if (idsForShard == null) {

Modified: lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java?rev=1372423&r1=1372422&r2=1372423&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java (original)
+++ lucene/dev/branches/LUCENE-2878/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java Mon Aug 13 13:52:46 2012
@@ -256,13 +256,12 @@ class SimpleStats {
     FieldCache.DocTermsIndex facetTermsIndex;
     for( String facetField : facet ) {
       SchemaField fsf = searcher.getSchema().getField(facetField);
-      FieldType facetFieldType = fsf.getType();
 
-      if (facetFieldType.isTokenized() || facetFieldType.isMultiValued()) {
+      if ( fsf.multiValued()) {
         throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
-          "Stats can only facet on single-valued fields, not: " + facetField
-          + "[" + facetFieldType + "]");
-        }
+          "Stats can only facet on single-valued fields, not: " + facetField );
+      }
+
       try {
         facetTermsIndex = FieldCache.DEFAULT.getTermsIndex(searcher.getAtomicReader(), facetField);
       }