diff --git a/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java b/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java index 880119b7037..820d82eeaa7 100644 --- a/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java +++ b/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java @@ -533,7 +533,7 @@ public class DirectUpdateHandler2 extends UpdateHandler implements SolrCoreState // we shouldn't close the transaction logs either, but leaving them open // means we can't delete them on windows. - if (ulog != null) ulog.close(); + if (ulog != null) ulog.close(false); return; } @@ -543,11 +543,9 @@ public class DirectUpdateHandler2 extends UpdateHandler implements SolrCoreState } // if the writer hits an exception, it's OK (and perhaps desirable) - // to not close the ulog? + // to not close the ulog. - // Closing the log currently deletes the log file. - // If this changes, we should record this as a "commit". - if (ulog != null) ulog.close(); + if (ulog != null) ulog.close(true); } finally { commitLock.unlock(); } diff --git a/solr/core/src/java/org/apache/solr/update/UpdateLog.java b/solr/core/src/java/org/apache/solr/update/UpdateLog.java index 179c9d6481e..57f3fe8fcc1 100644 --- a/solr/core/src/java/org/apache/solr/update/UpdateLog.java +++ b/solr/core/src/java/org/apache/solr/update/UpdateLog.java @@ -20,7 +20,9 @@ package org.apache.solr.update; import org.apache.lucene.util.BytesRef; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.MapSolrParams; import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.core.PluginInfo; import org.apache.solr.core.SolrCore; @@ -580,7 +582,7 @@ public class UpdateLog implements PluginInfoInitialized { } } - public void close() { + public void close(boolean committed) { synchronized (this) { try { recoveryExecutor.shutdownNow(); @@ -596,6 +598,12 @@ public class UpdateLog implements PluginInfoInitialized { prevTlog.forceClose(); } if (tlog != null) { + if (committed) { + // record a commit + CommitUpdateCommand cmd = new CommitUpdateCommand(new LocalSolrQueryRequest(uhandler.core, new ModifiableSolrParams((SolrParams)null)), false); + tlog.writeCommit(cmd); + } + tlog.deleteOnClose = false; tlog.decref(); tlog.forceClose(); diff --git a/solr/core/src/test/org/apache/solr/search/TestRecovery.java b/solr/core/src/test/org/apache/solr/search/TestRecovery.java index 2613bc062c2..b0aaaae01af 100644 --- a/solr/core/src/test/org/apache/solr/search/TestRecovery.java +++ b/solr/core/src/test/org/apache/solr/search/TestRecovery.java @@ -448,6 +448,64 @@ public class TestRecovery extends SolrTestCaseJ4 { ); } + + // make sure that log isn't needlessly replayed after a clean shutdown + @Test + public void testCleanShutdown() throws Exception { + DirectUpdateHandler2.commitOnClose = true; + final Semaphore logReplay = new Semaphore(0); + final Semaphore logReplayFinish = new Semaphore(0); + + UpdateLog.testing_logReplayHook = new Runnable() { + @Override + public void run() { + try { + assertTrue(logReplay.tryAcquire(timeout, TimeUnit.SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + + UpdateLog.testing_logReplayFinishHook = new Runnable() { + @Override + public void run() { + logReplayFinish.release(); + } + }; + + + SolrQueryRequest req = req(); + UpdateHandler uhandler = req.getCore().getUpdateHandler(); + UpdateLog ulog = uhandler.getUpdateLog(); + + try { + clearIndex(); + assertU(commit()); + + assertU(adoc("id","1", "val_i","1")); + assertU(adoc("id","2", "val_i","1")); + + // set to a high enough number so this test won't hang on a bug + logReplay.release(10); + + h.close(); + createCore(); + + // make sure the docs got committed + assertJQ(req("q","*:*"),"/response/numFound==2"); + + // make sure no replay happened + assertEquals(10, logReplay.availablePermits()); + + } finally { + DirectUpdateHandler2.commitOnClose = true; + UpdateLog.testing_logReplayHook = null; + UpdateLog.testing_logReplayFinishHook = null; + + req().close(); + } + } private void addDocs(int nDocs, int start, LinkedList versions) throws Exception {