You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ma...@apache.org on 2012/07/16 22:08:48 UTC

svn commit: r1362232 - in /lucene/dev/trunk/solr: ./ core/src/java/org/apache/solr/core/ core/src/java/org/apache/solr/handler/ core/src/java/org/apache/solr/update/ core/src/test/org/apache/solr/ core/src/test/org/apache/solr/cloud/ core/src/test/org/...

Author: markrmiller
Date: Mon Jul 16 20:08:46 2012
New Revision: 1362232

URL: http://svn.apache.org/viewvc?rev=1362232&view=rev
Log:
SOLR-3621: fix rare concurrency issue when opening a new IndexWriter for replication or rollback.

Modified:
    lucene/dev/trunk/solr/CHANGES.txt
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SnapPuller.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/SolrCoreState.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/AbstractDistributedZkTestCase.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfig.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInject.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInjectDefaults.java

Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Mon Jul 16 20:08:46 2012
@@ -87,6 +87,9 @@ Bug Fixes
 
 * SOLR-3377: edismax fails to correctly parse a fielded query wrapped by parens.
   This regression was introduced in 3.6.  (Bernd Fehling, Jan Høydahl, yonik)
+  
+* SOLR-3621: fix rare concurrency issue when opening a new IndexWriter for replication or rollback.
+  (Mark Miller)
 
 
 Other Changes

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java Mon Jul 16 20:08:46 2012
@@ -1180,8 +1180,12 @@ public final class SolrCore implements S
 
         if (updateHandlerReopens) {
           // SolrCore.verbose("start reopen from",previousSearcher,"writer=",writer);
-          IndexWriter writer = getUpdateHandler().getSolrCoreState().getIndexWriter(this);
-          newReader = DirectoryReader.openIfChanged(currentReader, writer, true);
+          RefCounted<IndexWriter> writer = getUpdateHandler().getSolrCoreState().getIndexWriter(this);
+          try {
+            newReader = DirectoryReader.openIfChanged(currentReader, writer.get(), true);
+          } finally {
+            writer.decref();
+          }
 
         } else {
           // verbose("start reopen without writer, reader=", currentReader);

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SnapPuller.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SnapPuller.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SnapPuller.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SnapPuller.java Mon Jul 16 20:08:46 2012
@@ -19,6 +19,7 @@ package org.apache.solr.handler;
 import org.apache.commons.io.IOUtils;
 import org.apache.http.client.HttpClient;
 import org.apache.lucene.index.IndexCommit;
+import org.apache.lucene.index.IndexWriter;
 import org.apache.solr.client.solrj.SolrServer;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
@@ -276,7 +277,12 @@ public class SnapPuller {
         if (force && commit.getGeneration() != 0) {
           // since we won't get the files for an empty index,
           // we just clear ours and commit
-          core.getUpdateHandler().getSolrCoreState().getIndexWriter(core).deleteAll();
+          RefCounted<IndexWriter> iw = core.getUpdateHandler().getSolrCoreState().getIndexWriter(core);
+          try {
+            iw.get().deleteAll();
+          } finally {
+            iw.decref();
+          }
           SolrQueryRequest req = new LocalSolrQueryRequest(core,
               new ModifiableSolrParams());
           core.getUpdateHandler().commit(new CommitUpdateCommand(req, false));

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java Mon Jul 16 20:08:46 2012
@@ -24,6 +24,7 @@ import org.apache.solr.cloud.RecoveryStr
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.DirectoryFactory;
 import org.apache.solr.core.SolrCore;
+import org.apache.solr.util.RefCounted;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -40,26 +41,67 @@ public final class DefaultSolrCoreState 
   private boolean recoveryRunning;
   private RecoveryStrategy recoveryStrat;
   private boolean closed = false;
+
+  private RefCounted<IndexWriter> refCntWriter;
+
+  private boolean pauseWriter;
+  private boolean writerFree = true;
   
   public DefaultSolrCoreState(DirectoryFactory directoryFactory) {
     this.directoryFactory = directoryFactory;
   }
   
   @Override
-  public synchronized IndexWriter getIndexWriter(SolrCore core) throws IOException {
+  public synchronized RefCounted<IndexWriter> getIndexWriter(SolrCore core)
+      throws IOException {
+    while (pauseWriter) {
+      try {
+        wait();
+      } catch (InterruptedException e) {}
+    }
+    
     if (indexWriter == null) {
-      indexWriter = createMainIndexWriter(core, "DirectUpdateHandler2", false, false);
+      indexWriter = createMainIndexWriter(core, "DirectUpdateHandler2", false,
+          false);
     }
-    return indexWriter;
+    if (refCntWriter == null) {
+      refCntWriter = new RefCounted<IndexWriter>(indexWriter) {
+        @Override
+        public void close() {
+          synchronized (DefaultSolrCoreState.this) {
+            writerFree = true;
+            DefaultSolrCoreState.this.notifyAll();
+          }
+        }
+      };
+    }
+    writerFree = false;
+    notifyAll();
+    refCntWriter.incref();
+    return refCntWriter;
   }
 
   @Override
   public synchronized void newIndexWriter(SolrCore core) throws IOException {
+    // we need to wait for the Writer to fall out of use
+    // first lets stop it from being lent out
+    pauseWriter = true;
+    // then lets wait until its out of use
+    while(!writerFree) {
+      try {
+        wait();
+      } catch (InterruptedException e) {}
+    }
+    
     if (indexWriter != null) {
       indexWriter.close();
     }
     indexWriter = createMainIndexWriter(core, "DirectUpdateHandler2",
         false, true);
+    // we need to null this so it picks up the new writer next get call
+    refCntWriter = null;
+    pauseWriter = false;
+    notifyAll();
   }
 
   @Override

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java Mon Jul 16 20:08:46 2012
@@ -137,7 +137,12 @@ public class DirectUpdateHandler2 extend
 
   private void deleteAll() throws IOException {
     SolrCore.log.info(core.getLogId()+"REMOVING ALL DOCUMENTS FROM INDEX");
-    solrCoreState.getIndexWriter(core).deleteAll();
+    RefCounted<IndexWriter> iw = solrCoreState.getIndexWriter(core);
+    try {
+      iw.get().deleteAll();
+    } finally {
+      iw.decref();
+    }
   }
 
   protected void rollbackWriter() throws IOException {
@@ -148,115 +153,124 @@ public class DirectUpdateHandler2 extend
 
   @Override
   public int addDoc(AddUpdateCommand cmd) throws IOException {
-    IndexWriter writer = solrCoreState.getIndexWriter(core);
-    addCommands.incrementAndGet();
-    addCommandsCumulative.incrementAndGet();
-    int rc=-1;
-
-    // if there is no ID field, don't overwrite
-    if( idField == null ) {
-      cmd.overwrite = false;
-    }
-
-
+    int rc = -1;
+    RefCounted<IndexWriter> iw = solrCoreState.getIndexWriter(core);
     try {
-
-      if (cmd.overwrite) {
-
-        // Check for delete by query commands newer (i.e. reordered).  This should always be null on a leader
-        List<UpdateLog.DBQ> deletesAfter = null;
-        if (ulog != null && cmd.version > 0) {
-          deletesAfter = ulog.getDBQNewer(cmd.version);
-        }
-
-        if (deletesAfter != null) {
-          log.info("Reordered DBQs detected.  Update="+cmd+" DBQs="+deletesAfter);
-          List<Query> dbqList = new ArrayList<Query>(deletesAfter.size());
-          for (UpdateLog.DBQ dbq : deletesAfter) {
-            try {
-              DeleteUpdateCommand tmpDel = new DeleteUpdateCommand(cmd.req);
-              tmpDel.query = dbq.q;
-              tmpDel.version = -dbq.version;
-              dbqList.add( getQuery(tmpDel) );
-            } catch (Exception e) {
-              log.error("Exception parsing reordered query : " + dbq, e);
-            }
+      IndexWriter writer = iw.get();
+      addCommands.incrementAndGet();
+      addCommandsCumulative.incrementAndGet();
+      
+      // if there is no ID field, don't overwrite
+      if (idField == null) {
+        cmd.overwrite = false;
+      }
+      
+      try {
+        
+        if (cmd.overwrite) {
+          
+          // Check for delete by query commands newer (i.e. reordered). This
+          // should always be null on a leader
+          List<UpdateLog.DBQ> deletesAfter = null;
+          if (ulog != null && cmd.version > 0) {
+            deletesAfter = ulog.getDBQNewer(cmd.version);
           }
-
-          addAndDelete(cmd, dbqList);
-        } else {
-          // normal update
-
-          Term updateTerm;
-          Term idTerm = new Term(idField.getName(), cmd.getIndexedId());
-          boolean del = false;
-          if (cmd.updateTerm == null) {
-            updateTerm = idTerm;
+          
+          if (deletesAfter != null) {
+            log.info("Reordered DBQs detected.  Update=" + cmd + " DBQs="
+                + deletesAfter);
+            List<Query> dbqList = new ArrayList<Query>(deletesAfter.size());
+            for (UpdateLog.DBQ dbq : deletesAfter) {
+              try {
+                DeleteUpdateCommand tmpDel = new DeleteUpdateCommand(cmd.req);
+                tmpDel.query = dbq.q;
+                tmpDel.version = -dbq.version;
+                dbqList.add(getQuery(tmpDel));
+              } catch (Exception e) {
+                log.error("Exception parsing reordered query : " + dbq, e);
+              }
+            }
+            
+            addAndDelete(cmd, dbqList);
           } else {
-            del = true;
-            updateTerm = cmd.updateTerm;
-          }
-
-          Document luceneDocument = cmd.getLuceneDocument();
-          // SolrCore.verbose("updateDocument",updateTerm,luceneDocument,writer);
-          writer.updateDocument(updateTerm, luceneDocument, schema.getAnalyzer());
-          // SolrCore.verbose("updateDocument",updateTerm,"DONE");
-
-
-          if(del) { // ensure id remains unique
-            BooleanQuery bq = new BooleanQuery();
-            bq.add(new BooleanClause(new TermQuery(updateTerm), Occur.MUST_NOT));
-            bq.add(new BooleanClause(new TermQuery(idTerm), Occur.MUST));
-            writer.deleteDocuments(bq);
+            // normal update
+            
+            Term updateTerm;
+            Term idTerm = new Term(idField.getName(), cmd.getIndexedId());
+            boolean del = false;
+            if (cmd.updateTerm == null) {
+              updateTerm = idTerm;
+            } else {
+              del = true;
+              updateTerm = cmd.updateTerm;
+            }
+            
+            Document luceneDocument = cmd.getLuceneDocument();
+            // SolrCore.verbose("updateDocument",updateTerm,luceneDocument,writer);
+            writer.updateDocument(updateTerm, luceneDocument,
+                schema.getAnalyzer());
+            // SolrCore.verbose("updateDocument",updateTerm,"DONE");
+            
+            if (del) { // ensure id remains unique
+              BooleanQuery bq = new BooleanQuery();
+              bq.add(new BooleanClause(new TermQuery(updateTerm),
+                  Occur.MUST_NOT));
+              bq.add(new BooleanClause(new TermQuery(idTerm), Occur.MUST));
+              writer.deleteDocuments(bq);
+            }
+            
+            // Add to the transaction log *after* successfully adding to the
+            // index, if there was no error.
+            // This ordering ensures that if we log it, it's definitely been
+            // added to the the index.
+            // This also ensures that if a commit sneaks in-between, that we
+            // know everything in a particular
+            // log version was definitely committed.
+            if (ulog != null) ulog.add(cmd);
           }
-
-
-          // Add to the transaction log *after* successfully adding to the index, if there was no error.
-          // This ordering ensures that if we log it, it's definitely been added to the the index.
-          // This also ensures that if a commit sneaks in-between, that we know everything in a particular
-          // log version was definitely committed.
+          
+        } else {
+          // allow duplicates
+          writer.addDocument(cmd.getLuceneDocument(), schema.getAnalyzer());
           if (ulog != null) ulog.add(cmd);
         }
-
-      } else {
-        // allow duplicates
-        writer.addDocument(cmd.getLuceneDocument(), schema.getAnalyzer());
-        if (ulog != null) ulog.add(cmd);
-      }
-
-
-      if ((cmd.getFlags() & UpdateCommand.IGNORE_AUTOCOMMIT) == 0) {
-        commitTracker.addedDocument( -1 );
-        softCommitTracker.addedDocument( cmd.commitWithin );
+        
+        if ((cmd.getFlags() & UpdateCommand.IGNORE_AUTOCOMMIT) == 0) {
+          commitTracker.addedDocument(-1);
+          softCommitTracker.addedDocument(cmd.commitWithin);
+        }
+        
+        rc = 1;
+      } finally {
+        if (rc != 1) {
+          numErrors.incrementAndGet();
+          numErrorsCumulative.incrementAndGet();
+        } else {
+          numDocsPending.incrementAndGet();
+        }
       }
-
-      rc = 1;
+      
     } finally {
-      if (rc!=1) {
-        numErrors.incrementAndGet();
-        numErrorsCumulative.incrementAndGet();
-      } else {
-        numDocsPending.incrementAndGet();
-      }
+      iw.decref();
     }
-
+    
     return rc;
   }
-
+  
   private void updateDeleteTrackers(DeleteUpdateCommand cmd) {
     if ((cmd.getFlags() & UpdateCommand.IGNORE_AUTOCOMMIT) == 0) {
-      softCommitTracker.deletedDocument( cmd.commitWithin );
-
+      softCommitTracker.deletedDocument(cmd.commitWithin);
+      
       if (commitTracker.getTimeUpperBound() > 0) {
         commitTracker.scheduleCommitWithin(commitTracker.getTimeUpperBound());
       }
-
+      
       if (softCommitTracker.getTimeUpperBound() > 0) {
-        softCommitTracker.scheduleCommitWithin(softCommitTracker.getTimeUpperBound());
+        softCommitTracker.scheduleCommitWithin(softCommitTracker
+            .getTimeUpperBound());
       }
     }
   }
-  
 
   // we don't return the number of docs deleted because it's not always possible to quickly know that info.
   @Override
@@ -264,11 +278,14 @@ public class DirectUpdateHandler2 extend
     deleteByIdCommands.incrementAndGet();
     deleteByIdCommandsCumulative.incrementAndGet();
 
-    IndexWriter writer = solrCoreState.getIndexWriter(core);
     Term deleteTerm = new Term(idField.getName(), cmd.getIndexedId());
-
     // SolrCore.verbose("deleteDocuments",deleteTerm,writer);
-    writer.deleteDocuments(deleteTerm);
+    RefCounted<IndexWriter> iw = solrCoreState.getIndexWriter(core);
+    try {
+      iw.get().deleteDocuments(deleteTerm);
+    } finally {
+      iw.decref();
+    }
     // SolrCore.verbose("deleteDocuments",deleteTerm,"DONE");
 
     if (ulog != null) ulog.delete(cmd);
@@ -343,7 +360,12 @@ public class DirectUpdateHandler2 extend
         if (delAll) {
           deleteAll();
         } else {
-          solrCoreState.getIndexWriter(core).deleteDocuments(q);
+          RefCounted<IndexWriter> iw = solrCoreState.getIndexWriter(core);
+          try {
+            iw.get().deleteDocuments(q);
+          } finally {
+            iw.decref();
+          }
         }
 
         if (ulog != null) ulog.deleteByQuery(cmd);
@@ -364,23 +386,29 @@ public class DirectUpdateHandler2 extend
 
 
   /** Add a document execute the deletes as atomically as possible */
-  private void addAndDelete(AddUpdateCommand cmd, List<Query> dbqList) throws IOException {
+  private void addAndDelete(AddUpdateCommand cmd, List<Query> dbqList)
+      throws IOException {
     Document luceneDocument = cmd.getLuceneDocument();
     Term idTerm = new Term(idField.getName(), cmd.getIndexedId());
-
+    
     // see comment in deleteByQuery
     synchronized (this) {
-      IndexWriter writer = solrCoreState.getIndexWriter(core);
-
-      writer.updateDocument(idTerm, luceneDocument, core.getSchema().getAnalyzer());
-
-      for (Query q : dbqList) {
-        writer.deleteDocuments(q);
+      RefCounted<IndexWriter> iw = solrCoreState.getIndexWriter(core);
+      try {
+        IndexWriter writer = iw.get();
+        writer.updateDocument(idTerm, luceneDocument, core.getSchema()
+            .getAnalyzer());
+        
+        for (Query q : dbqList) {
+          writer.deleteDocuments(q);
+        }
+      } finally {
+        iw.decref();
       }
-
+      
       if (ulog != null) ulog.add(cmd, true);
     }
-
+    
   }
 
 
@@ -395,7 +423,12 @@ public class DirectUpdateHandler2 extend
     
     IndexReader[] readers = cmd.readers;
     if (readers != null && readers.length > 0) {
-      solrCoreState.getIndexWriter(core).addIndexes(readers);
+      RefCounted<IndexWriter> iw = solrCoreState.getIndexWriter(core);
+      try {
+        iw.get().addIndexes(readers);
+      } finally {
+        iw.decref();
+      }
       rc = 1;
     } else {
       rc = 0;
@@ -418,9 +451,12 @@ public class DirectUpdateHandler2 extend
 
     try {
       log.info("start "+cmd);
-      IndexWriter writer = solrCoreState.getIndexWriter(core);
-
-      writer.prepareCommit();
+      RefCounted<IndexWriter> iw = solrCoreState.getIndexWriter(core);
+      try {
+        iw.get().prepareCommit();
+      } finally {
+        iw.decref();
+      }
 
       log.info("end_prepareCommit");
 
@@ -438,7 +474,6 @@ public class DirectUpdateHandler2 extend
       return;
     }
 
-    IndexWriter writer = solrCoreState.getIndexWriter(core);
     if (cmd.optimize) {
       optimizeCommands.incrementAndGet();
     } else {
@@ -473,27 +508,35 @@ public class DirectUpdateHandler2 extend
          commitTracker.cancelPendingCommit();
       }
 
-
-      if (cmd.optimize) {
-        writer.forceMerge(cmd.maxOptimizeSegments);
-      } else if (cmd.expungeDeletes) {
-        writer.forceMergeDeletes();
-      }
-
-      if (!cmd.softCommit) {
-        synchronized (this) { // sync is currently needed to prevent preCommit from being called between preSoft and postSoft... see postSoft comments.
-          if (ulog != null) ulog.preCommit(cmd);
+      RefCounted<IndexWriter> iw = solrCoreState.getIndexWriter(core);
+      try {
+        IndexWriter writer = iw.get();
+        if (cmd.optimize) {
+          writer.forceMerge(cmd.maxOptimizeSegments);
+        } else if (cmd.expungeDeletes) {
+          writer.forceMergeDeletes();
         }
-
-        // SolrCore.verbose("writer.commit() start writer=",writer);
-        final Map<String,String> commitData = new HashMap<String,String>();
-        commitData.put(SolrIndexWriter.COMMIT_TIME_MSEC_KEY, String.valueOf(System.currentTimeMillis()));
-        writer.commit(commitData);
-        // SolrCore.verbose("writer.commit() end");
-        numDocsPending.set(0);
-        callPostCommitCallbacks();
-      } else {
-        callPostSoftCommitCallbacks();
+        
+        if (!cmd.softCommit) {
+          synchronized (this) { // sync is currently needed to prevent preCommit
+                                // from being called between preSoft and
+                                // postSoft... see postSoft comments.
+            if (ulog != null) ulog.preCommit(cmd);
+          }
+          
+          // SolrCore.verbose("writer.commit() start writer=",writer);
+          final Map<String,String> commitData = new HashMap<String,String>();
+          commitData.put(SolrIndexWriter.COMMIT_TIME_MSEC_KEY,
+              String.valueOf(System.currentTimeMillis()));
+          writer.commit(commitData);
+          // SolrCore.verbose("writer.commit() end");
+          numDocsPending.set(0);
+          callPostCommitCallbacks();
+        } else {
+          callPostSoftCommitCallbacks();
+        }
+      } finally {
+        iw.decref();
       }
 
 

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/SolrCoreState.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/SolrCoreState.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/SolrCoreState.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/SolrCoreState.java Mon Jul 16 20:08:46 2012
@@ -23,6 +23,7 @@ import org.apache.lucene.index.IndexWrit
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.DirectoryFactory;
 import org.apache.solr.core.SolrCore;
+import org.apache.solr.util.RefCounted;
 
 /**
  * The state in this class can be easily shared between SolrCores across
@@ -46,7 +47,7 @@ public abstract class SolrCoreState {
    * 
    * @throws IOException
    */
-  public abstract IndexWriter getIndexWriter(SolrCore core) throws IOException;
+  public abstract RefCounted<IndexWriter> getIndexWriter(SolrCore core) throws IOException;
   
   /**
    * Decrement the number of references to this state. When then number of

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java Mon Jul 16 20:08:46 2012
@@ -52,6 +52,7 @@ import org.apache.solr.schema.SchemaFiel
 import org.apache.solr.search.DocIterator;
 import org.apache.solr.search.DocList;
 import org.apache.solr.update.DirectUpdateHandler2;
+import org.apache.solr.util.RefCounted;
 
 
 import org.junit.BeforeClass;
@@ -125,9 +126,14 @@ public class BasicFunctionalityTest exte
     // test merge factor picked up
     SolrCore core = h.getCore();
 
-    IndexWriter writer = ((DirectUpdateHandler2)core.getUpdateHandler()).getSolrCoreState().getIndexWriter(core);
-    assertEquals("Mergefactor was not picked up", 8, ((LogMergePolicy)writer.getConfig().getMergePolicy()).getMergeFactor());
-
+    RefCounted<IndexWriter> iw = ((DirectUpdateHandler2) core
+        .getUpdateHandler()).getSolrCoreState().getIndexWriter(core);
+    try {
+      assertEquals("Mergefactor was not picked up", 8, ((LogMergePolicy) iw
+          .get().getConfig().getMergePolicy()).getMergeFactor());
+    } finally {
+      iw.decref();
+    }
     // test stats call
     NamedList stats = core.getStatistics();
     assertEquals("collection1", stats.get("coreName"));

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/AbstractDistributedZkTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/AbstractDistributedZkTestCase.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/AbstractDistributedZkTestCase.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/AbstractDistributedZkTestCase.java Mon Jul 16 20:08:46 2012
@@ -139,7 +139,7 @@ public abstract class AbstractDistribute
           }
         }
       }
-      if (!sawLiveRecovering || cnt == 120) {
+      if (!sawLiveRecovering || cnt == 520) {
         if (!sawLiveRecovering) {
           if (verbose) System.out.println("no one is recoverying");
         } else {

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java Mon Jul 16 20:08:46 2012
@@ -28,6 +28,7 @@ import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.update.DirectUpdateHandler2;
+import org.apache.solr.util.RefCounted;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -61,10 +62,12 @@ public class BasicZkTest extends Abstrac
     // test merge factor picked up
     SolrCore core = h.getCore();
 
-    IndexWriter writer = ((DirectUpdateHandler2)core.getUpdateHandler()).getSolrCoreState().getIndexWriter(core);
-
-    assertEquals("Mergefactor was not picked up", 8, ((LogMergePolicy)writer.getConfig().getMergePolicy()).getMergeFactor());
-    
+    RefCounted<IndexWriter> iw = ((DirectUpdateHandler2)core.getUpdateHandler()).getSolrCoreState().getIndexWriter(core);
+    try {
+      assertEquals("Mergefactor was not picked up", 8, ((LogMergePolicy)iw.get().getConfig().getMergePolicy()).getMergeFactor());
+    } finally {
+      iw.decref();
+    }
     lrf.args.put(CommonParams.VERSION, "2.2");
     assertQ("test query on empty index", request("qlkciyopsbgzyvkylsjhchghjrdf"),
         "//result[@numFound='0']");

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfig.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfig.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfig.java Mon Jul 16 20:08:46 2012
@@ -23,6 +23,7 @@ import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.handler.admin.ShowFileRequestHandler;
 import org.apache.solr.update.DirectUpdateHandler2;
 import org.apache.solr.update.SolrIndexConfig;
+import org.apache.solr.util.RefCounted;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.w3c.dom.Node;
@@ -115,8 +116,15 @@ public class TestConfig extends SolrTest
 
   @Test
   public void testTermIndexInterval() throws Exception {
-    IndexWriter writer = ((DirectUpdateHandler2)h.getCore().getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
-    int interval = writer.getConfig().getTermIndexInterval();
+    RefCounted<IndexWriter> iw = ((DirectUpdateHandler2) h.getCore()
+        .getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
+    int interval = 0;
+    try {
+      IndexWriter writer = iw.get();
+      interval = writer.getConfig().getTermIndexInterval();
+    } finally {
+      iw.decref();
+    }
     assertEquals(256, interval);
   }
 

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInject.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInject.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInject.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInject.java Mon Jul 16 20:08:46 2012
@@ -24,6 +24,7 @@ import org.apache.lucene.index.IndexWrit
 import org.apache.lucene.index.LogByteSizeMergePolicy;
 import org.apache.solr.update.DirectUpdateHandler2;
 import org.apache.solr.util.AbstractSolrTestCase;
+import org.apache.solr.util.RefCounted;
 
 public class TestPropInject extends AbstractSolrTestCase {
   @Override
@@ -37,14 +38,25 @@ public class TestPropInject extends Abst
   }
 
   public void testMergePolicy() throws Exception {
-    IndexWriter writer = ((DirectUpdateHandler2)h.getCore().getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
-    LogByteSizeMergePolicy mp = (LogByteSizeMergePolicy)writer.getConfig().getMergePolicy();
+
+    RefCounted<IndexWriter> iw = ((DirectUpdateHandler2)h.getCore().getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
+    LogByteSizeMergePolicy mp;
+    try {
+     mp = (LogByteSizeMergePolicy)iw.get().getConfig().getMergePolicy();
+    } finally {
+      iw.decref();
+    }
     assertEquals(64.0, mp.getMaxMergeMB(), 0);
   }
   
   public void testProps() throws Exception {
-    IndexWriter writer = ((DirectUpdateHandler2)h.getCore().getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
-    ConcurrentMergeScheduler cms = (ConcurrentMergeScheduler)writer.getConfig().getMergeScheduler();
+    RefCounted<IndexWriter> iw = ((DirectUpdateHandler2)h.getCore().getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
+    ConcurrentMergeScheduler cms;
+    try {
+      cms = (ConcurrentMergeScheduler)iw.get().getConfig().getMergeScheduler();
+    } finally {
+      iw.decref();
+    }
     assertEquals(2, cms.getMaxThreadCount());
   }
 }

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInjectDefaults.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInjectDefaults.java?rev=1362232&r1=1362231&r2=1362232&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInjectDefaults.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestPropInjectDefaults.java Mon Jul 16 20:08:46 2012
@@ -22,6 +22,7 @@ import org.apache.lucene.index.IndexWrit
 import org.apache.lucene.index.LogByteSizeMergePolicy;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.update.DirectUpdateHandler2;
+import org.apache.solr.util.RefCounted;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -33,15 +34,27 @@ public class TestPropInjectDefaults exte
 
   @Test
   public void testMergePolicyDefaults() throws Exception {
-    IndexWriter writer = ((DirectUpdateHandler2)h.getCore().getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
-    LogByteSizeMergePolicy mp = (LogByteSizeMergePolicy)writer.getConfig().getMergePolicy();
+    RefCounted<IndexWriter> iw = ((DirectUpdateHandler2) h.getCore()
+        .getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
+    LogByteSizeMergePolicy mp;
+    try {
+      mp = (LogByteSizeMergePolicy) iw.get().getConfig().getMergePolicy();
+    } finally {
+      iw.decref();
+    }
     assertEquals(32.0, mp.getMaxMergeMB(), 0);
   }
   
   @Test
   public void testPropsDefaults() throws Exception {
-    IndexWriter writer = ((DirectUpdateHandler2)h.getCore().getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
-    ConcurrentMergeScheduler cms = (ConcurrentMergeScheduler)writer.getConfig().getMergeScheduler();
+    RefCounted<IndexWriter> iw = ((DirectUpdateHandler2) h.getCore()
+        .getUpdateHandler()).getSolrCoreState().getIndexWriter(h.getCore());
+    ConcurrentMergeScheduler cms;
+    try {
+      cms = (ConcurrentMergeScheduler) iw.get().getConfig().getMergeScheduler();
+    } finally {
+      iw.decref();
+    }
     assertEquals(4, cms.getMaxThreadCount());
   }