LUCENE-6852: merge trunk
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene6852@1710430 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lucene/classification/src/java/org/apache/lucene/classification/utils/ConfusionMatrixGenerator.java b/lucene/classification/src/java/org/apache/lucene/classification/utils/ConfusionMatrixGenerator.java
index ce48d5c..78ad691 100644
--- a/lucene/classification/src/java/org/apache/lucene/classification/utils/ConfusionMatrixGenerator.java
+++ b/lucene/classification/src/java/org/apache/lucene/classification/utils/ConfusionMatrixGenerator.java
@@ -32,12 +32,10 @@
import org.apache.lucene.classification.Classifier;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.StoredDocument;
-import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
-import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.NamedThreadFactory;
@@ -152,6 +150,7 @@
/**
* get the linearized confusion matrix as a {@link Map}
+ *
* @return a {@link Map} whose keys are the correct classification answers and whose values are the actual answers'
* counts
*/
@@ -160,6 +159,61 @@
}
/**
+ * calculate precision on the given class
+ *
+ * @param klass the class to calculate the precision for
+ * @return the precision for the given class
+ */
+ public double getPrecision(String klass) {
+ Map<String, Long> classifications = linearizedMatrix.get(klass);
+ double tp = 0;
+ double fp = 0;
+ for (Map.Entry<String, Long> entry : classifications.entrySet()) {
+ if (klass.equals(entry.getKey())) {
+ tp += entry.getValue();
+ }
+ }
+ for (Map<String, Long> values : linearizedMatrix.values()) {
+ if (values.containsKey(klass)) {
+ fp += values.get(klass);
+ }
+ }
+ return tp / (tp + fp);
+ }
+
+ /**
+ * calculate recall on the given class
+ *
+ * @param klass the class to calculate the recall for
+ * @return the recall for the given class
+ */
+ public double getRecall(String klass) {
+ Map<String, Long> classifications = linearizedMatrix.get(klass);
+ double tp = 0;
+ double fn = 0;
+ for (Map.Entry<String, Long> entry : classifications.entrySet()) {
+ if (klass.equals(entry.getKey())) {
+ tp += entry.getValue();
+ } else {
+ fn += entry.getValue();
+ }
+ }
+ return tp / (tp + fn);
+ }
+
+ /**
+ * get the F-1 measure of the given class
+ *
+ * @param klass the class to calculate the F-1 measure for
+ * @return the F-1 measure for the given class
+ */
+ public double getF1Measure(String klass) {
+ double recall = getRecall(klass);
+ double precision = getPrecision(klass);
+ return 2 * precision * recall / (precision + recall);
+ }
+
+ /**
* Calculate accuracy on this confusion matrix using the formula:
* {@literal accuracy = correctly-classified / (correctly-classified + wrongly-classified)}
*
@@ -199,6 +253,7 @@
/**
* get the average classification time in milliseconds
+ *
* @return the avg classification time
*/
public double getAvgClassificationTime() {
@@ -207,6 +262,7 @@
/**
* get the no. of documents evaluated while generating this confusion matrix
+ *
* @return the no. of documents evaluated
*/
public int getNumberOfEvaluatedDocs() {
diff --git a/lucene/classification/src/test/org/apache/lucene/classification/BooleanPerceptronClassifierTest.java b/lucene/classification/src/test/org/apache/lucene/classification/BooleanPerceptronClassifierTest.java
index 4f81b2d..4b83dce 100644
--- a/lucene/classification/src/test/org/apache/lucene/classification/BooleanPerceptronClassifierTest.java
+++ b/lucene/classification/src/test/org/apache/lucene/classification/BooleanPerceptronClassifierTest.java
@@ -93,8 +93,9 @@
assertTrue("evaluation took more than 1m: " + evaluationTime / 1000 + "s", evaluationTime < 60000);
double avgClassificationTime = confusionMatrix.getAvgClassificationTime();
assertTrue(5000 > avgClassificationTime);
- double accuracy = confusionMatrix.getAccuracy();
- assertTrue(accuracy > 0d);
+ // accuracy check disabled until LUCENE-6853 is fixed
+// double accuracy = confusionMatrix.getAccuracy();
+// assertTrue(accuracy > 0d);
} finally {
leafReader.close();
}
diff --git a/lucene/classification/src/test/org/apache/lucene/classification/utils/ConfusionMatrixGeneratorTest.java b/lucene/classification/src/test/org/apache/lucene/classification/utils/ConfusionMatrixGeneratorTest.java
index 23d08fb..faae083 100644
--- a/lucene/classification/src/test/org/apache/lucene/classification/utils/ConfusionMatrixGeneratorTest.java
+++ b/lucene/classification/src/test/org/apache/lucene/classification/utils/ConfusionMatrixGeneratorTest.java
@@ -145,6 +145,12 @@
assertEquals(7, confusionMatrix.getNumberOfEvaluatedDocs());
assertTrue(confusionMatrix.getAvgClassificationTime() >= 0d);
assertTrue(confusionMatrix.getAccuracy() > 0d);
+ assertTrue(confusionMatrix.getPrecision("true") > 0d);
+ assertTrue(confusionMatrix.getPrecision("false") > 0d);
+ assertTrue(confusionMatrix.getRecall("true") > 0d);
+ assertTrue(confusionMatrix.getRecall("false") > 0d);
+ assertTrue(confusionMatrix.getF1Measure("true") > 0d);
+ assertTrue(confusionMatrix.getF1Measure("false") > 0d);
} finally {
if (reader != null) {
reader.close();
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 8d129a9..24849b1 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -291,7 +291,10 @@
* SOLR-8189: eTag calculation during HTTP Cache Validation uses unsynchronized WeakHashMap causing
threads to be stuck in runnable state. (shalin)
-
+
+* SOLR-7993: Raw json output for fields stopped working in 5.3.0 when requested fields do not include
+ the unique key field name. (Bill Bell, Ryan McKinley via shalin)
+
Optimizations
----------------------
@@ -373,6 +376,8 @@
* SOLR-8116: SearchGroupsResultTransformer tweaks (String literals, list/map initialCapacity)
(Christine Poerschke)
+* SOLR-8074: LoadAdminUIServlet directly references admin.html (Mark Miller, Upayavira)
+
================== 5.3.1 ==================
Bug Fixes
diff --git a/solr/core/src/java/org/apache/solr/response/transform/DocTransformer.java b/solr/core/src/java/org/apache/solr/response/transform/DocTransformer.java
index a1462db..374a0db 100644
--- a/solr/core/src/java/org/apache/solr/response/transform/DocTransformer.java
+++ b/solr/core/src/java/org/apache/solr/response/transform/DocTransformer.java
@@ -63,9 +63,9 @@
public abstract void transform(SolrDocument doc, int docid, float score) throws IOException;
/**
- * When a transformer needs access to fields that are not automaticaly derived from the
+ * When a transformer needs access to fields that are not automatically derived from the
* input fields names, this option lets us explicitly say the field names that we hope
- * will be in the SolrDocument. These fields will be requestd from the
+ * will be in the SolrDocument. These fields will be requested from the
* {@link SolrIndexSearcher} but may or may not be returned in the final
* {@link QueryResponseWriter}
*
diff --git a/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java b/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
index 8abb050..5e1f81a 100644
--- a/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
+++ b/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
@@ -124,6 +124,11 @@
doc.setField(display, new WriteableStringValue(val));
}
}
+
+ @Override
+ public String[] getExtraRequestFields() {
+ return new String[] {this.field};
+ }
}
public static class WriteableStringValue extends WriteableValue {
diff --git a/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java b/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java
index 98524ef..d079e4c 100644
--- a/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java
+++ b/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java
@@ -47,8 +47,9 @@
response.addHeader("X-Frame-Options", "DENY"); // security: SOLR-7966 - avoid clickjacking for admin interface
// This attribute is set by the SolrDispatchFilter
+ String admin = request.getRequestURI().substring(request.getContextPath().length());
CoreContainer cores = (CoreContainer) request.getAttribute("org.apache.solr.CoreContainer");
- InputStream in = getServletContext().getResourceAsStream("/admin.html");
+ InputStream in = getServletContext().getResourceAsStream(admin);
if(in != null && cores != null) {
try {
response.setCharacterEncoding("UTF-8");
diff --git a/solr/core/src/java/org/apache/solr/servlet/cache/HttpCacheHeaderUtil.java b/solr/core/src/java/org/apache/solr/servlet/cache/HttpCacheHeaderUtil.java
index 228a169..7c0dede 100644
--- a/solr/core/src/java/org/apache/solr/servlet/cache/HttpCacheHeaderUtil.java
+++ b/solr/core/src/java/org/apache/solr/servlet/cache/HttpCacheHeaderUtil.java
@@ -27,6 +27,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.lucene.util.WeakIdentityMap;
import org.apache.solr.common.util.SuppressForbidden;
import org.apache.solr.core.IndexDeletionPolicyWrapper;
import org.apache.solr.core.SolrCore;
@@ -56,7 +57,7 @@
*
* @see #calcEtag
*/
- private static Map<SolrCore, EtagCacheVal> etagCoreCache = Collections.synchronizedMap(new WeakHashMap<>());
+ private static WeakIdentityMap<SolrCore, EtagCacheVal> etagCoreCache = WeakIdentityMap.newConcurrentHashMap();
/** @see #etagCoreCache */
private static class EtagCacheVal {
diff --git a/solr/core/src/java/org/apache/solr/update/StreamingSolrClients.java b/solr/core/src/java/org/apache/solr/update/StreamingSolrClients.java
index 2fcea1e..1e9d6dd 100644
--- a/solr/core/src/java/org/apache/solr/update/StreamingSolrClients.java
+++ b/solr/core/src/java/org/apache/solr/update/StreamingSolrClients.java
@@ -67,6 +67,9 @@
String url = getFullUrl(req.node.getUrl());
ConcurrentUpdateSolrClient client = solrClients.get(url);
if (client == null) {
+ // NOTE: increasing to more than 1 threadCount for the client could cause updates to be reordered
+ // on a greater scale since the current behavior is to only increase the number of connections/Runners when
+ // the queue is more than half full.
client = new ConcurrentUpdateSolrClient(url, httpClient, 100, 1, updateExecutor, true) {
@Override
public void handleError(Throwable ex) {
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithKerberosAlt.java b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithKerberosAlt.java
index 99fd3b1..7e6a80a 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithKerberosAlt.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithKerberosAlt.java
@@ -29,6 +29,7 @@
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.minikdc.MiniKdc;
+import org.apache.lucene.util.Constants;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.solrj.SolrQuery;
@@ -44,6 +45,7 @@
import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.util.BadZookeeperThreadsFilter;
import org.apache.solr.util.RevertDefaultThreadHandlerRule;
+import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
@@ -87,6 +89,11 @@
new SystemPropertiesRestoreRule()).around(
new RevertDefaultThreadHandlerRule());
+ @BeforeClass
+ public static void betterNotBeJava9() {
+ assumeFalse("FIXME: SOLR-8182: This test fails under Java 9", Constants.JRE_IS_MINIMUM_JAVA9);
+ }
+
@Override
public void setUp() throws Exception {
savedLocale = KerberosTestUtil.overrideLocaleIfNotSpportedByMiniKdc();
diff --git a/solr/core/src/test/org/apache/solr/response/TestRawTransformer.java b/solr/core/src/test/org/apache/solr/response/TestRawTransformer.java
new file mode 100644
index 0000000..d8b66fd
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/response/TestRawTransformer.java
@@ -0,0 +1,71 @@
+package org.apache.solr.response;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.request.SolrQueryRequest;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Tests Raw JSON output for fields when used with and without the unique key field.
+ *
+ * See SOLR-7993
+ */
+public class TestRawTransformer extends SolrTestCaseJ4 {
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ initCore("solrconfig-doctransformers.xml", "schema.xml");
+ }
+
+ @After
+ public void cleanup() throws Exception {
+ assertU(delQ("*:*"));
+ assertU(commit());
+ }
+
+ @Test
+ public void testCustomTransformer() throws Exception {
+ // Build a simple index
+ int max = 10;
+ for (int i = 0; i < max; i++) {
+ SolrInputDocument sdoc = new SolrInputDocument();
+ sdoc.addField("id", i);
+ sdoc.addField("subject", "{poffL:[{offL:[{oGUID:\"79D5A31D-B3E4-4667-B812-09DF4336B900\",oID:\"OO73XRX\",prmryO:1,oRank:1,addTp:\"Office\",addCd:\"AA4GJ5T\",ad1:\"102 S 3rd St Ste 100\",city:\"Carson City\",st:\"MI\",zip:\"48811\",lat:43.176885,lng:-84.842919,phL:[\"(989) 584-1308\"],faxL:[\"(989) 584-6453\"]}]}]}");
+ sdoc.addField("title", "title_" + i);
+ updateJ(jsonAdd(sdoc), null);
+ }
+ assertU(commit());
+ assertQ(req("q", "*:*"), "//*[@numFound='" + max + "']");
+
+ SolrQueryRequest req = req("q", "*:*", "fl", "subject:[json]", "wt", "json");
+ String strResponse = h.query(req);
+ assertTrue("response does not contain right JSON encoding: " + strResponse,
+ strResponse.contains("\"subject\":[{poffL:[{offL:[{oGUID:\"7"));
+
+ req = req("q", "*:*", "fl", "id,subject", "wt", "json");
+ strResponse = h.query(req);
+ assertTrue("response does not contain right JSON encoding: " + strResponse,
+ strResponse.contains("subject\":[\""));
+ }
+
+}
+
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/ChaosMonkey.java b/solr/test-framework/src/java/org/apache/solr/cloud/ChaosMonkey.java
index c3ea976..083e895 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/ChaosMonkey.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/ChaosMonkey.java
@@ -535,8 +535,8 @@
DirectUpdateHandler2.commitOnClose = true;
double runtime = runTimer.getTime()/1000.0f;
- if (runtime > 30 && stops.get() == 0) {
- LuceneTestCase.fail("The Monkey ran for over 30 seconds and no jetties were stopped - this is worth investigating!");
+ if (runtime > 45 && stops.get() == 0) {
+ LuceneTestCase.fail("The Monkey ran for over 45 seconds and no jetties were stopped - this is worth investigating!");
}
}
diff --git a/solr/webapp/web/WEB-INF/web.xml b/solr/webapp/web/WEB-INF/web.xml
index 01aca18..24a27ae 100644
--- a/solr/webapp/web/WEB-INF/web.xml
+++ b/solr/webapp/web/WEB-INF/web.xml
@@ -141,7 +141,12 @@
<servlet-mapping>
<servlet-name>LoadAdminUI</servlet-name>
- <url-pattern>/admin.html</url-pattern>
+ <url-pattern>/old.html</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>LoadAdminUI</servlet-name>
+ <url-pattern>/index.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
@@ -156,7 +161,7 @@
</mime-mapping>
<welcome-file-list>
- <welcome-file>admin.html</welcome-file>
+ <welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
diff --git a/solr/webapp/web/css/angular/common.css b/solr/webapp/web/css/angular/common.css
index 41e3bca..1a3b087 100644
--- a/solr/webapp/web/css/angular/common.css
+++ b/solr/webapp/web/css/angular/common.css
@@ -755,8 +755,23 @@
top: -20px;
}
-.other-ui-link span {
+.other-ui-link span,
+.new-ui-warning span.help {
background-image: url( ../../img/ico/information-white.png );
right: 0px;
padding-left: 16px;
-}
\ No newline at end of file
+}
+
+.new-ui-warning {
+ position: absolute;
+ left: 150px;
+ top: -20px;
+ align: center;
+ color: red;
+ font-weight: bold;
+}
+.new-ui-warning a.ul {
+ color: red;
+ font-weight: bold;
+ text-decoration: underline;
+}
diff --git a/solr/webapp/web/index.html b/solr/webapp/web/index.html
index df85ef4..d64002e 100644
--- a/solr/webapp/web/index.html
+++ b/solr/webapp/web/index.html
@@ -121,8 +121,10 @@
<div class="exception">{{exception.msg}}</div>
</div>
- <div class="other-ui-link">
- <a href="/solr/">Original UI</a><a target="_blank" href="http://wiki.apache.org/solr/AngularUI"> <span class="help"></span></a>
+ <div class="new-ui-warning">
+ This is an experimental UI. Report bugs <a class="ul" target="_blank" href="http://issues.apache.org/jira/browse/SOLR">here</a>.
+ For the old UI click <a class="ul" href="/solr/old.html">here</a>
+ <a target="_blank" href="http://wiki.apache.org/solr/AngularUI"> <span class="help"></span></a>
</div>
<div id="content-wrapper">
diff --git a/solr/webapp/web/admin.html b/solr/webapp/web/old.html
similarity index 97%
rename from solr/webapp/web/admin.html
rename to solr/webapp/web/old.html
index 4f20a97..880b1c5 100644
--- a/solr/webapp/web/admin.html
+++ b/solr/webapp/web/old.html
@@ -80,7 +80,7 @@
</div>
<div class="other-ui-link">
- <a href="/solr/index.html">New UI</a><a target="_blank" href="http://wiki.apache.org/solr/AngularUI"> <span class="help"></span></a>
+ <a href="/solr/">New UI</a><a target="_blank" href="http://wiki.apache.org/solr/AngularUI"> <span class="help"></span></a>
</div>
<div id="content-wrapper">