You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2013/04/14 06:02:00 UTC
svn commit: r1467725 - in /lucene/dev/branches/branch_4x: ./ dev-tools/
lucene/ lucene/analysis/
lucene/analysis/icu/src/java/org/apache/lucene/collation/ lucene/backwards/
lucene/benchmark/ lucene/classification/ lucene/classification/src/
lucene/code...
Author: hossman
Date: Sun Apr 14 04:01:58 2013
New Revision: 1467725
URL: http://svn.apache.org/r1467725
Log:
SOLR-4629: TestReplicationHandler improvements (merge r1467723)
- new testEmptyCommits
- numFound assertion refactoring
- reduce excessive test sleeping in rQuery
- new "wait" option to make fetchindex block
- refactor core reload test to wait for the startAt time to change
Modified:
lucene/dev/branches/branch_4x/ (props changed)
lucene/dev/branches/branch_4x/dev-tools/ (props changed)
lucene/dev/branches/branch_4x/lucene/ (props changed)
lucene/dev/branches/branch_4x/lucene/BUILD.txt (props changed)
lucene/dev/branches/branch_4x/lucene/CHANGES.txt (props changed)
lucene/dev/branches/branch_4x/lucene/JRE_VERSION_MIGRATION.txt (props changed)
lucene/dev/branches/branch_4x/lucene/LICENSE.txt (props changed)
lucene/dev/branches/branch_4x/lucene/MIGRATE.txt (props changed)
lucene/dev/branches/branch_4x/lucene/NOTICE.txt (props changed)
lucene/dev/branches/branch_4x/lucene/README.txt (props changed)
lucene/dev/branches/branch_4x/lucene/SYSTEM_REQUIREMENTS.txt (props changed)
lucene/dev/branches/branch_4x/lucene/analysis/ (props changed)
lucene/dev/branches/branch_4x/lucene/analysis/icu/src/java/org/apache/lucene/collation/ICUCollationKeyFilterFactory.java (props changed)
lucene/dev/branches/branch_4x/lucene/backwards/ (props changed)
lucene/dev/branches/branch_4x/lucene/benchmark/ (props changed)
lucene/dev/branches/branch_4x/lucene/build.xml (props changed)
lucene/dev/branches/branch_4x/lucene/classification/ (props changed)
lucene/dev/branches/branch_4x/lucene/classification/build.xml (props changed)
lucene/dev/branches/branch_4x/lucene/classification/ivy.xml (props changed)
lucene/dev/branches/branch_4x/lucene/classification/src/ (props changed)
lucene/dev/branches/branch_4x/lucene/codecs/ (props changed)
lucene/dev/branches/branch_4x/lucene/common-build.xml (props changed)
lucene/dev/branches/branch_4x/lucene/core/ (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/index.40.cfs.zip (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/index.40.nocfs.zip (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/index.40.optimized.cfs.zip (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/index.40.optimized.nocfs.zip (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/TestSort.java (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/TestSortDocValues.java (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/TestTopFieldCollector.java (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/TestTotalHitCountCollector.java (props changed)
lucene/dev/branches/branch_4x/lucene/demo/ (props changed)
lucene/dev/branches/branch_4x/lucene/facet/ (props changed)
lucene/dev/branches/branch_4x/lucene/grouping/ (props changed)
lucene/dev/branches/branch_4x/lucene/highlighter/ (props changed)
lucene/dev/branches/branch_4x/lucene/ivy-settings.xml (props changed)
lucene/dev/branches/branch_4x/lucene/join/ (props changed)
lucene/dev/branches/branch_4x/lucene/licenses/ (props changed)
lucene/dev/branches/branch_4x/lucene/memory/ (props changed)
lucene/dev/branches/branch_4x/lucene/misc/ (props changed)
lucene/dev/branches/branch_4x/lucene/module-build.xml (props changed)
lucene/dev/branches/branch_4x/lucene/queries/ (props changed)
lucene/dev/branches/branch_4x/lucene/queryparser/ (props changed)
lucene/dev/branches/branch_4x/lucene/sandbox/ (props changed)
lucene/dev/branches/branch_4x/lucene/site/ (props changed)
lucene/dev/branches/branch_4x/lucene/spatial/ (props changed)
lucene/dev/branches/branch_4x/lucene/suggest/ (props changed)
lucene/dev/branches/branch_4x/lucene/test-framework/ (props changed)
lucene/dev/branches/branch_4x/lucene/tools/ (props changed)
lucene/dev/branches/branch_4x/solr/ (props changed)
lucene/dev/branches/branch_4x/solr/CHANGES.txt (props changed)
lucene/dev/branches/branch_4x/solr/LICENSE.txt (props changed)
lucene/dev/branches/branch_4x/solr/NOTICE.txt (props changed)
lucene/dev/branches/branch_4x/solr/README.txt (props changed)
lucene/dev/branches/branch_4x/solr/SYSTEM_REQUIREMENTS.txt (props changed)
lucene/dev/branches/branch_4x/solr/build.xml (props changed)
lucene/dev/branches/branch_4x/solr/cloud-dev/ (props changed)
lucene/dev/branches/branch_4x/solr/common-build.xml (props changed)
lucene/dev/branches/branch_4x/solr/contrib/ (props changed)
lucene/dev/branches/branch_4x/solr/core/ (props changed)
lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java
lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/SnapPuller.java
lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/core/TestConfig.java (props changed)
lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
lucene/dev/branches/branch_4x/solr/example/ (props changed)
lucene/dev/branches/branch_4x/solr/licenses/ (props changed)
lucene/dev/branches/branch_4x/solr/licenses/httpclient-LICENSE-ASL.txt (props changed)
lucene/dev/branches/branch_4x/solr/licenses/httpclient-NOTICE.txt (props changed)
lucene/dev/branches/branch_4x/solr/licenses/httpcore-LICENSE-ASL.txt (props changed)
lucene/dev/branches/branch_4x/solr/licenses/httpcore-NOTICE.txt (props changed)
lucene/dev/branches/branch_4x/solr/licenses/httpmime-LICENSE-ASL.txt (props changed)
lucene/dev/branches/branch_4x/solr/licenses/httpmime-NOTICE.txt (props changed)
lucene/dev/branches/branch_4x/solr/scripts/ (props changed)
lucene/dev/branches/branch_4x/solr/site/ (props changed)
lucene/dev/branches/branch_4x/solr/solrj/ (props changed)
lucene/dev/branches/branch_4x/solr/test-framework/ (props changed)
lucene/dev/branches/branch_4x/solr/webapp/ (props changed)
Modified: lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java?rev=1467725&r1=1467724&r2=1467725&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java Sun Apr 14 04:01:58 2013
@@ -143,6 +143,7 @@ public abstract class CachingDirectoryFa
+ " " + byDirectoryCache);
}
cacheValue.doneWithDir = true;
+ log.debug("Done with dir: {}", cacheValue);
if (cacheValue.refCnt == 0 && !closed) {
boolean cl = closeCacheValue(cacheValue);
if (cl) {
@@ -164,6 +165,8 @@ public abstract class CachingDirectoryFa
this.closed = true;
Collection<CacheValue> values = byDirectoryCache.values();
for (CacheValue val : values) {
+ log.debug("Closing {} - currently tracking: {}",
+ this.getClass().getSimpleName(), val);
try {
// if there are still refs out, we have to wait for them
int cnt = 0;
@@ -217,9 +220,9 @@ public abstract class CachingDirectoryFa
}
private void removeFromCache(CacheValue v) {
+ log.debug("Removing from cache: {}", v);
byDirectoryCache.remove(v.directory);
byPathCache.remove(v.path);
-
}
// be sure this is called with the this sync lock
@@ -353,6 +356,7 @@ public abstract class CachingDirectoryFa
log.info("return new directory for " + fullPath);
} else {
cacheValue.refCnt++;
+ log.debug("Reusing cached directory: {}", cacheValue);
}
return directory;
@@ -397,6 +401,7 @@ public abstract class CachingDirectoryFa
}
cacheValue.refCnt++;
+ log.debug("incRef'ed: {}", cacheValue);
}
}
@@ -521,8 +526,20 @@ public abstract class CachingDirectoryFa
return path;
}
- // for tests
- public synchronized Set<String> getPaths() {
- return byPathCache.keySet();
+ /**
+ * Test only method for inspecting the cache
+ * @return paths in the cache which have not been marked "done"
+ *
+ * @see #doneWithDirectory
+ * @lucene.internal
+ */
+ public synchronized Set<String> getLivePaths() {
+ HashSet<String> livePaths = new HashSet<String>();
+ for (CacheValue val : byPathCache.values()) {
+ if (!val.doneWithDir) {
+ livePaths.add(val.path);
+ }
+ }
+ return livePaths;
}
}
Modified: lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java?rev=1467725&r1=1467724&r2=1467725&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java Sun Apr 14 04:01:58 2013
@@ -180,12 +180,16 @@ public class ReplicationHandler extends
return;
}
final SolrParams paramsCopy = new ModifiableSolrParams(solrParams);
- new Thread() {
+ Thread puller = new Thread("explicit-fetchindex-cmd") {
@Override
public void run() {
doFetch(paramsCopy, false);
}
- }.start();
+ };
+ puller.start();
+ if (solrParams.getBool(WAIT, false)) {
+ puller.join();
+ }
rsp.add(STATUS, OK_STATUS);
} else if (command.equalsIgnoreCase(CMD_DISABLE_POLL)) {
if (snapPuller != null){
@@ -1298,4 +1302,15 @@ public class ReplicationHandler extends
public static final String NUMBER_BACKUPS_TO_KEEP_REQUEST_PARAM = "numberToKeep";
public static final String NUMBER_BACKUPS_TO_KEEP_INIT_PARAM = "maxNumberOfBackups";
+
+ /**
+ * Boolean param for tests that can be specified when using
+ * {@link #CMD_FETCH_INDEX} to force the current request to block until
+ * the fetch is complete. <b>NOTE:</b> This param is not advised for
+ * non-test code, since the the durration of the fetch for non-trivial
+ * indexes will likeley cause the request to time out.
+ *
+ * @lucene.internal
+ */
+ public static final String WAIT = "wait";
}
Modified: lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/SnapPuller.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/SnapPuller.java?rev=1467725&r1=1467724&r2=1467725&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/SnapPuller.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/SnapPuller.java Sun Apr 14 04:01:58 2013
@@ -218,6 +218,7 @@ public class SnapPuller {
return;
}
try {
+ LOG.debug("Polling for index modifications");
executorStartTime = System.currentTimeMillis();
replicationHandler.doFetch(null, false);
} catch (Exception e) {
Modified: lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java?rev=1467725&r1=1467724&r2=1467725&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java Sun Apr 14 04:01:58 2013
@@ -368,6 +368,7 @@ public class SolrDispatchFilter implemen
}
finally {
if( solrReq != null ) {
+ log.debug("Closing out SolrRequest: {}", solrReq);
solrReq.close();
}
if (core != null) {
Modified: lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java?rev=1467725&r1=1467724&r2=1467725&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java Sun Apr 14 04:01:58 2013
@@ -28,6 +28,8 @@ import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Set;
+import java.util.Date;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -49,11 +51,15 @@ import org.apache.solr.client.solrj.Solr
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
+import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.client.solrj.response.UpdateResponse;
+import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
@@ -110,14 +116,11 @@ public class TestReplicationHandler exte
}
public void clearIndexWithReplication() throws Exception {
- NamedList res = query("*:*", masterClient);
- SolrDocumentList docs = (SolrDocumentList)res.get("response");
- if (docs.getNumFound() != 0) {
+ if (numFound(query("*:*", masterClient)) != 0) {
masterClient.deleteByQuery("*:*");
masterClient.commit();
- // wait for replication to sync
- res = rQuery(0, "*:*", slaveClient);
- assertEquals(0, ((SolrDocumentList) res.get("response")).getNumFound());
+ // wait for replication to sync & verify
+ assertEquals(0, numFound(rQuery(0, "*:*", slaveClient)));
}
}
@@ -183,23 +186,27 @@ public class TestReplicationHandler exte
/** will sleep up to 30 seconds, looking for expectedDocCount */
private NamedList rQuery(int expectedDocCount, String query, SolrServer server) throws Exception {
int timeSlept = 0;
- NamedList res = null;
- SolrDocumentList docList = null;
- do {
+ NamedList res = query(query, server);
+ while (expectedDocCount != numFound(res)
+ && timeSlept < 30000) {
log.info("Waiting for " + expectedDocCount + " docs");
- res = query(query, server);
- docList = (SolrDocumentList) res.get("response");
timeSlept += 100;
Thread.sleep(100);
- } while(docList.getNumFound() != expectedDocCount && timeSlept < 30000);
+ res = query(query, server);
+ }
return res;
}
+ private long numFound(NamedList res) {
+ return ((SolrDocumentList) res.get("response")).getNumFound();
+ }
+
private NamedList<Object> getDetails(SolrServer s) throws Exception {
ModifiableSolrParams params = new ModifiableSolrParams();
params.set("command","details");
+ params.set("_trace","getDetails");
params.set("qt","/replication");
QueryRequest req = new QueryRequest(params);
@@ -220,6 +227,7 @@ public class TestReplicationHandler exte
ModifiableSolrParams params = new ModifiableSolrParams();
params.set("command","commits");
+ params.set("_trace","getCommits");
params.set("qt","/replication");
QueryRequest req = new QueryRequest(params);
@@ -235,6 +243,7 @@ public class TestReplicationHandler exte
ModifiableSolrParams params = new ModifiableSolrParams();
params.set("command","indexversion");
+ params.set("_trace","getIndexVersion");
params.set("qt","/replication");
QueryRequest req = new QueryRequest(params);
@@ -329,6 +338,56 @@ public class TestReplicationHandler exte
}
}
+ /**
+ * Verify that empty commits and/or commits with openSearcher=false
+ * on the master do not cause subsequent replication problems on the slave
+ */
+ public void testEmptyCommits() throws Exception {
+ clearIndexWithReplication();
+
+ // add a doc to master and commit
+ index(masterClient, "id", "1", "name", "empty1");
+ emptyUpdate(masterClient, "commit", "true");
+ // force replication
+ pullFromMasterToSlave();
+ // verify doc is on slave
+ rQuery(1, "name:empty1", slaveClient);
+ assertVersions(masterClient, slaveClient);
+
+ // do a completely empty commit on master and force replication
+ emptyUpdate(masterClient, "commit", "true");
+ pullFromMasterToSlave();
+
+ // add another doc and verify slave gets it
+ index(masterClient, "id", "2", "name", "empty2");
+ emptyUpdate(masterClient, "commit", "true");
+ // force replication
+ pullFromMasterToSlave();
+
+ rQuery(1, "name:empty2", slaveClient);
+ assertVersions(masterClient, slaveClient);
+
+ // add a third doc but don't open a new searcher on master
+ index(masterClient, "id", "3", "name", "empty3");
+ emptyUpdate(masterClient, "commit", "true", "openSearcher", "false");
+ pullFromMasterToSlave();
+
+ // verify slave can search the doc, but master doesn't
+ rQuery(0, "name:empty3", masterClient);
+ rQuery(1, "name:empty3", slaveClient);
+
+ // final doc with hard commit, slave and master both showing all docs
+ index(masterClient, "id", "4", "name", "empty4");
+ emptyUpdate(masterClient, "commit", "true");
+ pullFromMasterToSlave();
+
+ String q = "name:(empty1 empty2 empty3 empty4)";
+ rQuery(4, q, masterClient);
+ rQuery(4, q, slaveClient);
+ assertVersions(masterClient, slaveClient);
+
+ }
+
@Test
public void doTestReplicateAfterWrite2Slave() throws Exception {
clearIndexWithReplication();
@@ -342,9 +401,7 @@ public class TestReplicationHandler exte
masterClient.commit();
- NamedList masterQueryRsp = rQuery(nDocs, "*:*", masterClient);
- SolrDocumentList masterQueryResult = (SolrDocumentList) masterQueryRsp.get("response");
- assertEquals(nDocs, masterQueryResult.getNumFound());
+ assertEquals(nDocs, numFound(rQuery(nDocs, "*:*", masterClient)));
// Make sure that both the index version and index generation on the slave is
// higher than that of the master, just to make the test harder.
@@ -360,14 +417,8 @@ public class TestReplicationHandler exte
index(slaveClient, "id", 555, "name", "name = " + 555);
slaveClient.commit(true, true);
-
-
//this doc is added to slave so it should show an item w/ that result
- SolrDocumentList slaveQueryResult = null;
- NamedList slaveQueryRsp;
- slaveQueryRsp = rQuery(1, "id:555", slaveClient);
- slaveQueryResult = (SolrDocumentList) slaveQueryRsp.get("response");
- assertEquals(1, slaveQueryResult.getNumFound());
+ assertEquals(1, numFound(rQuery(1, "id:555", slaveClient)));
//Let's fetch the index rather than rely on the polling.
invokeReplicationCommand(masterJetty.getLocalPort(), "enablereplication");
@@ -413,12 +464,12 @@ public class TestReplicationHandler exte
NamedList masterQueryRsp = rQuery(nDocs, "*:*", masterClient);
SolrDocumentList masterQueryResult = (SolrDocumentList) masterQueryRsp.get("response");
- assertEquals(nDocs, masterQueryResult.getNumFound());
+ assertEquals(nDocs, numFound(masterQueryRsp));
//get docs from slave and check if number is equal to master
NamedList slaveQueryRsp = rQuery(nDocs, "*:*", slaveClient);
SolrDocumentList slaveQueryResult = (SolrDocumentList) slaveQueryRsp.get("response");
- assertEquals(nDocs, slaveQueryResult.getNumFound());
+ assertEquals(nDocs, numFound(slaveQueryRsp));
//compare results
String cmp = BaseDistributedSearchTestCase.compare(masterQueryResult, slaveQueryResult, 0, null);
@@ -460,9 +511,7 @@ public class TestReplicationHandler exte
index(masterClient, "id", "2000", "name", "name = " + 2000, "newname", "newname = " + 2000);
masterClient.commit();
- NamedList masterQueryRsp2 = rQuery(1, "*:*", masterClient);
- SolrDocumentList masterQueryResult2 = (SolrDocumentList) masterQueryRsp2.get("response");
- assertEquals(1, masterQueryResult2.getNumFound());
+ assertEquals(1, numFound( rQuery(1, "*:*", masterClient)));
assertVersions(masterClient, slaveClient);
@@ -493,12 +542,12 @@ public class TestReplicationHandler exte
NamedList masterQueryRsp = rQuery(nDocs, "*:*", masterClient);
SolrDocumentList masterQueryResult = (SolrDocumentList) masterQueryRsp.get("response");
- assertEquals(nDocs, masterQueryResult.getNumFound());
+ assertEquals(nDocs, numFound(masterQueryRsp));
//get docs from slave and check if number is equal to master
NamedList slaveQueryRsp = rQuery(nDocs, "*:*", slaveClient);
SolrDocumentList slaveQueryResult = (SolrDocumentList) slaveQueryRsp.get("response");
- assertEquals(nDocs, slaveQueryResult.getNumFound());
+ assertEquals(nDocs, numFound(slaveQueryRsp));
//compare results
String cmp = BaseDistributedSearchTestCase.compare(masterQueryResult, slaveQueryResult, 0, null);
@@ -511,25 +560,19 @@ public class TestReplicationHandler exte
masterClient.commit();
//get docs from master and check if number is equal to master
- masterQueryRsp = rQuery(nDocs+1, "*:*", masterClient);
- masterQueryResult = (SolrDocumentList) masterQueryRsp.get("response");
- assertEquals(nDocs+1, masterQueryResult.getNumFound());
+ assertEquals(nDocs+1, numFound(rQuery(nDocs+1, "*:*", masterClient)));
// NOTE: this test is wierd, we want to verify it DOESNT replicate...
// for now, add a sleep for this.., but the logic is wierd.
Thread.sleep(3000);
//get docs from slave and check if number is not equal to master; polling is disabled
- slaveQueryRsp = rQuery(nDocs, "*:*", slaveClient);
- slaveQueryResult = (SolrDocumentList) slaveQueryRsp.get("response");
- assertEquals(nDocs, slaveQueryResult.getNumFound());
+ assertEquals(nDocs, numFound(rQuery(nDocs, "*:*", slaveClient)));
// re-enable replication
invokeReplicationCommand(slaveJetty.getLocalPort(), "enablepoll");
- slaveQueryRsp = rQuery(nDocs+1, "*:*", slaveClient);
- slaveQueryResult = (SolrDocumentList) slaveQueryRsp.get("response");
- assertEquals(nDocs+1, slaveQueryResult.getNumFound());
+ assertEquals(nDocs+1, numFound(rQuery(nDocs+1, "*:*", slaveClient)));
}
@Test
@@ -676,14 +719,18 @@ public class TestReplicationHandler exte
if (useStraightStandardDirectory) {
useFactory(null);
}
+ final String SLAVE_SCHEMA_1 = "schema-replication1.xml";
+ final String SLAVE_SCHEMA_2 = "schema-replication2.xml";
+ String slaveSchema = SLAVE_SCHEMA_1;
+
try {
- slave
- .copyConfigFile(CONF_DIR + "solrconfig-slave1.xml", "solrconfig.xml");
+ slave.copyConfigFile(CONF_DIR +"solrconfig-slave1.xml", "solrconfig.xml");
+ slave.copyConfigFile(CONF_DIR +slaveSchema, "schema.xml");
slaveJetty.stop();
slaveJetty = createJetty(slave);
slaveClient = createNewSolrServer(slaveJetty.getLocalPort());
-
+
master.copyConfigFile(CONF_DIR + "solrconfig-master3.xml",
"solrconfig.xml");
masterJetty.stop();
@@ -700,11 +747,14 @@ public class TestReplicationHandler exte
int id = 0;
for (int x = 0; x < rounds; x++) {
- // we randomly trigger a configuration replication
- // if (random().nextBoolean()) {
- master.copyConfigFile(CONF_DIR + "schema-replication"
- + (random().nextInt(2) + 1) + ".xml", "schema.xml");
- // }
+ final boolean confCoreReload = random().nextBoolean();
+ if (confCoreReload) {
+ // toggle the schema file used
+
+ slaveSchema = slaveSchema.equals(SLAVE_SCHEMA_1) ?
+ SLAVE_SCHEMA_2 : SLAVE_SCHEMA_1;
+ master.copyConfigFile(CONF_DIR + slaveSchema, "schema.xml");
+ }
int docs = random().nextInt(maxDocs);
for (int i = 0; i < docs; i++) {
@@ -720,8 +770,12 @@ public class TestReplicationHandler exte
assertEquals(totalDocs, masterQueryResult.getNumFound());
// snappull
+ Date slaveCoreStart = watchCoreStartAt(slaveClient, 30*1000, null);
pullFromMasterToSlave();
-
+ if (confCoreReload) {
+ watchCoreStartAt(slaveClient, 30*1000, slaveCoreStart);
+ }
+
// get docs from slave and check if number is equal to master
NamedList slaveQueryRsp = rQuery(totalDocs, "*:*", slaveClient);
SolrDocumentList slaveQueryResult = (SolrDocumentList) slaveQueryRsp
@@ -761,7 +815,10 @@ public class TestReplicationHandler exte
String ddir = core.getDataDir();
CachingDirectoryFactory dirFactory = (CachingDirectoryFactory) core.getDirectoryFactory();
synchronized (dirFactory) {
- assertEquals(dirFactory.getPaths().toString(), 2, dirFactory.getPaths().size());
+ Set<String> livePaths = dirFactory.getLivePaths();
+ // one for data, one for hte index under data
+ assertEquals(livePaths.toString(), 2, livePaths.size());
+ // :TODO: assert that one of the paths is a subpath of hte other
}
if (dirFactory instanceof StandardDirectoryFactory) {
System.out.println(Arrays.asList(new File(ddir).list()));
@@ -783,15 +840,7 @@ public class TestReplicationHandler exte
private void pullFromMasterToSlave() throws MalformedURLException,
IOException {
- String masterUrl = "http://127.0.0.1:" + slaveJetty.getLocalPort() + "/solr/replication?command=fetchindex&masterUrl=";
- masterUrl += "http://127.0.0.1:" + masterJetty.getLocalPort() + "/solr/replication";
- URL url = new URL(masterUrl);
- InputStream stream = url.openStream();
- try {
- stream.close();
- } catch (IOException e) {
- //e.printStackTrace();
- }
+ pullFromTo(masterJetty, slaveJetty);
}
@Test
@@ -874,6 +923,7 @@ public class TestReplicationHandler exte
// check vs /replication?command=indexversion call
ModifiableSolrParams params = new ModifiableSolrParams();
params.set("qt", "/replication");
+ params.set("_trace", "assertVersions");
params.set("command", "indexversion");
QueryRequest req = new QueryRequest(params);
NamedList<Object> resp = client1.request(req);
@@ -910,7 +960,7 @@ public class TestReplicationHandler exte
URL url;
InputStream stream;
masterUrl = "http://127.0.0.1:" + to.getLocalPort()
- + "/solr/replication?command=fetchindex&masterUrl=";
+ + "/solr/replication?wait=true&command=fetchindex&masterUrl=";
masterUrl += "http://127.0.0.1:" + from.getLocalPort()
+ "/solr/replication";
url = new URL(masterUrl);
@@ -1102,7 +1152,6 @@ public class TestReplicationHandler exte
}
@Test
- //@Ignore("ignore while i track down the intermittent problem with this test")
public void doTestIndexAndConfigAliasReplication() throws Exception {
clearIndexWithReplication();
@@ -1130,6 +1179,7 @@ public class TestReplicationHandler exte
//clear master index
masterClient.deleteByQuery("*:*");
masterClient.commit();
+ rQuery(0, "*:*", masterClient); // sanity check w/retry
//change solrconfig on master
master.copyConfigFile(CONF_DIR + "solrconfig-master1.xml",
@@ -1157,28 +1207,33 @@ public class TestReplicationHandler exte
slaveClient.deleteByQuery("*:*");
slaveClient.commit();
+ rQuery(0, "*:*", slaveClient); // sanity check w/retry
+ // record collection1's start time on slave
+ final Date slaveStartTime = watchCoreStartAt(slaveClient, 30*1000, null);
+
//add a doc with new field and commit on master to trigger snappull from slave.
- index(masterClient, "id", "2000", "name", "name = " + 2000, "newname", "newname = " + 2000);
+ index(masterClient, "id", "2000", "name", "name = " + 2000, "newname", "n2000");
masterClient.commit();
+ rQuery(1, "newname:n2000", masterClient); // sanity check
+
+ // wait for slave to reload core by watching updated startTime
+ watchCoreStartAt(slaveClient, 30*1000, slaveStartTime);
- NamedList masterQueryRsp2 = rQuery(1, "*:*", masterClient);
+ NamedList masterQueryRsp2 = rQuery(1, "id:2000", masterClient);
SolrDocumentList masterQueryResult2 = (SolrDocumentList) masterQueryRsp2.get("response");
assertEquals(1, masterQueryResult2.getNumFound());
- NamedList slaveQueryRsp2 = rQuery(1, "*:*", slaveClient);
+ NamedList slaveQueryRsp2 = rQuery(1, "id:2000", slaveClient);
SolrDocumentList slaveQueryResult2 = (SolrDocumentList) slaveQueryRsp2.get("response");
assertEquals(1, slaveQueryResult2.getNumFound());
- // we need to wait until the core is reloaded
- rQuery(1, "*:*", slaveClient);
-
- index(slaveClient, "id", "2000", "name", "name = " + 2001, "newname", "newname = " + 2001);
+ index(slaveClient, "id", "2001", "name", "name = " + 2001, "newname", "n2001");
slaveClient.commit();
- slaveQueryRsp = rQuery(1, "*:*", slaveClient);
+ slaveQueryRsp = rQuery(1, "id:2001", slaveClient);
SolrDocument d = ((SolrDocumentList) slaveQueryRsp.get("response")).get(0);
- assertEquals("newname = 2001", (String) d.getFieldValue("newname"));
+ assertEquals("n2001", (String) d.getFieldValue("newname"));
checkForSingleIndex(masterJetty);
checkForSingleIndex(slaveJetty);
@@ -1365,6 +1420,59 @@ public class TestReplicationHandler exte
out.close();
}
+ private UpdateResponse emptyUpdate(SolrServer client, String... params)
+ throws SolrServerException, IOException {
+
+ UpdateRequest req = new UpdateRequest();
+ req.setParams(params(params));
+ return req.process(client);
+ }
+
+ /**
+ * Polls the SolrCore stats using the specified client until the "startTime"
+ * time for collection is after the specified "min". Will loop for
+ * at most "timeout" milliseconds before throwing an assertion failure.
+ *
+ * @param client The SolrServer to poll
+ * @param timeout the max milliseconds to continue polling for
+ * @param min the startTime value must exceed this value before the method will return, if null this method will return the first startTime value encountered.
+ * @return the startTime value of collection
+ */
+ private Date watchCoreStartAt(SolrServer client, final long timeout,
+ final Date min) throws InterruptedException, IOException, SolrServerException {
+ final long sleepInterval = 200;
+ long timeSlept = 0;
+
+ SolrParams p = params("action","status", "core", "collection1");
+ while (timeSlept < timeout) {
+ QueryRequest req = new QueryRequest(p);
+ req.setPath("/admin/cores");
+ try {
+ NamedList data = client.request(req);
+ for (String k : new String[] {"status","collection1"}) {
+ Object o = data.get(k);
+ assertNotNull("core status rsp missing key: " + k, o);
+ data = (NamedList) o;
+ }
+ Date startTime = (Date) data.get("startTime");
+ assertNotNull("core has null startTime", startTime);
+ if (null == min || startTime.after(min)) {
+ return startTime;
+ }
+ } catch (SolrException e) {
+ // workarround for SOLR-4668
+ if (500 != e.code()) {
+ throw e;
+ } // else server possibly from the core reload in progress...
+ }
+
+ timeSlept += sleepInterval;
+ Thread.sleep(sleepInterval);
+ }
+ fail("timed out waiting for collection1 startAt time to exceed: " + min);
+ return min; // compilation neccessity
+ }
+
private static class SolrInstance {
private String name;