mirror of
https://github.com/Alfresco/SearchServices.git
synced 2026-09-16 18:12:56 +00:00
pulling from master
This commit is contained in:
+1
-3
@@ -54,7 +54,6 @@ ENV MASTER_HOST $MASTER_HOST
|
||||
|
||||
# Set Master / Slave configuration for this Node
|
||||
RUN if [ "$ENABLE_MASTER" == "true" ] ; then \
|
||||
sed -i '/^bash.*/i echo "\nenable.master=${ENABLE_MASTER}\nenable.slave=${ENABLE_SLAVE}" >> ${DIST_DIR}/solrhome/templates/rerank/conf/solrcore.properties\n' \
|
||||
${DIST_DIR}/solr/bin/search_config_setup.sh; \
|
||||
sed -i "/^bash.*/i sed -i '/^\\\\\s*<requestHandler name=\"\\\\/replication\".*/a \
|
||||
<lst name=\"master\">\
|
||||
@@ -64,7 +63,6 @@ RUN if [ "$ENABLE_MASTER" == "true" ] ; then \
|
||||
</lst>' ${DIST_DIR}/solrhome/templates/rerank/conf/solrconfig.xml\n" ${DIST_DIR}/solr/bin/search_config_setup.sh; \
|
||||
fi
|
||||
RUN if [ "$ENABLE_SLAVE" == "true" ] ; then \
|
||||
sed -i '/^bash.*/i echo "\nenable.master=${ENABLE_MASTER}\nenable.slave=${ENABLE_SLAVE}" >> ${DIST_DIR}/solrhome/templates/rerank/conf/solrcore.properties\n' \
|
||||
${DIST_DIR}/solr/bin/search_config_setup.sh; \
|
||||
sed -i "/^bash.*/i sed -i '/^\\\\\s*<requestHandler name=\"\\\\/replication\".*/a \
|
||||
<lst name=\"slave\">\
|
||||
@@ -131,4 +129,4 @@ fi
|
||||
RUN mkdir ${DIST_DIR}/keystore \
|
||||
&& chown -R solr:solr ${DIST_DIR}/keystore
|
||||
|
||||
VOLUME ["${DIST_DIR}/keystore"]
|
||||
VOLUME ["${DIST_DIR}/keystore"]
|
||||
|
||||
+2
-4
@@ -13,10 +13,8 @@
|
||||
<properties>
|
||||
<tas.rest.api.version>6.0.1.2</tas.rest.api.version>
|
||||
<tas.cmis.api.version>6.0.0.4</tas.cmis.api.version>
|
||||
<tas.utility.version>3.0.11</tas.utility.version>
|
||||
<!-- GS V3.2-0-SNAPSHOT will have to be used for GS-IE automation tests due to the dependencies in TAS Rest API project
|
||||
This version needs to be later updated when GS V3.2-0 is released -->
|
||||
<rm.version>3.2.0-SNAPSHOT</rm.version>
|
||||
<tas.utility.version>3.0.14</tas.utility.version>
|
||||
<rm.version>3.2.0</rm.version>
|
||||
<suiteXmlFile>src/test/resources/SearchSuite.xml</suiteXmlFile>
|
||||
<test.exclude></test.exclude>
|
||||
<test.include></test.include>
|
||||
|
||||
+44
-5
@@ -29,6 +29,7 @@ import org.alfresco.utility.model.UserModel;
|
||||
import org.alfresco.utility.network.ServerHealth;
|
||||
import org.apache.chemistry.opencmis.client.api.CmisObject;
|
||||
import org.apache.chemistry.opencmis.client.api.Session;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -39,6 +40,7 @@ import org.testng.annotations.BeforeSuite;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static lombok.AccessLevel.PROTECTED;
|
||||
|
||||
/**
|
||||
@@ -85,6 +87,14 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
|
||||
protected SiteModel testSite;
|
||||
|
||||
protected static String unique_searchString;
|
||||
|
||||
protected static final String SEARCH_LANGUAGE_CMIS = "cmis";
|
||||
|
||||
protected enum SearchLanguage {
|
||||
CMIS,
|
||||
AFTS
|
||||
}
|
||||
|
||||
|
||||
@BeforeSuite(alwaysRun = true)
|
||||
public void beforeSuite() throws Exception
|
||||
@@ -399,16 +409,45 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
|
||||
* @param userQuery
|
||||
* @return
|
||||
*/
|
||||
protected SearchResponse runSearchSpellcheckQuery(String query, String userQuery)
|
||||
{
|
||||
SearchRequest searchReq = new SearchRequest();
|
||||
protected SearchResponse SearchSpellcheckQuery(UserModel user, String query, String userQuery)
|
||||
{
|
||||
UserModel searchUser = ofNullable(user).isPresent()? user: testUser;
|
||||
SearchRequest searchReq = new SearchRequest();
|
||||
RestRequestQueryModel queryReq = new RestRequestQueryModel();
|
||||
queryReq.setQuery(query);
|
||||
queryReq.setUserQuery(userQuery);
|
||||
searchReq.setQuery(queryReq);
|
||||
searchReq.setSpellcheck(new RestRequestSpellcheckModel());
|
||||
SearchResponse response = query(searchReq);
|
||||
searchReq.setSpellcheck(new org.alfresco.rest.model.RestRequestSpellcheckModel());
|
||||
SearchResponse response = queryAsUser(searchUser, queryReq);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to test if the search query works and count matches where provided
|
||||
* @param query: AFTS or cmis query string
|
||||
* @param expectedCount: Only successful response is checked, when expectedCount is null (can not be exactly specified),
|
||||
* @param setCmis: Query language is set to cmis when setCmis is true, AFTS when false
|
||||
* @return SearchResponse
|
||||
*/
|
||||
protected SearchResponse testSearchQuery(String query, Integer expectedCount, SearchLanguage queryLanguage)
|
||||
{
|
||||
RestRequestQueryModel queryModel = new RestRequestQueryModel();
|
||||
queryModel.setQuery(query);
|
||||
|
||||
if (ofNullable(queryLanguage).isPresent())
|
||||
{
|
||||
queryModel.setLanguage(queryLanguage.toString());
|
||||
}
|
||||
|
||||
SearchResponse response = queryAsUser(testUser, queryModel);
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
|
||||
if (ofNullable(expectedCount).isPresent())
|
||||
{
|
||||
restClient.onResponse().assertThat().body("list.pagination.count", Matchers.equalTo(expectedCount));
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
+25
-25
@@ -170,24 +170,24 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
waitForIndexing(file.getName(), true);
|
||||
|
||||
// Correct spelling with cm:name field
|
||||
SearchResponse response = runSearchSpellcheckQuery("cm:name:learning", "learning");
|
||||
SearchResponse response = SearchSpellcheckQuery(testUser, "cm:name:learning", "learning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNull();
|
||||
|
||||
// Correct spelling with no field
|
||||
response = runSearchSpellcheckQuery("learning", "learning");
|
||||
response = SearchSpellcheckQuery(testUser, "learning", "learning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNull();
|
||||
|
||||
// Correct spelling with a different field. Used cm:content field
|
||||
response = runSearchSpellcheckQuery("cm:content:learning", "learning");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:content:learning", "learning");
|
||||
|
||||
response.assertThat().entriesListIsEmpty();
|
||||
|
||||
// Incorrect spelling with cm:name field
|
||||
response = runSearchSpellcheckQuery("cm:name:lerning", "lerning");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:name:lerning", "lerning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -195,7 +195,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with no field
|
||||
response = runSearchSpellcheckQuery("lerning", "lerning");
|
||||
response = SearchSpellcheckQuery(testUser, "lerning", "lerning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -203,7 +203,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with a different field. Used cm:content field
|
||||
response = runSearchSpellcheckQuery("cm:content:lerning", "lerning");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:content:lerning", "lerning");
|
||||
|
||||
response.assertThat().entriesListIsEmpty();
|
||||
|
||||
@@ -220,7 +220,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
waitForContentIndexing(file3.getContent(), true);
|
||||
|
||||
// Incorrect spelling with cm:name field
|
||||
response = runSearchSpellcheckQuery("cm:name:lerning", "lerning");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:name:lerning", "lerning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -228,7 +228,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with no field
|
||||
response = runSearchSpellcheckQuery("lerning", "lerning");
|
||||
response = SearchSpellcheckQuery(testUser, "lerning", "lerning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -236,7 +236,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with cm:content field
|
||||
response = runSearchSpellcheckQuery("cm:content:lerning", "lerning");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:content:lerning", "lerning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -244,7 +244,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Correct spelling with cm:name field
|
||||
response = runSearchSpellcheckQuery("cm:name:learning", "learning");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:name:learning", "learning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -252,7 +252,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("didYouMean");
|
||||
|
||||
// Correct spelling with no field
|
||||
response = runSearchSpellcheckQuery("learning", "learning");
|
||||
response = SearchSpellcheckQuery(testUser, "learning", "learning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -260,7 +260,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("didYouMean");
|
||||
|
||||
// Correct spelling with cm:content field
|
||||
response = runSearchSpellcheckQuery("cm:content:learning", "learning");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:content:learning", "learning");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -288,13 +288,13 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
waitForContentIndexing(file2.getContent(), true);
|
||||
|
||||
// Search with field not filed in either files
|
||||
SearchResponse response = runSearchSpellcheckQuery("cm:description:eclipse", "eclipse");
|
||||
SearchResponse response = SearchSpellcheckQuery(testUser, "cm:description:eclipse", "eclipse");
|
||||
|
||||
response.assertThat().entriesListIsEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNull();
|
||||
|
||||
// Incorrect spelling with the field on a file as well
|
||||
response = runSearchSpellcheckQuery("cm:name:eclipse", "eclipse");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:name:eclipse", "eclipse");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -302,7 +302,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with no field for file1
|
||||
response = runSearchSpellcheckQuery("eclipse", "eclipse");
|
||||
response = SearchSpellcheckQuery(testUser, "eclipse", "eclipse");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -310,7 +310,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with no field for file2
|
||||
response = runSearchSpellcheckQuery("eclipses", "eclipses");
|
||||
response = SearchSpellcheckQuery(testUser, "eclipses", "eclipses");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -318,7 +318,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Search for the field only filed on file2 and not file1
|
||||
response = runSearchSpellcheckQuery("cm:title:eclipses", "eclipses");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:title:eclipses", "eclipses");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -326,13 +326,13 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Query using 3 edits (more than spellcheck works for [maxEdits<=2])
|
||||
response = runSearchSpellcheckQuery("elapssed", "elapssed");
|
||||
response = SearchSpellcheckQuery(testUser, "elapssed", "elapssed");
|
||||
|
||||
response.assertThat().entriesListIsEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNull();
|
||||
|
||||
// Query with edit on first letter (does not work with spellcheck [minPrefix=1])
|
||||
response = runSearchSpellcheckQuery("iklipse ", "iklipse ");
|
||||
response = SearchSpellcheckQuery(testUser, "iklipse ", "iklipse ");
|
||||
|
||||
response.assertThat().entriesListIsEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNull();
|
||||
@@ -354,7 +354,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
waitForContentIndexing(file.getContent(), true);
|
||||
|
||||
// Incorrect spelling with no field
|
||||
SearchResponse response = runSearchSpellcheckQuery("b00k", "b00k");
|
||||
SearchResponse response = SearchSpellcheckQuery(testUser, "b00k", "b00k");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -362,7 +362,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with the cm:name field
|
||||
response = runSearchSpellcheckQuery("cm:name:b00k", "b00k");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:name:b00k", "b00k");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -370,7 +370,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with the cm:title field
|
||||
response = runSearchSpellcheckQuery("cm:title:b00k", "b00k");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:title:b00k", "b00k");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -378,7 +378,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with the cm:description field
|
||||
response = runSearchSpellcheckQuery("cm:description:b00k", "b00k");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:description:b00k", "b00k");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -386,7 +386,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
response.getContext().getSpellCheck().assertThat().field("type").is("searchInsteadFor");
|
||||
|
||||
// Incorrect spelling with the cm:description field
|
||||
response = runSearchSpellcheckQuery("cm:content:b00k", "b00k");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:content:b00k", "b00k");
|
||||
|
||||
response.assertThat().entriesListIsNotEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNotEmpty();
|
||||
@@ -395,7 +395,7 @@ public class SearchSpellCheckTest extends AbstractSearchServicesE2ETest
|
||||
|
||||
// Incorrect spelling with the cm:author field (not a field in shared.properties
|
||||
// for spellcheck)
|
||||
response = runSearchSpellcheckQuery("cm:author:b00k", "b00k");
|
||||
response = SearchSpellcheckQuery(testUser, "cm:author:b00k", "b00k");
|
||||
|
||||
response.assertThat().entriesListIsEmpty();
|
||||
response.getContext().assertThat().field("spellCheck").isNull();
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
<solr.base.version>6.6.5</solr.base.version>
|
||||
<solr.version>${solr.base.version}-patched</solr.version>
|
||||
<solr.version>${solr.base.version}-patched.1</solr.version>
|
||||
<!-- The location to download the solr zip file from. -->
|
||||
<!-- <solr.zip>https://archive.apache.org/dist/lucene/solr/${solr.version}/solr-${solr.version}.zip</solr.zip> -->
|
||||
<!-- Solr startup scripts do not work with any Java version higher than 9 so the scripts have been patched -->
|
||||
@@ -54,6 +54,19 @@
|
||||
<showDeprecation>true</showDeprecation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
|
||||
@@ -150,8 +150,6 @@ The following table illustrates the configuration properties used by the Tracker
|
||||
|alfresco.stores|workspace://SpacesStore|The reference to a node store| | |Y|Y| | |
|
||||
|batch.count|5000|UpSert batch size (e.g. metadata docs, acls)| | |Y|Y| | |
|
||||
|alfresco.maxLiveSearchers|2|Max allowed number of active searchers|Y| |Y|Y| | |
|
||||
|enable.slave|false|Indicates if the hosting instance is a slave| | |Y|Y| | |
|
||||
|enable.master|true|Indicates if the hosting instance is a master| | |Y|Y| | |
|
||||
|shard.count|1|The total number of shards that compose the Solr infrastructure|| |Y|Y| | |
|
||||
|shard.instance|0|The unique shard identifier assigned to this instance|| |Y|Y| | |
|
||||
|shard.method|"DB_ID"|Data (Documents, ACLs) Routing criteria among shards| | |Y|Y| | |
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
<dependency>
|
||||
<groupId>com.carrotsearch.randomizedtesting</groupId>
|
||||
<artifactId>randomizedtesting-runner</artifactId>
|
||||
<version>2.7.3</version>
|
||||
<version>2.7.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -292,7 +292,7 @@
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/AnnotationWriter.*</exclude>
|
||||
<exclude>**/libs/*</exclude>
|
||||
</excludes>
|
||||
<!-- Sets the path to the file which contains the execution data. -->
|
||||
<dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
|
||||
|
||||
+747
-721
File diff suppressed because it is too large
Load Diff
-484
@@ -1,484 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.solr;
|
||||
|
||||
import org.alfresco.httpclient.AuthenticationException;
|
||||
import org.alfresco.service.cmr.repository.datatype.Duration;
|
||||
import org.alfresco.solr.client.Node;
|
||||
import org.alfresco.solr.tracker.*;
|
||||
import org.alfresco.util.CachingDateFormat;
|
||||
import org.apache.commons.codec.EncoderException;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Methods taken from AlfrescoCoreAdminHandler that deal with building reports
|
||||
*/
|
||||
public class HandlerReportBuilder {
|
||||
|
||||
/**
|
||||
* Builds AclReport
|
||||
* @param tracker
|
||||
* @param aclid
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static NamedList<Object> buildAclReport(AclTracker tracker, Long aclid) throws IOException, JSONException
|
||||
{
|
||||
AclReport aclReport = tracker.checkAcl(aclid);
|
||||
|
||||
NamedList<Object> nr = new SimpleOrderedMap<Object>();
|
||||
nr.add("Acl Id", aclReport.getAclId());
|
||||
nr.add("Acl doc in index", aclReport.getIndexAclDoc());
|
||||
if (aclReport.getIndexAclDoc() != null)
|
||||
{
|
||||
nr.add("Acl tx in Index", aclReport.getIndexAclTx());
|
||||
}
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds TxReport
|
||||
* @param trackerRegistry
|
||||
* @param srv
|
||||
* @param coreName
|
||||
* @param tracker
|
||||
* @param txid
|
||||
* @return
|
||||
* @throws AuthenticationException
|
||||
* @throws IOException
|
||||
* @throws JSONException
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public static NamedList<Object> buildTxReport(TrackerRegistry trackerRegistry, InformationServer srv, String coreName, MetadataTracker tracker, Long txid)
|
||||
throws AuthenticationException, IOException, JSONException, EncoderException
|
||||
{
|
||||
NamedList<Object> nr = new SimpleOrderedMap<Object>();
|
||||
nr.add("TXID", txid);
|
||||
nr.add("transaction", buildTrackerReport(trackerRegistry, srv, coreName, txid, txid, 0l, 0l, null, null));
|
||||
NamedList<Object> nodes = new SimpleOrderedMap<Object>();
|
||||
// add node reports ....
|
||||
List<Node> dbNodes = tracker.getFullNodesForDbTransaction(txid);
|
||||
for (Node node : dbNodes)
|
||||
{
|
||||
nodes.add("DBID " + node.getId(), buildNodeReport(tracker, node));
|
||||
}
|
||||
|
||||
nr.add("txDbNodeCount", dbNodes.size());
|
||||
nr.add("nodes", nodes);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds AclTxReport
|
||||
* @param trackerRegistry
|
||||
* @param srv
|
||||
* @param coreName
|
||||
* @param tracker
|
||||
* @param acltxid
|
||||
* @return
|
||||
* @throws AuthenticationException
|
||||
* @throws IOException
|
||||
* @throws JSONException
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public static NamedList<Object> buildAclTxReport(TrackerRegistry trackerRegistry, InformationServer srv, String coreName, AclTracker tracker, Long acltxid)
|
||||
throws AuthenticationException, IOException, JSONException, EncoderException
|
||||
{
|
||||
NamedList<Object> nr = new SimpleOrderedMap<Object>();
|
||||
nr.add("TXID", acltxid);
|
||||
nr.add("transaction", buildTrackerReport(trackerRegistry, srv, coreName, 0l, 0l, acltxid, acltxid, null, null));
|
||||
NamedList<Object> nodes = new SimpleOrderedMap<Object>();
|
||||
// add node reports ....
|
||||
List<Long> dbAclIds = tracker.getAclsForDbAclTransaction(acltxid);
|
||||
for (Long aclid : dbAclIds)
|
||||
{
|
||||
nodes.add("ACLID " + aclid, buildAclReport(tracker, aclid));
|
||||
}
|
||||
nr.add("aclTxDbAclCount", dbAclIds.size());
|
||||
nr.add("nodes", nodes);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds Node report
|
||||
* @param tracker
|
||||
* @param node
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static NamedList<Object> buildNodeReport(MetadataTracker tracker, Node node) throws IOException, JSONException
|
||||
{
|
||||
NodeReport nodeReport = tracker.checkNode(node);
|
||||
|
||||
NamedList<Object> nr = new SimpleOrderedMap<Object>();
|
||||
nr.add("Node DBID", nodeReport.getDbid());
|
||||
nr.add("DB TX", nodeReport.getDbTx());
|
||||
nr.add("DB TX status", nodeReport.getDbNodeStatus().toString());
|
||||
if (nodeReport.getIndexLeafDoc() != null)
|
||||
{
|
||||
nr.add("Leaf tx in Index", nodeReport.getIndexLeafTx());
|
||||
}
|
||||
if (nodeReport.getIndexAuxDoc() != null)
|
||||
{
|
||||
nr.add("Aux tx in Index", nodeReport.getIndexAuxTx());
|
||||
}
|
||||
nr.add("Indexed Node Doc Count", nodeReport.getIndexedNodeDocCount());
|
||||
return nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds Node Report
|
||||
* @param tracker
|
||||
* @param dbid
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static NamedList<Object> buildNodeReport(MetadataTracker tracker, Long dbid) throws IOException, JSONException
|
||||
{
|
||||
NodeReport nodeReport = tracker.checkNode(dbid);
|
||||
|
||||
NamedList<Object> nr = new SimpleOrderedMap<Object>();
|
||||
nr.add("Node DBID", nodeReport.getDbid());
|
||||
nr.add("DB TX", nodeReport.getDbTx());
|
||||
nr.add("DB TX status", nodeReport.getDbNodeStatus().toString());
|
||||
if (nodeReport.getIndexLeafDoc() != null)
|
||||
{
|
||||
nr.add("Leaf tx in Index", nodeReport.getIndexLeafTx());
|
||||
}
|
||||
if (nodeReport.getIndexAuxDoc() != null)
|
||||
{
|
||||
nr.add("Aux tx in Index", nodeReport.getIndexAuxTx());
|
||||
}
|
||||
nr.add("Indexed Node Doc Count", nodeReport.getIndexedNodeDocCount());
|
||||
return nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds Tracker report
|
||||
* @param trackerRegistry
|
||||
* @param srv
|
||||
* @param coreName
|
||||
* @param fromTx
|
||||
* @param toTx
|
||||
* @param fromAclTx
|
||||
* @param toAclTx
|
||||
* @param fromTime
|
||||
* @param toTime
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws JSONException
|
||||
* @throws AuthenticationException
|
||||
* @throws EncoderException
|
||||
*/
|
||||
public static NamedList<Object> buildTrackerReport(TrackerRegistry trackerRegistry, InformationServer srv, String coreName, Long fromTx, Long toTx, Long fromAclTx, Long toAclTx,
|
||||
Long fromTime, Long toTime) throws IOException, JSONException, AuthenticationException, EncoderException
|
||||
{
|
||||
// ACL
|
||||
AclTracker aclTracker = trackerRegistry.getTrackerForCore(coreName, AclTracker.class);
|
||||
IndexHealthReport aclReport = aclTracker.checkIndex(toTx, toAclTx, fromTime, toTime);
|
||||
NamedList<Object> ihr = new SimpleOrderedMap<Object>();
|
||||
ihr.add("Alfresco version", aclTracker.getAlfrescoVersion());
|
||||
ihr.add("DB acl transaction count", aclReport.getDbAclTransactionCount());
|
||||
ihr.add("Count of duplicated acl transactions in the index", aclReport.getDuplicatedAclTxInIndex()
|
||||
.cardinality());
|
||||
if (aclReport.getDuplicatedAclTxInIndex().cardinality() > 0)
|
||||
{
|
||||
ihr.add("First duplicate acl tx", aclReport.getDuplicatedAclTxInIndex().nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Count of acl transactions in the index but not the DB", aclReport.getAclTxInIndexButNotInDb()
|
||||
.cardinality());
|
||||
if (aclReport.getAclTxInIndexButNotInDb().cardinality() > 0)
|
||||
{
|
||||
ihr.add("First acl transaction in the index but not the DB", aclReport.getAclTxInIndexButNotInDb()
|
||||
.nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Count of missing acl transactions from the Index", aclReport.getMissingAclTxFromIndex()
|
||||
.cardinality());
|
||||
if (aclReport.getMissingAclTxFromIndex().cardinality() > 0)
|
||||
{
|
||||
ihr.add("First acl transaction missing from the Index", aclReport.getMissingAclTxFromIndex()
|
||||
.nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Index acl transaction count", aclReport.getAclTransactionDocsInIndex());
|
||||
ihr.add("Index unique acl transaction count", aclReport.getAclTransactionDocsInIndex());
|
||||
TrackerState aclState = aclTracker.getTrackerState();
|
||||
ihr.add("Last indexed change set commit time", aclState.getLastIndexedChangeSetCommitTime());
|
||||
Date lastChangeSetDate = new Date(aclState.getLastIndexedChangeSetCommitTime());
|
||||
ihr.add("Last indexed change set commit date", CachingDateFormat.getDateFormat().format(lastChangeSetDate));
|
||||
ihr.add("Last changeset id before holes", aclState.getLastIndexedChangeSetIdBeforeHoles());
|
||||
|
||||
// Metadata
|
||||
MetadataTracker metadataTracker = trackerRegistry.getTrackerForCore(coreName, MetadataTracker.class);
|
||||
IndexHealthReport metaReport = metadataTracker.checkIndex(toTx, toAclTx, fromTime, toTime);
|
||||
ihr.add("DB transaction count", metaReport.getDbTransactionCount());
|
||||
ihr.add("Count of duplicated transactions in the index", metaReport.getDuplicatedTxInIndex()
|
||||
.cardinality());
|
||||
if (metaReport.getDuplicatedTxInIndex().cardinality() > 0)
|
||||
{
|
||||
ihr.add("First duplicate", metaReport.getDuplicatedTxInIndex().nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Count of transactions in the index but not the DB", metaReport.getTxInIndexButNotInDb()
|
||||
.cardinality());
|
||||
if (metaReport.getTxInIndexButNotInDb().cardinality() > 0)
|
||||
{
|
||||
ihr.add("First transaction in the index but not the DB", metaReport.getTxInIndexButNotInDb()
|
||||
.nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Count of missing transactions from the Index", metaReport.getMissingTxFromIndex().cardinality());
|
||||
if (metaReport.getMissingTxFromIndex().cardinality() > 0)
|
||||
{
|
||||
ihr.add("First transaction missing from the Index", metaReport.getMissingTxFromIndex()
|
||||
.nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Index transaction count", metaReport.getTransactionDocsInIndex());
|
||||
ihr.add("Index unique transaction count", metaReport.getTransactionDocsInIndex());
|
||||
ihr.add("Index node count", metaReport.getLeafDocCountInIndex());
|
||||
ihr.add("Count of duplicate nodes in the index", metaReport.getDuplicatedLeafInIndex().cardinality());
|
||||
if (metaReport.getDuplicatedLeafInIndex().cardinality() > 0)
|
||||
{
|
||||
ihr.add("First duplicate node id in the index", metaReport.getDuplicatedLeafInIndex().nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Index error count", metaReport.getErrorDocCountInIndex());
|
||||
ihr.add("Count of duplicate error docs in the index", metaReport.getDuplicatedErrorInIndex()
|
||||
.cardinality());
|
||||
if (metaReport.getDuplicatedErrorInIndex().cardinality() > 0)
|
||||
{
|
||||
ihr.add("First duplicate error in the index", SolrInformationServer.PREFIX_ERROR
|
||||
+ metaReport.getDuplicatedErrorInIndex().nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Index unindexed count", metaReport.getUnindexedDocCountInIndex());
|
||||
ihr.add("Count of duplicate unindexed docs in the index", metaReport.getDuplicatedUnindexedInIndex()
|
||||
.cardinality());
|
||||
if (metaReport.getDuplicatedUnindexedInIndex().cardinality() > 0)
|
||||
{
|
||||
ihr.add("First duplicate unindexed in the index",
|
||||
metaReport.getDuplicatedUnindexedInIndex().nextSetBit(0L));
|
||||
}
|
||||
TrackerState metaState = metadataTracker.getTrackerState();
|
||||
ihr.add("Last indexed transaction commit time", metaState.getLastIndexedTxCommitTime());
|
||||
Date lastTxDate = new Date(metaState.getLastIndexedTxCommitTime());
|
||||
ihr.add("Last indexed transaction commit date", CachingDateFormat.getDateFormat().format(lastTxDate));
|
||||
ihr.add("Last TX id before holes", metaState.getLastIndexedTxIdBeforeHoles());
|
||||
|
||||
srv.addFTSStatusCounts(ihr);
|
||||
|
||||
return ihr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a core summary
|
||||
* @param cname
|
||||
* @param detail
|
||||
* @param hist
|
||||
* @param values
|
||||
* @param srv
|
||||
* @param report
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void addCoreSummary(TrackerRegistry trackerRegistry, String cname, boolean detail, boolean hist, boolean values,
|
||||
InformationServer srv, NamedList<Object> report) throws IOException
|
||||
{
|
||||
NamedList<Object> coreSummary = new SimpleOrderedMap<Object>();
|
||||
coreSummary.addAll((SimpleOrderedMap<Object>) srv.getCoreStats());
|
||||
|
||||
MetadataTracker metaTrkr = trackerRegistry.getTrackerForCore(cname, MetadataTracker.class);
|
||||
TrackerState metadataTrkrState = metaTrkr.getTrackerState();
|
||||
long lastIndexTxCommitTime = metadataTrkrState.getLastIndexedTxCommitTime();
|
||||
|
||||
long lastIndexedTxId = metadataTrkrState.getLastIndexedTxId();
|
||||
long lastTxCommitTimeOnServer = metadataTrkrState.getLastTxCommitTimeOnServer();
|
||||
long lastTxIdOnServer = metadataTrkrState.getLastTxIdOnServer();
|
||||
Date lastIndexTxCommitDate = new Date(lastIndexTxCommitTime);
|
||||
Date lastTxOnServerDate = new Date(lastTxCommitTimeOnServer);
|
||||
long transactionsToDo = lastTxIdOnServer - lastIndexedTxId;
|
||||
if (transactionsToDo < 0)
|
||||
{
|
||||
transactionsToDo = 0;
|
||||
}
|
||||
|
||||
AclTracker aclTrkr = trackerRegistry.getTrackerForCore(cname, AclTracker.class);
|
||||
TrackerState aclTrkrState = aclTrkr.getTrackerState();
|
||||
long lastIndexChangeSetCommitTime = aclTrkrState.getLastIndexedChangeSetCommitTime();
|
||||
long lastIndexedChangeSetId = aclTrkrState.getLastIndexedChangeSetId();
|
||||
long lastChangeSetCommitTimeOnServer = aclTrkrState.getLastChangeSetCommitTimeOnServer();
|
||||
long lastChangeSetIdOnServer = aclTrkrState.getLastChangeSetIdOnServer();
|
||||
Date lastIndexChangeSetCommitDate = new Date(lastIndexChangeSetCommitTime);
|
||||
Date lastChangeSetOnServerDate = new Date(lastChangeSetCommitTimeOnServer);
|
||||
long changeSetsToDo = lastChangeSetIdOnServer - lastIndexedChangeSetId;
|
||||
if (changeSetsToDo < 0)
|
||||
{
|
||||
changeSetsToDo = 0;
|
||||
}
|
||||
|
||||
long nodesToDo = 0;
|
||||
long remainingTxTimeMillis = 0;
|
||||
if (transactionsToDo > 0)
|
||||
{
|
||||
// We now use the elapsed time as seen by the single thread farming out metadata indexing
|
||||
double meanDocsPerTx = srv.getTrackerStats().getMeanDocsPerTx();
|
||||
double meanNodeElaspedIndexTime = srv.getTrackerStats().getMeanNodeElapsedIndexTime();
|
||||
nodesToDo = (long)(transactionsToDo * meanDocsPerTx);
|
||||
remainingTxTimeMillis = (long) (nodesToDo * meanNodeElaspedIndexTime);
|
||||
}
|
||||
Date now = new Date();
|
||||
Date end = new Date(now.getTime() + remainingTxTimeMillis);
|
||||
Duration remainingTx = new Duration(now, end);
|
||||
|
||||
long remainingChangeSetTimeMillis = 0;
|
||||
if (changeSetsToDo > 0)
|
||||
{
|
||||
// We now use the elapsed time as seen by the single thread farming out alc indexing
|
||||
double meanAclsPerChangeSet = srv.getTrackerStats().getMeanAclsPerChangeSet();
|
||||
double meanAclElapsedIndexTime = srv.getTrackerStats().getMeanAclElapsedIndexTime();
|
||||
remainingChangeSetTimeMillis = (long) (changeSetsToDo * meanAclsPerChangeSet * meanAclElapsedIndexTime);
|
||||
}
|
||||
now = new Date();
|
||||
end = new Date(now.getTime() + remainingChangeSetTimeMillis);
|
||||
Duration remainingChangeSet = new Duration(now, end);
|
||||
|
||||
NamedList<Object> ftsSummary = new SimpleOrderedMap<Object>();
|
||||
long remainingContentTimeMillis = 0;
|
||||
srv.addFTSStatusCounts(ftsSummary);
|
||||
long cleanCount = ((Long)ftsSummary.get("Node count with FTSStatus Clean")).longValue();
|
||||
long dirtyCount = ((Long)ftsSummary.get("Node count with FTSStatus Dirty")).longValue();
|
||||
long newCount = ((Long)ftsSummary.get("Node count with FTSStatus New")).longValue();
|
||||
long nodesInIndex = ((Long)coreSummary.get("Alfresco Nodes in Index"));
|
||||
long contentYetToSee = nodesInIndex > 0 ? nodesToDo * (cleanCount + dirtyCount + newCount)/nodesInIndex : 0;;
|
||||
if (dirtyCount + newCount + contentYetToSee > 0)
|
||||
{
|
||||
// We now use the elapsed time as seen by the single thread farming out alc indexing
|
||||
double meanContentElapsedIndexTime = srv.getTrackerStats().getMeanContentElapsedIndexTime();
|
||||
remainingContentTimeMillis = (long) ((dirtyCount + newCount + contentYetToSee) * meanContentElapsedIndexTime);
|
||||
}
|
||||
now = new Date();
|
||||
end = new Date(now.getTime() + remainingContentTimeMillis);
|
||||
Duration remainingContent = new Duration(now, end);
|
||||
coreSummary.add("FTS",ftsSummary);
|
||||
|
||||
Duration txLag = new Duration(lastIndexTxCommitDate, lastTxOnServerDate);
|
||||
if (lastIndexTxCommitDate.compareTo(lastTxOnServerDate) > 0)
|
||||
{
|
||||
txLag = new Duration();
|
||||
}
|
||||
long txLagSeconds = (lastTxCommitTimeOnServer - lastIndexTxCommitTime) / 1000;
|
||||
if (txLagSeconds < 0)
|
||||
{
|
||||
txLagSeconds = 0;
|
||||
}
|
||||
|
||||
Duration changeSetLag = new Duration(lastIndexChangeSetCommitDate, lastChangeSetOnServerDate);
|
||||
if (lastIndexChangeSetCommitDate.compareTo(lastChangeSetOnServerDate) > 0)
|
||||
{
|
||||
changeSetLag = new Duration();
|
||||
}
|
||||
long changeSetLagSeconds = (lastChangeSetCommitTimeOnServer - lastIndexChangeSetCommitTime) / 1000;
|
||||
if (txLagSeconds < 0)
|
||||
{
|
||||
txLagSeconds = 0;
|
||||
}
|
||||
|
||||
ContentTracker contentTrkr = trackerRegistry.getTrackerForCore(cname, ContentTracker.class);
|
||||
TrackerState contentTrkrState = contentTrkr.getTrackerState();
|
||||
// Leave ModelTracker out of this check, because it is common
|
||||
boolean aTrackerIsRunning = aclTrkrState.isRunning() || metadataTrkrState.isRunning()
|
||||
|| contentTrkrState.isRunning();
|
||||
coreSummary.add("Active", aTrackerIsRunning);
|
||||
|
||||
ModelTracker modelTrkr = trackerRegistry.getModelTracker();
|
||||
TrackerState modelTrkrState = modelTrkr.getTrackerState();
|
||||
coreSummary.add("ModelTracker Active", modelTrkrState.isRunning());
|
||||
coreSummary.add("ContentTracker Active", contentTrkrState.isRunning());
|
||||
coreSummary.add("MetadataTracker Active", metadataTrkrState.isRunning());
|
||||
coreSummary.add("AclTracker Active", aclTrkrState.isRunning());
|
||||
|
||||
// TX
|
||||
|
||||
coreSummary.add("Last Index TX Commit Time", lastIndexTxCommitTime);
|
||||
coreSummary.add("Last Index TX Commit Date", lastIndexTxCommitDate);
|
||||
coreSummary.add("TX Lag", txLagSeconds + " s");
|
||||
coreSummary.add("TX Duration", txLag.toString());
|
||||
coreSummary.add("Timestamp for last TX on server", lastTxCommitTimeOnServer);
|
||||
coreSummary.add("Date for last TX on server", lastTxOnServerDate);
|
||||
coreSummary.add("Id for last TX on server", lastTxIdOnServer);
|
||||
coreSummary.add("Id for last TX in index", lastIndexedTxId);
|
||||
coreSummary.add("Approx transactions remaining", transactionsToDo);
|
||||
coreSummary.add("Approx transaction indexing time remaining", remainingTx.largestComponentformattedString());
|
||||
|
||||
// Change set
|
||||
|
||||
coreSummary.add("Last Index Change Set Commit Time", lastIndexChangeSetCommitTime);
|
||||
coreSummary.add("Last Index Change Set Commit Date", lastIndexChangeSetCommitDate);
|
||||
coreSummary.add("Change Set Lag", changeSetLagSeconds + " s");
|
||||
coreSummary.add("Change Set Duration", changeSetLag.toString());
|
||||
coreSummary.add("Timestamp for last Change Set on server", lastChangeSetCommitTimeOnServer);
|
||||
coreSummary.add("Date for last Change Set on server", lastChangeSetOnServerDate);
|
||||
coreSummary.add("Id for last Change Set on server", lastChangeSetIdOnServer);
|
||||
coreSummary.add("Id for last Change Set in index", lastIndexedChangeSetId);
|
||||
coreSummary.add("Approx change sets remaining", changeSetsToDo);
|
||||
coreSummary.add("Approx change set indexing time remaining",
|
||||
remainingChangeSet.largestComponentformattedString());
|
||||
|
||||
coreSummary.add("Approx content indexing time remaining",
|
||||
remainingContent.largestComponentformattedString());
|
||||
|
||||
// Stats
|
||||
|
||||
coreSummary.add("Model sync times (ms)",
|
||||
srv.getTrackerStats().getModelTimes().getNamedList(detail, hist, values));
|
||||
coreSummary.add("Acl index time (ms)",
|
||||
srv.getTrackerStats().getAclTimes().getNamedList(detail, hist, values));
|
||||
coreSummary.add("Node index time (ms)",
|
||||
srv.getTrackerStats().getNodeTimes().getNamedList(detail, hist, values));
|
||||
coreSummary.add("Docs/Tx", srv.getTrackerStats().getTxDocs().getNamedList(detail, hist, values));
|
||||
coreSummary.add("Doc Transformation time (ms)", srv.getTrackerStats().getDocTransformationTimes()
|
||||
.getNamedList(detail, hist, values));
|
||||
|
||||
// Model
|
||||
|
||||
Map<String, Set<String>> modelErrors = srv.getModelErrors();
|
||||
if (modelErrors.size() > 0)
|
||||
{
|
||||
NamedList<Object> errorList = new SimpleOrderedMap<Object>();
|
||||
for (Map.Entry<String, Set<String>> modelNameToErrors : modelErrors.entrySet())
|
||||
{
|
||||
errorList.add(modelNameToErrors.getKey(), modelNameToErrors.getValue());
|
||||
}
|
||||
coreSummary.add("Model changes are not compatible with the existing data model and have not been applied",
|
||||
errorList);
|
||||
}
|
||||
|
||||
report.add(cname, coreSummary);
|
||||
}
|
||||
}
|
||||
+564
@@ -0,0 +1,564 @@
|
||||
/*
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.solr;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.service.cmr.repository.datatype.Duration;
|
||||
import org.alfresco.solr.client.Node;
|
||||
import org.alfresco.solr.tracker.*;
|
||||
import org.alfresco.util.CachingDateFormat;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
/**
|
||||
* Methods taken from AlfrescoCoreAdminHandler that deal with building reports
|
||||
*/
|
||||
class HandlerReportHelper
|
||||
{
|
||||
static NamedList<Object> buildAclReport(AclTracker tracker, Long aclid) throws JSONException
|
||||
{
|
||||
AclReport aclReport = tracker.checkAcl(aclid);
|
||||
|
||||
NamedList<Object> nr = new SimpleOrderedMap<>();
|
||||
nr.add("Acl Id", aclReport.getAclId());
|
||||
nr.add("Acl doc in index", aclReport.getIndexAclDoc());
|
||||
if (aclReport.getIndexAclDoc() != null)
|
||||
{
|
||||
nr.add("Acl tx in Index", aclReport.getIndexAclTx());
|
||||
}
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
static NamedList<Object> buildTxReport(TrackerRegistry trackerRegistry, InformationServer srv, String coreName, MetadataTracker tracker, Long txid) throws JSONException
|
||||
{
|
||||
NamedList<Object> nr = new SimpleOrderedMap<>();
|
||||
nr.add("TXID", txid);
|
||||
nr.add("transaction", buildTrackerReport(trackerRegistry, srv, coreName, txid, txid, 0L, 0L, null, null));
|
||||
NamedList<Object> nodes = new SimpleOrderedMap<>();
|
||||
|
||||
// add node reports ....
|
||||
List<Node> dbNodes = tracker.getFullNodesForDbTransaction(txid);
|
||||
for (Node node : dbNodes)
|
||||
{
|
||||
nodes.add("DBID " + node.getId(), buildNodeReport(tracker, node));
|
||||
}
|
||||
|
||||
nr.add("txDbNodeCount", dbNodes.size());
|
||||
nr.add("nodes", nodes);
|
||||
return nr;
|
||||
}
|
||||
|
||||
static NamedList<Object> buildAclTxReport(TrackerRegistry trackerRegistry, InformationServer srv, String coreName, AclTracker tracker, Long acltxid) throws JSONException
|
||||
{
|
||||
try {
|
||||
NamedList<Object> nr = new SimpleOrderedMap<>();
|
||||
nr.add("TXID", acltxid);
|
||||
nr.add("transaction", buildTrackerReport(trackerRegistry, srv, coreName, 0L, 0L, acltxid, acltxid, null, null));
|
||||
NamedList<Object> nodes = new SimpleOrderedMap<>();
|
||||
|
||||
// add node reports ....
|
||||
List<Long> dbAclIds = tracker.getAclsForDbAclTransaction(acltxid);
|
||||
for (Long aclid : dbAclIds) {
|
||||
nodes.add("ACLID " + aclid, buildAclReport(tracker, aclid));
|
||||
}
|
||||
nr.add("aclTxDbAclCount", dbAclIds.size());
|
||||
nr.add("nodes", nodes);
|
||||
return nr;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("", exception);
|
||||
}
|
||||
}
|
||||
|
||||
static NamedList<Object> buildNodeReport(MetadataTracker tracker, Node node) throws JSONException
|
||||
{
|
||||
NodeReport nodeReport = tracker.checkNode(node);
|
||||
|
||||
NamedList<Object> nr = new SimpleOrderedMap<>();
|
||||
nr.add("Node DBID", nodeReport.getDbid());
|
||||
nr.add("DB TX", nodeReport.getDbTx());
|
||||
nr.add("DB TX status", nodeReport.getDbNodeStatus().toString());
|
||||
if (nodeReport.getIndexLeafDoc() != null)
|
||||
{
|
||||
nr.add("Leaf tx in Index", nodeReport.getIndexLeafTx());
|
||||
}
|
||||
if (nodeReport.getIndexAuxDoc() != null)
|
||||
{
|
||||
nr.add("Aux tx in Index", nodeReport.getIndexAuxTx());
|
||||
}
|
||||
nr.add("Indexed Node Doc Count", nodeReport.getIndexedNodeDocCount());
|
||||
return nr;
|
||||
}
|
||||
|
||||
static NamedList<Object> buildNodeReport(CoreStatePublisher publisher, Long dbid) throws JSONException
|
||||
{
|
||||
NodeReport nodeReport = publisher.checkNode(dbid);
|
||||
|
||||
NamedList<Object> payload = new SimpleOrderedMap<>();
|
||||
payload.add("Node DBID", nodeReport.getDbid());
|
||||
|
||||
if (publisher.isOnMasterOrStandalone())
|
||||
{
|
||||
ofNullable(nodeReport.getDbTx()).ifPresent(value -> payload.add("DB TX", value));
|
||||
ofNullable(nodeReport.getDbNodeStatus()).map(Object::toString).ifPresent(value -> payload.add("DB TX Status", value));
|
||||
ofNullable(nodeReport.getIndexLeafTx()).ifPresent(value -> payload.add("Leaf tx in Index", value));
|
||||
ofNullable(nodeReport.getIndexAuxDoc()).ifPresent(value -> payload.add("Aux tx in Index", value));
|
||||
}
|
||||
else
|
||||
{
|
||||
payload.add("WARNING", "This response comes from a slave core and it contains minimal information about the node. " +
|
||||
"Please consider to re-submit the same request to the corresponding Master, in order to get more information.");
|
||||
}
|
||||
|
||||
ofNullable(nodeReport.getIndexedNodeDocCount()).ifPresent(value -> payload.add("Indexed Node Doc Count", value));
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds Tracker report
|
||||
*/
|
||||
static NamedList<Object> buildTrackerReport(TrackerRegistry trackerRegistry, InformationServer srv, String coreName, Long fromTx, Long toTx, Long fromAclTx, Long toAclTx,
|
||||
Long fromTime, Long toTime) throws JSONException
|
||||
{
|
||||
try
|
||||
{
|
||||
// ACL
|
||||
AclTracker aclTracker = trackerRegistry.getTrackerForCore(coreName, AclTracker.class);
|
||||
IndexHealthReport aclReport = aclTracker.checkIndex(toTx, toAclTx, fromTime, toTime);
|
||||
NamedList<Object> ihr = new SimpleOrderedMap<>();
|
||||
ihr.add("Alfresco version", aclTracker.getAlfrescoVersion());
|
||||
ihr.add("DB acl transaction count", aclReport.getDbAclTransactionCount());
|
||||
ihr.add("Count of duplicated acl transactions in the index", aclReport.getDuplicatedAclTxInIndex()
|
||||
.cardinality());
|
||||
if (aclReport.getDuplicatedAclTxInIndex().cardinality() > 0) {
|
||||
ihr.add("First duplicate acl tx", aclReport.getDuplicatedAclTxInIndex().nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Count of acl transactions in the index but not the DB", aclReport.getAclTxInIndexButNotInDb()
|
||||
.cardinality());
|
||||
if (aclReport.getAclTxInIndexButNotInDb().cardinality() > 0) {
|
||||
ihr.add("First acl transaction in the index but not the DB", aclReport.getAclTxInIndexButNotInDb()
|
||||
.nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Count of missing acl transactions from the Index", aclReport.getMissingAclTxFromIndex()
|
||||
.cardinality());
|
||||
if (aclReport.getMissingAclTxFromIndex().cardinality() > 0) {
|
||||
ihr.add("First acl transaction missing from the Index", aclReport.getMissingAclTxFromIndex()
|
||||
.nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Index acl transaction count", aclReport.getAclTransactionDocsInIndex());
|
||||
ihr.add("Index unique acl transaction count", aclReport.getAclTransactionDocsInIndex());
|
||||
TrackerState aclState = aclTracker.getTrackerState();
|
||||
ihr.add("Last indexed change set commit time", aclState.getLastIndexedChangeSetCommitTime());
|
||||
Date lastChangeSetDate = new Date(aclState.getLastIndexedChangeSetCommitTime());
|
||||
ihr.add("Last indexed change set commit date", CachingDateFormat.getDateFormat().format(lastChangeSetDate));
|
||||
ihr.add("Last changeset id before holes", aclState.getLastIndexedChangeSetIdBeforeHoles());
|
||||
|
||||
// Metadata
|
||||
MetadataTracker metadataTracker = trackerRegistry.getTrackerForCore(coreName, MetadataTracker.class);
|
||||
IndexHealthReport metaReport = metadataTracker.checkIndex(toTx, toAclTx, fromTime, toTime);
|
||||
ihr.add("DB transaction count", metaReport.getDbTransactionCount());
|
||||
ihr.add("Count of duplicated transactions in the index", metaReport.getDuplicatedTxInIndex()
|
||||
.cardinality());
|
||||
if (metaReport.getDuplicatedTxInIndex().cardinality() > 0) {
|
||||
ihr.add("First duplicate", metaReport.getDuplicatedTxInIndex().nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Count of transactions in the index but not the DB", metaReport.getTxInIndexButNotInDb()
|
||||
.cardinality());
|
||||
if (metaReport.getTxInIndexButNotInDb().cardinality() > 0) {
|
||||
ihr.add("First transaction in the index but not the DB", metaReport.getTxInIndexButNotInDb()
|
||||
.nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Count of missing transactions from the Index", metaReport.getMissingTxFromIndex().cardinality());
|
||||
if (metaReport.getMissingTxFromIndex().cardinality() > 0) {
|
||||
ihr.add("First transaction missing from the Index", metaReport.getMissingTxFromIndex()
|
||||
.nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Index transaction count", metaReport.getTransactionDocsInIndex());
|
||||
ihr.add("Index unique transaction count", metaReport.getTransactionDocsInIndex());
|
||||
ihr.add("Index node count", metaReport.getLeafDocCountInIndex());
|
||||
ihr.add("Count of duplicate nodes in the index", metaReport.getDuplicatedLeafInIndex().cardinality());
|
||||
if (metaReport.getDuplicatedLeafInIndex().cardinality() > 0) {
|
||||
ihr.add("First duplicate node id in the index", metaReport.getDuplicatedLeafInIndex().nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Index error count", metaReport.getErrorDocCountInIndex());
|
||||
ihr.add("Count of duplicate error docs in the index", metaReport.getDuplicatedErrorInIndex()
|
||||
.cardinality());
|
||||
if (metaReport.getDuplicatedErrorInIndex().cardinality() > 0) {
|
||||
ihr.add("First duplicate error in the index", SolrInformationServer.PREFIX_ERROR
|
||||
+ metaReport.getDuplicatedErrorInIndex().nextSetBit(0L));
|
||||
}
|
||||
ihr.add("Index unindexed count", metaReport.getUnindexedDocCountInIndex());
|
||||
ihr.add("Count of duplicate unindexed docs in the index", metaReport.getDuplicatedUnindexedInIndex()
|
||||
.cardinality());
|
||||
if (metaReport.getDuplicatedUnindexedInIndex().cardinality() > 0) {
|
||||
ihr.add("First duplicate unindexed in the index",
|
||||
metaReport.getDuplicatedUnindexedInIndex().nextSetBit(0L));
|
||||
}
|
||||
TrackerState metaState = metadataTracker.getTrackerState();
|
||||
ihr.add("Last indexed transaction commit time", metaState.getLastIndexedTxCommitTime());
|
||||
Date lastTxDate = new Date(metaState.getLastIndexedTxCommitTime());
|
||||
ihr.add("Last indexed transaction commit date", CachingDateFormat.getDateFormat().format(lastTxDate));
|
||||
ihr.add("Last TX id before holes", metaState.getLastIndexedTxIdBeforeHoles());
|
||||
|
||||
srv.addFTSStatusCounts(ihr);
|
||||
|
||||
return ihr;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("", exception);
|
||||
}
|
||||
}
|
||||
|
||||
static void addSlaveCoreSummary(TrackerRegistry trackerRegistry, String cname, boolean detail, boolean hist, boolean values,
|
||||
InformationServer srv, NamedList<Object> report) throws IOException
|
||||
{
|
||||
NamedList<Object> coreSummary = new SimpleOrderedMap<>();
|
||||
coreSummary.addAll((SimpleOrderedMap<Object>) srv.getCoreStats());
|
||||
|
||||
SlaveCoreStatePublisher statePublisher = trackerRegistry.getTrackerForCore(cname, SlaveCoreStatePublisher.class);
|
||||
TrackerState trackerState = statePublisher.getTrackerState();
|
||||
long lastIndexTxCommitTime = trackerState.getLastIndexedTxCommitTime();
|
||||
|
||||
long lastIndexedTxId = trackerState.getLastIndexedTxId();
|
||||
long lastTxCommitTimeOnServer = trackerState.getLastTxCommitTimeOnServer();
|
||||
long lastTxIdOnServer = trackerState.getLastTxIdOnServer();
|
||||
|
||||
Date lastIndexTxCommitDate = new Date(lastIndexTxCommitTime);
|
||||
Date lastTxOnServerDate = new Date(lastTxCommitTimeOnServer);
|
||||
long transactionsToDo = lastTxIdOnServer - lastIndexedTxId;
|
||||
if (transactionsToDo < 0)
|
||||
{
|
||||
transactionsToDo = 0;
|
||||
}
|
||||
|
||||
long nodesToDo = 0;
|
||||
long remainingTxTimeMillis = 0;
|
||||
if (transactionsToDo > 0)
|
||||
{
|
||||
// We now use the elapsed time as seen by the single thread farming out metadata indexing
|
||||
double meanDocsPerTx = srv.getTrackerStats().getMeanDocsPerTx();
|
||||
double meanNodeElaspedIndexTime = srv.getTrackerStats().getMeanNodeElapsedIndexTime();
|
||||
nodesToDo = (long)(transactionsToDo * meanDocsPerTx);
|
||||
remainingTxTimeMillis = (long) (nodesToDo * meanNodeElaspedIndexTime);
|
||||
}
|
||||
Date now = new Date();
|
||||
Date end = new Date(now.getTime() + remainingTxTimeMillis);
|
||||
Duration remainingTx = new Duration(now, end);
|
||||
|
||||
long remainingChangeSetTimeMillis = 0;
|
||||
|
||||
now = new Date();
|
||||
end = new Date(now.getTime() + remainingChangeSetTimeMillis);
|
||||
Duration remainingChangeSet = new Duration(now, end);
|
||||
|
||||
NamedList<Object> ftsSummary = new SimpleOrderedMap<>();
|
||||
long remainingContentTimeMillis = 0;
|
||||
srv.addFTSStatusCounts(ftsSummary);
|
||||
long cleanCount =
|
||||
ofNullable(ftsSummary.get("Node count with FTSStatus Clean"))
|
||||
.map(Number.class::cast)
|
||||
.map(Number::longValue)
|
||||
.orElse(0L);
|
||||
long dirtyCount =
|
||||
ofNullable(ftsSummary.get("Node count with FTSStatus Dirty"))
|
||||
.map(Number.class::cast)
|
||||
.map(Number::longValue)
|
||||
.orElse(0L);
|
||||
long newCount =
|
||||
ofNullable(ftsSummary.get("Node count with FTSStatus New"))
|
||||
.map(Number.class::cast)
|
||||
.map(Number::longValue)
|
||||
.orElse(0L);
|
||||
|
||||
long nodesInIndex =
|
||||
ofNullable(coreSummary.get("Alfresco Nodes in Index"))
|
||||
.map(Number.class::cast)
|
||||
.map(Number::longValue)
|
||||
.orElse(0L);
|
||||
|
||||
long contentYetToSee = nodesInIndex > 0 ? nodesToDo * (cleanCount + dirtyCount + newCount)/nodesInIndex : 0;
|
||||
if (dirtyCount + newCount + contentYetToSee > 0)
|
||||
{
|
||||
// We now use the elapsed time as seen by the single thread farming out alc indexing
|
||||
double meanContentElapsedIndexTime = srv.getTrackerStats().getMeanContentElapsedIndexTime();
|
||||
remainingContentTimeMillis = (long) ((dirtyCount + newCount + contentYetToSee) * meanContentElapsedIndexTime);
|
||||
}
|
||||
now = new Date();
|
||||
end = new Date(now.getTime() + remainingContentTimeMillis);
|
||||
Duration remainingContent = new Duration(now, end);
|
||||
coreSummary.add("FTS",ftsSummary);
|
||||
|
||||
Duration txLag = new Duration(lastIndexTxCommitDate, lastTxOnServerDate);
|
||||
if (lastIndexTxCommitDate.compareTo(lastTxOnServerDate) > 0)
|
||||
{
|
||||
txLag = new Duration();
|
||||
}
|
||||
long txLagSeconds = (lastTxCommitTimeOnServer - lastIndexTxCommitTime) / 1000;
|
||||
if (txLagSeconds < 0)
|
||||
{
|
||||
txLagSeconds = 0;
|
||||
}
|
||||
|
||||
ModelTracker modelTrkr = trackerRegistry.getModelTracker();
|
||||
TrackerState modelTrkrState = modelTrkr.getTrackerState();
|
||||
coreSummary.add("ModelTracker Active", modelTrkrState.isRunning());
|
||||
coreSummary.add("NodeState Publisher Active", trackerState.isRunning());
|
||||
|
||||
// TX
|
||||
|
||||
coreSummary.add("Last Index TX Commit Time", lastIndexTxCommitTime);
|
||||
coreSummary.add("Last Index TX Commit Date", lastIndexTxCommitDate);
|
||||
coreSummary.add("TX Lag", txLagSeconds + " s");
|
||||
coreSummary.add("TX Duration", txLag.toString());
|
||||
coreSummary.add("Timestamp for last TX on server", lastTxCommitTimeOnServer);
|
||||
coreSummary.add("Date for last TX on server", lastTxOnServerDate);
|
||||
coreSummary.add("Id for last TX on server", lastTxIdOnServer);
|
||||
coreSummary.add("Id for last TX in index", lastIndexedTxId);
|
||||
coreSummary.add("Approx transactions remaining", transactionsToDo);
|
||||
coreSummary.add("Approx transaction indexing time remaining", remainingTx.largestComponentformattedString());
|
||||
// Stats
|
||||
|
||||
coreSummary.add("Model sync times (ms)", srv.getTrackerStats().getModelTimes().getNamedList(detail, hist, values));
|
||||
coreSummary.add("Docs/Tx", srv.getTrackerStats().getTxDocs().getNamedList(detail, hist, values));
|
||||
|
||||
// Model
|
||||
|
||||
Map<String, Set<String>> modelErrors = srv.getModelErrors();
|
||||
if (modelErrors.size() > 0)
|
||||
{
|
||||
NamedList<Object> errorList = new SimpleOrderedMap<>();
|
||||
for (Map.Entry<String, Set<String>> modelNameToErrors : modelErrors.entrySet())
|
||||
{
|
||||
errorList.add(modelNameToErrors.getKey(), modelNameToErrors.getValue());
|
||||
}
|
||||
coreSummary.add("Model changes are not compatible with the existing data model and have not been applied", errorList);
|
||||
}
|
||||
|
||||
report.add(cname, coreSummary);
|
||||
}
|
||||
|
||||
static void addMasterOrStandaloneCoreSummary(TrackerRegistry trackerRegistry, String cname, boolean detail, boolean hist, boolean values,
|
||||
InformationServer srv, NamedList<Object> report) throws IOException
|
||||
{
|
||||
NamedList<Object> coreSummary = new SimpleOrderedMap<>();
|
||||
coreSummary.addAll((SimpleOrderedMap<Object>) srv.getCoreStats());
|
||||
|
||||
MetadataTracker metaTrkr = trackerRegistry.getTrackerForCore(cname, MetadataTracker.class);
|
||||
TrackerState metadataTrkrState = metaTrkr.getTrackerState();
|
||||
long lastIndexTxCommitTime = metadataTrkrState.getLastIndexedTxCommitTime();
|
||||
|
||||
long lastIndexedTxId = metadataTrkrState.getLastIndexedTxId();
|
||||
long lastTxCommitTimeOnServer = metadataTrkrState.getLastTxCommitTimeOnServer();
|
||||
long lastTxIdOnServer = metadataTrkrState.getLastTxIdOnServer();
|
||||
Date lastIndexTxCommitDate = new Date(lastIndexTxCommitTime);
|
||||
Date lastTxOnServerDate = new Date(lastTxCommitTimeOnServer);
|
||||
long transactionsToDo = lastTxIdOnServer - lastIndexedTxId;
|
||||
if (transactionsToDo < 0)
|
||||
{
|
||||
transactionsToDo = 0;
|
||||
}
|
||||
|
||||
AclTracker aclTrkr = trackerRegistry.getTrackerForCore(cname, AclTracker.class);
|
||||
TrackerState aclTrkrState = aclTrkr.getTrackerState();
|
||||
long lastIndexChangeSetCommitTime = aclTrkrState.getLastIndexedChangeSetCommitTime();
|
||||
long lastIndexedChangeSetId = aclTrkrState.getLastIndexedChangeSetId();
|
||||
long lastChangeSetCommitTimeOnServer = aclTrkrState.getLastChangeSetCommitTimeOnServer();
|
||||
long lastChangeSetIdOnServer = aclTrkrState.getLastChangeSetIdOnServer();
|
||||
Date lastIndexChangeSetCommitDate = new Date(lastIndexChangeSetCommitTime);
|
||||
Date lastChangeSetOnServerDate = new Date(lastChangeSetCommitTimeOnServer);
|
||||
long changeSetsToDo = lastChangeSetIdOnServer - lastIndexedChangeSetId;
|
||||
if (changeSetsToDo < 0)
|
||||
{
|
||||
changeSetsToDo = 0;
|
||||
}
|
||||
|
||||
long nodesToDo = 0;
|
||||
long remainingTxTimeMillis = 0;
|
||||
if (transactionsToDo > 0)
|
||||
{
|
||||
// We now use the elapsed time as seen by the single thread farming out metadata indexing
|
||||
double meanDocsPerTx = srv.getTrackerStats().getMeanDocsPerTx();
|
||||
double meanNodeElaspedIndexTime = srv.getTrackerStats().getMeanNodeElapsedIndexTime();
|
||||
nodesToDo = (long)(transactionsToDo * meanDocsPerTx);
|
||||
remainingTxTimeMillis = (long) (nodesToDo * meanNodeElaspedIndexTime);
|
||||
}
|
||||
Date now = new Date();
|
||||
Date end = new Date(now.getTime() + remainingTxTimeMillis);
|
||||
Duration remainingTx = new Duration(now, end);
|
||||
|
||||
long remainingChangeSetTimeMillis = 0;
|
||||
if (changeSetsToDo > 0)
|
||||
{
|
||||
// We now use the elapsed time as seen by the single thread farming out alc indexing
|
||||
double meanAclsPerChangeSet = srv.getTrackerStats().getMeanAclsPerChangeSet();
|
||||
double meanAclElapsedIndexTime = srv.getTrackerStats().getMeanAclElapsedIndexTime();
|
||||
remainingChangeSetTimeMillis = (long) (changeSetsToDo * meanAclsPerChangeSet * meanAclElapsedIndexTime);
|
||||
}
|
||||
now = new Date();
|
||||
end = new Date(now.getTime() + remainingChangeSetTimeMillis);
|
||||
Duration remainingChangeSet = new Duration(now, end);
|
||||
|
||||
NamedList<Object> ftsSummary = new SimpleOrderedMap<>();
|
||||
long remainingContentTimeMillis = 0;
|
||||
srv.addFTSStatusCounts(ftsSummary);
|
||||
long cleanCount =
|
||||
ofNullable(ftsSummary.get("Node count with FTSStatus Clean"))
|
||||
.map(Number.class::cast)
|
||||
.map(Number::longValue)
|
||||
.orElse(0L);
|
||||
long dirtyCount =
|
||||
ofNullable(ftsSummary.get("Node count with FTSStatus Dirty"))
|
||||
.map(Number.class::cast)
|
||||
.map(Number::longValue)
|
||||
.orElse(0L);
|
||||
long newCount =
|
||||
ofNullable(ftsSummary.get("Node count with FTSStatus New"))
|
||||
.map(Number.class::cast)
|
||||
.map(Number::longValue)
|
||||
.orElse(0L);
|
||||
|
||||
long nodesInIndex =
|
||||
ofNullable(coreSummary.get("Alfresco Nodes in Index"))
|
||||
.map(Number.class::cast)
|
||||
.map(Number::longValue)
|
||||
.orElse(0L);
|
||||
|
||||
long contentYetToSee = nodesInIndex > 0 ? nodesToDo * (cleanCount + dirtyCount + newCount)/nodesInIndex : 0;
|
||||
if (dirtyCount + newCount + contentYetToSee > 0)
|
||||
{
|
||||
// We now use the elapsed time as seen by the single thread farming out alc indexing
|
||||
double meanContentElapsedIndexTime = srv.getTrackerStats().getMeanContentElapsedIndexTime();
|
||||
remainingContentTimeMillis = (long) ((dirtyCount + newCount + contentYetToSee) * meanContentElapsedIndexTime);
|
||||
}
|
||||
now = new Date();
|
||||
end = new Date(now.getTime() + remainingContentTimeMillis);
|
||||
Duration remainingContent = new Duration(now, end);
|
||||
coreSummary.add("FTS",ftsSummary);
|
||||
|
||||
Duration txLag = new Duration(lastIndexTxCommitDate, lastTxOnServerDate);
|
||||
if (lastIndexTxCommitDate.compareTo(lastTxOnServerDate) > 0)
|
||||
{
|
||||
txLag = new Duration();
|
||||
}
|
||||
long txLagSeconds = (lastTxCommitTimeOnServer - lastIndexTxCommitTime) / 1000;
|
||||
if (txLagSeconds < 0)
|
||||
{
|
||||
txLagSeconds = 0;
|
||||
}
|
||||
|
||||
Duration changeSetLag = new Duration(lastIndexChangeSetCommitDate, lastChangeSetOnServerDate);
|
||||
if (lastIndexChangeSetCommitDate.compareTo(lastChangeSetOnServerDate) > 0)
|
||||
{
|
||||
changeSetLag = new Duration();
|
||||
}
|
||||
long changeSetLagSeconds = (lastChangeSetCommitTimeOnServer - lastIndexChangeSetCommitTime) / 1000;
|
||||
if (txLagSeconds < 0)
|
||||
{
|
||||
txLagSeconds = 0;
|
||||
}
|
||||
|
||||
ContentTracker contentTrkr = trackerRegistry.getTrackerForCore(cname, ContentTracker.class);
|
||||
TrackerState contentTrkrState = contentTrkr.getTrackerState();
|
||||
// Leave ModelTracker out of this check, because it is common
|
||||
boolean aTrackerIsRunning = aclTrkrState.isRunning() || metadataTrkrState.isRunning()
|
||||
|| contentTrkrState.isRunning();
|
||||
coreSummary.add("Active", aTrackerIsRunning);
|
||||
|
||||
ModelTracker modelTrkr = trackerRegistry.getModelTracker();
|
||||
TrackerState modelTrkrState = modelTrkr.getTrackerState();
|
||||
coreSummary.add("ModelTracker Active", modelTrkrState.isRunning());
|
||||
coreSummary.add("ContentTracker Active", contentTrkrState.isRunning());
|
||||
coreSummary.add("MetadataTracker Active", metadataTrkrState.isRunning());
|
||||
coreSummary.add("AclTracker Active", aclTrkrState.isRunning());
|
||||
|
||||
// TX
|
||||
|
||||
coreSummary.add("Last Index TX Commit Time", lastIndexTxCommitTime);
|
||||
coreSummary.add("Last Index TX Commit Date", lastIndexTxCommitDate);
|
||||
coreSummary.add("TX Lag", txLagSeconds + " s");
|
||||
coreSummary.add("TX Duration", txLag.toString());
|
||||
coreSummary.add("Timestamp for last TX on server", lastTxCommitTimeOnServer);
|
||||
coreSummary.add("Date for last TX on server", lastTxOnServerDate);
|
||||
coreSummary.add("Id for last TX on server", lastTxIdOnServer);
|
||||
coreSummary.add("Id for last TX in index", lastIndexedTxId);
|
||||
coreSummary.add("Approx transactions remaining", transactionsToDo);
|
||||
coreSummary.add("Approx transaction indexing time remaining", remainingTx.largestComponentformattedString());
|
||||
|
||||
// Change set
|
||||
|
||||
coreSummary.add("Last Index Change Set Commit Time", lastIndexChangeSetCommitTime);
|
||||
coreSummary.add("Last Index Change Set Commit Date", lastIndexChangeSetCommitDate);
|
||||
coreSummary.add("Change Set Lag", changeSetLagSeconds + " s");
|
||||
coreSummary.add("Change Set Duration", changeSetLag.toString());
|
||||
coreSummary.add("Timestamp for last Change Set on server", lastChangeSetCommitTimeOnServer);
|
||||
coreSummary.add("Date for last Change Set on server", lastChangeSetOnServerDate);
|
||||
coreSummary.add("Id for last Change Set on server", lastChangeSetIdOnServer);
|
||||
coreSummary.add("Id for last Change Set in index", lastIndexedChangeSetId);
|
||||
coreSummary.add("Approx change sets remaining", changeSetsToDo);
|
||||
coreSummary.add("Approx change set indexing time remaining",
|
||||
remainingChangeSet.largestComponentformattedString());
|
||||
|
||||
coreSummary.add("Approx content indexing time remaining",
|
||||
remainingContent.largestComponentformattedString());
|
||||
|
||||
// Stats
|
||||
|
||||
coreSummary.add("Model sync times (ms)",
|
||||
srv.getTrackerStats().getModelTimes().getNamedList(detail, hist, values));
|
||||
coreSummary.add("Acl index time (ms)",
|
||||
srv.getTrackerStats().getAclTimes().getNamedList(detail, hist, values));
|
||||
coreSummary.add("Node index time (ms)",
|
||||
srv.getTrackerStats().getNodeTimes().getNamedList(detail, hist, values));
|
||||
coreSummary.add("Docs/Tx", srv.getTrackerStats().getTxDocs().getNamedList(detail, hist, values));
|
||||
coreSummary.add("Doc Transformation time (ms)", srv.getTrackerStats().getDocTransformationTimes()
|
||||
.getNamedList(detail, hist, values));
|
||||
|
||||
// Model
|
||||
|
||||
Map<String, Set<String>> modelErrors = srv.getModelErrors();
|
||||
if (modelErrors.size() > 0)
|
||||
{
|
||||
NamedList<Object> errorList = new SimpleOrderedMap<>();
|
||||
for (Map.Entry<String, Set<String>> modelNameToErrors : modelErrors.entrySet())
|
||||
{
|
||||
errorList.add(modelNameToErrors.getKey(), modelNameToErrors.getValue());
|
||||
}
|
||||
coreSummary.add("Model changes are not compatible with the existing data model and have not been applied",
|
||||
errorList);
|
||||
}
|
||||
|
||||
report.add(cname, coreSummary);
|
||||
}
|
||||
}
|
||||
+11
-1
@@ -40,6 +40,8 @@ import org.apache.solr.handler.component.ResponseBuilder;
|
||||
import org.apache.solr.handler.component.SearchComponent;
|
||||
import org.apache.solr.handler.component.ShardRequest;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
@@ -49,6 +51,8 @@ import org.apache.solr.request.SolrQueryRequest;
|
||||
*/
|
||||
public class RewriteFacetParametersComponent extends SearchComponent
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(RewriteFacetParametersComponent.class);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.solr.handler.component.SearchComponent#prepare(org.apache.solr.handler.component.ResponseBuilder)
|
||||
*/
|
||||
@@ -439,7 +443,13 @@ public class RewriteFacetParametersComponent extends SearchComponent
|
||||
Map<String, String> fieldMappings, SolrQueryRequest req)
|
||||
{
|
||||
String shardPurpose = req.getParams().get(ShardParams.SHARDS_PURPOSE);
|
||||
boolean isRefinementRequest = (shardPurpose!=null)?(shardPurpose.equals(String.valueOf(ShardRequest.PURPOSE_REFINE_FACETS))) || (shardPurpose.equals(String.valueOf(ShardRequest.PURPOSE_REFINE_PIVOT_FACETS))):false;
|
||||
boolean isRefinementRequest = false;
|
||||
//Fix for https://issues.alfresco.com/jira/browse/MNT-21015
|
||||
if (shardPurpose != null) {
|
||||
int shardPurposeCode = Integer.parseInt(shardPurpose);
|
||||
log.debug("ShardPurpose: " + shardPurpose);
|
||||
isRefinementRequest = ((shardPurposeCode & ShardRequest.PURPOSE_REFINE_FACETS) != 0) || ((shardPurposeCode & ShardRequest.PURPOSE_REFINE_PIVOT_FACETS) != 0);
|
||||
}
|
||||
String[] facetFieldsOrig = params.getParams(paramName);
|
||||
List<String> facetFieldList = new ArrayList<>();
|
||||
if(facetFieldsOrig != null)
|
||||
|
||||
+402
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2019 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -16,31 +16,423 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.solr.lifecycle;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService;
|
||||
import org.alfresco.solr.AlfrescoCoreAdminHandler;
|
||||
import org.alfresco.solr.AlfrescoSolrDataModel;
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.SolrKeyResourceLoader;
|
||||
import org.alfresco.solr.client.SOLRAPIClient;
|
||||
import org.alfresco.solr.client.SOLRAPIClientFactory;
|
||||
import org.alfresco.solr.content.SolrContentStore;
|
||||
import org.alfresco.solr.tracker.AclTracker;
|
||||
import org.alfresco.solr.tracker.CascadeTracker;
|
||||
import org.alfresco.solr.tracker.CommitTracker;
|
||||
import org.alfresco.solr.tracker.ContentTracker;
|
||||
import org.alfresco.solr.tracker.MetadataTracker;
|
||||
import org.alfresco.solr.tracker.ModelTracker;
|
||||
import org.alfresco.solr.tracker.SlaveCoreStatePublisher;
|
||||
import org.alfresco.solr.tracker.SolrTrackerScheduler;
|
||||
import org.alfresco.solr.tracker.Tracker;
|
||||
import org.alfresco.solr.tracker.TrackerRegistry;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.StrUtils;
|
||||
import org.apache.solr.core.AbstractSolrEventListener;
|
||||
import org.apache.solr.core.CloseHook;
|
||||
import org.apache.solr.core.CoreContainer;
|
||||
import org.apache.solr.core.CoreDescriptorDecorator;
|
||||
import org.apache.solr.core.PluginInfo;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
import org.apache.solr.handler.ReplicationHandler;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Listens for the first searcher to be created for a core and registers the trackers
|
||||
* Listeners for *FIRST SEARCHER* events in order to prepare and register the SolrContentStore and the Tracking Subsystem.
|
||||
*
|
||||
* @author Gethin James
|
||||
* @author Andrea Gazzarini
|
||||
*/
|
||||
public class SolrCoreLoadListener extends AbstractSolrEventListener {
|
||||
public class SolrCoreLoadListener extends AbstractSolrEventListener
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SolrCoreLoadListener.class);
|
||||
|
||||
public SolrCoreLoadListener(SolrCore core) {
|
||||
/**
|
||||
* Builds a new listener instance with the given {@link SolrCore} (event source).
|
||||
*
|
||||
* @param core the {@link SolrCore} instance representing the event source of this listener.
|
||||
*/
|
||||
public SolrCoreLoadListener(SolrCore core)
|
||||
{
|
||||
super(core);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {
|
||||
CoreContainer coreContainer = getCore().getCoreContainer();
|
||||
AlfrescoCoreAdminHandler coreAdminHandler = (AlfrescoCoreAdminHandler) coreContainer.getMultiCoreHandler();
|
||||
public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher)
|
||||
{
|
||||
if (getCore().isReloaded())
|
||||
{
|
||||
LOGGER.info("Solr Core {}, instance {} has been reloaded. " +
|
||||
"The previous tracking subsystem will be stopped and another set of trackers will be registered on this new instance.",
|
||||
getCore().getName(),
|
||||
getCore().hashCode());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.info("Solr Core {}, instance {}, has been registered for the first time.",
|
||||
getCore().getName(),
|
||||
getCore().hashCode());
|
||||
}
|
||||
|
||||
SolrCoreLoadRegistration.registerForCore(coreAdminHandler, coreContainer, getCore(), getCore().getName());
|
||||
CoreContainer coreContainer = getCore().getCoreContainer();
|
||||
AlfrescoCoreAdminHandler admin = (AlfrescoCoreAdminHandler) coreContainer.getMultiCoreHandler();
|
||||
SolrCore core = getCore();
|
||||
|
||||
TrackerRegistry trackerRegistry = admin.getTrackerRegistry();
|
||||
Properties coreProperties = new CoreDescriptorDecorator(core.getCoreDescriptor()).getProperties();
|
||||
|
||||
SolrResourceLoader loader = core.getLatestSchema().getResourceLoader();
|
||||
SolrKeyResourceLoader keyResourceLoader = new SolrKeyResourceLoader(loader);
|
||||
SOLRAPIClientFactory clientFactory = new SOLRAPIClientFactory();
|
||||
SOLRAPIClient repositoryClient =
|
||||
clientFactory.getSOLRAPIClient(coreProperties, keyResourceLoader,
|
||||
AlfrescoSolrDataModel.getInstance().getDictionaryService(CMISStrictDictionaryService.DEFAULT),
|
||||
AlfrescoSolrDataModel.getInstance().getNamespaceDAO());
|
||||
|
||||
SolrContentStore contentStore = new SolrContentStore(coreContainer.getSolrHome());
|
||||
SolrInformationServer informationServer = new SolrInformationServer(admin, core, repositoryClient, contentStore);
|
||||
coreProperties.putAll(informationServer.getProps());
|
||||
admin.getInformationServers().put(core.getName(), informationServer);
|
||||
|
||||
final SolrTrackerScheduler scheduler = admin.getScheduler();
|
||||
|
||||
// Prevents other threads from registering the ModelTracker at the same time
|
||||
// Create model tracker and load all the persisted models
|
||||
synchronized(SolrCoreLoadListener.class)
|
||||
{
|
||||
createModelTracker(core.getName(),
|
||||
trackerRegistry,
|
||||
coreProperties,
|
||||
coreContainer.getSolrHome(),
|
||||
repositoryClient,
|
||||
informationServer,
|
||||
scheduler);
|
||||
}
|
||||
|
||||
/*
|
||||
* The shutdown hook needs to be registered regardless we are slave or masters.
|
||||
* This because if we are master all trackers will be scheduled, if we are slave the node state publisher
|
||||
* will be scheduled.
|
||||
*
|
||||
* As consequence of that, regardless the node role, we will always have something to shutdown in the tracker
|
||||
* registry.
|
||||
*/
|
||||
final List<Tracker> trackers = new ArrayList<>();
|
||||
core.addCloseHook(new CloseHook()
|
||||
{
|
||||
@Override
|
||||
public void preClose(SolrCore core)
|
||||
{
|
||||
LOGGER.info("Solr Core instance {} with name {} is going to be closed. Tracking Subsystem shutdown callback procedure has been started.", core.hashCode(), core.getName());
|
||||
|
||||
// IMPORTANT: the closure needs to be created with the trackers created in this method
|
||||
shutdownTrackers(core, trackers, scheduler, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postClose(SolrCore core)
|
||||
{
|
||||
LOGGER.info("Solr Core instance {} with name {} has been closed. Tracking Subsystem shutdown callback procedure has been completed.", core.hashCode(), core.getName());
|
||||
}
|
||||
});
|
||||
|
||||
boolean trackersHaveBeenEnabled = Boolean.parseBoolean(coreProperties.getProperty("enable.alfresco.tracking", "true"));
|
||||
boolean owningCoreIsSlave = isSlaveModeEnabledFor(core);
|
||||
|
||||
if (trackerRegistry.hasTrackersForCore(core.getName()))
|
||||
{
|
||||
LOGGER.info("Trackers (it could be only the node state publisher in case this node is a slave) for " + core.getName() + " are already registered, shutting them down.");
|
||||
Collection<Tracker> alreadyRegisteredTrackers = trackerRegistry.getTrackersForCore(core.getName());
|
||||
trackerRegistry.removeTrackersForCore(core.getName());
|
||||
|
||||
shutdownTrackers(core, alreadyRegisteredTrackers, scheduler, core.isReloaded());
|
||||
admin.getInformationServers().remove(core.getName());
|
||||
}
|
||||
|
||||
// Re-put the information server in the map because a Core reload (see above) could have removed the reference.
|
||||
admin.getInformationServers().put(core.getName(), informationServer);
|
||||
|
||||
// Guard conditions: if trackers must be disabled then immediately return, we've done here.
|
||||
// Case #1: trackers have been explicitly disabled.
|
||||
if (!trackersHaveBeenEnabled)
|
||||
{
|
||||
LOGGER.info("SearchServices Core Trackers have been explicitly disabled on core \"{}\" through \"enable.alfresco.tracking\" configuration property.", core.getName());
|
||||
|
||||
SlaveCoreStatePublisher statePublisher = new SlaveCoreStatePublisher(false, coreProperties, repositoryClient, core.getName(), informationServer);
|
||||
trackerRegistry.register(core.getName(), statePublisher);
|
||||
scheduler.schedule(statePublisher, core.getName(), coreProperties);
|
||||
trackers.add(statePublisher);
|
||||
|
||||
LOGGER.info("SearchServices Slave Node Provider have been created and scheduled for core \"{}\".", core.getName());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Case #2: we are on a slave node.
|
||||
if (owningCoreIsSlave)
|
||||
{
|
||||
LOGGER.info("SearchServices Core Trackers have been disabled on core \"{}\" because it is a slave core.", core.getName());
|
||||
|
||||
SlaveCoreStatePublisher statePublisher = new SlaveCoreStatePublisher(false, coreProperties, repositoryClient, core.getName(), informationServer);
|
||||
trackerRegistry.register(core.getName(), statePublisher);
|
||||
scheduler.schedule(statePublisher, core.getName(), coreProperties);
|
||||
trackers.add(statePublisher);
|
||||
|
||||
LOGGER.info("SearchServices Slave Node Provider have been created and scheduled for Core instance {} with name {}.", core.hashCode(), core.getName());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("SearchServices Tracking Subsystem starts on Solr Core instance {} with name {}", core.hashCode(), core.getName());
|
||||
|
||||
trackers.addAll(createAndScheduleCoreTrackers(core, trackerRegistry, coreProperties, scheduler, repositoryClient, informationServer));
|
||||
|
||||
CommitTracker commitTracker = new CommitTracker(coreProperties, repositoryClient, core.getName(), informationServer, trackers);
|
||||
trackerRegistry.register(core.getName(), commitTracker);
|
||||
scheduler.schedule(commitTracker, core.getName(), coreProperties);
|
||||
|
||||
LOGGER.info("Tracker {}, instance {}, belonging to Core {}, instance {} has been registered and scheduled.",
|
||||
commitTracker.getClass().getSimpleName(),
|
||||
commitTracker.hashCode(),
|
||||
core.getName(),
|
||||
core.hashCode());
|
||||
|
||||
//Add the commitTracker to the list of scheduled trackers that can be shutdown
|
||||
trackers.add(commitTracker);
|
||||
}
|
||||
}
|
||||
|
||||
List<Tracker> createAndScheduleCoreTrackers(SolrCore core,
|
||||
TrackerRegistry trackerRegistry,
|
||||
Properties props,
|
||||
SolrTrackerScheduler scheduler,
|
||||
SOLRAPIClient repositoryClient,
|
||||
SolrInformationServer srv)
|
||||
{
|
||||
AclTracker aclTracker =
|
||||
registerAndSchedule(
|
||||
new AclTracker(props, repositoryClient, core.getName(), srv),
|
||||
core,
|
||||
props,
|
||||
trackerRegistry,
|
||||
scheduler);
|
||||
|
||||
ContentTracker contentTracker =
|
||||
registerAndSchedule(
|
||||
new ContentTracker(props, repositoryClient, core.getName(), srv),
|
||||
core,
|
||||
props,
|
||||
trackerRegistry,
|
||||
scheduler);
|
||||
|
||||
MetadataTracker metadataTracker =
|
||||
registerAndSchedule(
|
||||
new MetadataTracker(true, props, repositoryClient, core.getName(), srv),
|
||||
core,
|
||||
props,
|
||||
trackerRegistry,
|
||||
scheduler);
|
||||
|
||||
CascadeTracker cascadeTracker =
|
||||
registerAndSchedule(
|
||||
new CascadeTracker(props, repositoryClient, core.getName(), srv),
|
||||
core,
|
||||
props,
|
||||
trackerRegistry,
|
||||
scheduler);
|
||||
|
||||
//The CommitTracker will acquire these locks in order
|
||||
//The ContentTracker will likely have the longest runs so put it first to ensure the MetadataTracker is not paused while
|
||||
//waiting for the ContentTracker to release it's lock.
|
||||
//The aclTracker will likely have the shortest runs so put it last.
|
||||
return asList(cascadeTracker, contentTracker, metadataTracker, aclTracker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a {@link Tracker} instance, registers and schedules it.
|
||||
*
|
||||
* @param tracker the tracker that will be scheduled and registered.
|
||||
* @param core the owning core.
|
||||
* @param properties configuration properties.
|
||||
* @param registry the tracker registry instance.
|
||||
* @param scheduler the tracker schedule instance.
|
||||
* @param <T> the tracker instance.
|
||||
* @return the registered and scheduled tracker instance.
|
||||
*/
|
||||
private <T extends Tracker> T registerAndSchedule(T tracker, SolrCore core, Properties properties, TrackerRegistry registry, SolrTrackerScheduler scheduler)
|
||||
{
|
||||
registry.register(core.getName(), tracker);
|
||||
scheduler.schedule(tracker, core.getName(), properties);
|
||||
|
||||
LOGGER.info("Tracker {}, instance {}, belonging to Core {}, instance {} has been registered and scheduled.",
|
||||
tracker.getClass().getSimpleName(),
|
||||
tracker.hashCode(),
|
||||
core.getName(),
|
||||
core.hashCode());
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
private void createModelTracker(String coreName,
|
||||
TrackerRegistry trackerRegistry,
|
||||
Properties props,
|
||||
String solrHome,
|
||||
SOLRAPIClient repositoryClient,
|
||||
SolrInformationServer srv,
|
||||
SolrTrackerScheduler scheduler)
|
||||
{
|
||||
ModelTracker mTracker = trackerRegistry.getModelTracker();
|
||||
if (mTracker == null)
|
||||
{
|
||||
LOGGER.debug("Creating a new Model Tracker instance.");
|
||||
mTracker = new ModelTracker(solrHome, props, repositoryClient, coreName, srv);
|
||||
trackerRegistry.setModelTracker(mTracker);
|
||||
|
||||
LOGGER.info("Model Tracker: ensuring first model sync.");
|
||||
mTracker.ensureFirstModelSync();
|
||||
|
||||
scheduler.schedule(mTracker, coreName, props);
|
||||
|
||||
LOGGER.info("Model Tracker has been correctly initialised, registered and scheduled.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the trackers for a core.
|
||||
*
|
||||
* The trackers are only deleted from the scheduler if they are the exact same instance of the Tracker class
|
||||
* passed into this method.
|
||||
* For example, you could have 2 cores of the same name and have the trackers registered with the scheduler BUT
|
||||
* the scheduler only keys by core name. The Collection<Tracker>s passed into this method are only removed
|
||||
* from the scheduler if the instances are == (equal). See scheduler.deleteJobForTrackerInstance()
|
||||
*
|
||||
* Trackers are not removed from the registry because the registry only keys by core name; its possible to
|
||||
* have multiple cores of the same name running. Left over trackers in the registry are cleaned up by the CoreContainer
|
||||
* shutdown, that happens in the the AlfrescoCoreAdminHandler.shutdown().
|
||||
*
|
||||
* The coreHasBeenReloaded flag is used just for logging out meaningful messages about the owning core instance.
|
||||
* If we are in a RELOAD scenario (coreHasBeenReloaded = true) we no longer have the reference of the closed core
|
||||
* so we print only its name. Instead in case we are here because a core has been closed, we can print out the core
|
||||
* reference in order to add meaningful information in the log.
|
||||
*
|
||||
* @param core The owning core name.
|
||||
* @param coreTrackers A collection of trackers
|
||||
* @param scheduler The scheduler
|
||||
* @param coreHasBeenReloaded a flag indicating if we are on a Core RELOAD scenario.
|
||||
*/
|
||||
void shutdownTrackers(SolrCore core, Collection<Tracker> coreTrackers, SolrTrackerScheduler scheduler, boolean coreHasBeenReloaded)
|
||||
{
|
||||
coreTrackers.forEach(tracker -> shutdownTracker(core, tracker, scheduler, coreHasBeenReloaded));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown procedure for a single tracker.
|
||||
* The coreHasBeenReloaded flag is used just for logging out meaningful messages about the owning core instance.
|
||||
* If we are in a RELOAD scenario (coreHasBeenReloaded = true) we no longer have the reference of the closed core
|
||||
* so we print only its name. Instead in case we are here because a core has been closed, we can print out the core
|
||||
* reference in order to add meaningful information in the log.
|
||||
*
|
||||
* @param core the owning {@link SolrCore}
|
||||
* @param tracker the {@link Tracker} instance we want to stop.
|
||||
* @param scheduler the scheduler.
|
||||
* @param coreHasBeenReloaded a flag indicating if we are on a Core RELOAD scenario.
|
||||
*/
|
||||
private void shutdownTracker(SolrCore core, Tracker tracker, SolrTrackerScheduler scheduler, boolean coreHasBeenReloaded)
|
||||
{
|
||||
// In case of reload the input core is not the owner: the owner is instead the previous (closed) core and we don't have its reference here.
|
||||
String coreReference = core.getName() + (coreHasBeenReloaded ? "" : ", instance " + core.hashCode());
|
||||
|
||||
if (tracker.isAlreadyInShutDownMode())
|
||||
{
|
||||
LOGGER.info("Tracker {}, instance {} belonging to core {}, is already in shutdown mode.",
|
||||
tracker.getClass().getSimpleName(),
|
||||
tracker.hashCode(),
|
||||
coreReference);
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("Tracker {}, instance {} belonging to core {} shutdown procedure initiated.",
|
||||
tracker.getClass().getSimpleName(),
|
||||
tracker.hashCode(),
|
||||
coreReference);
|
||||
try
|
||||
{
|
||||
tracker.setShutdown(true);
|
||||
if (!scheduler.isShutdown())
|
||||
{
|
||||
scheduler.deleteJobForTrackerInstance(core.getName(), tracker);
|
||||
}
|
||||
|
||||
tracker.shutdown();
|
||||
|
||||
LOGGER.info("Tracker {}, instance {}, belonging to core {} shutdown procedure correctly terminated.",
|
||||
tracker.getClass().getSimpleName(),
|
||||
tracker.hashCode(),
|
||||
coreReference);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LOGGER.error("Tracker {}, instance {} belonging to core {}, shutdown procedure failed. " +
|
||||
"See the stacktrace below for further details.",
|
||||
tracker.getClass().getSimpleName(),
|
||||
tracker.hashCode(),
|
||||
coreReference,
|
||||
exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the configuration declares this node as a slave.
|
||||
*
|
||||
* @param core the hosting {@link SolrCore} instance.
|
||||
* @return true if the content store must be set in read only mode, false otherwise.
|
||||
*/
|
||||
boolean isSlaveModeEnabledFor(SolrCore core)
|
||||
{
|
||||
Predicate<PluginInfo> onlyReplicationHandler =
|
||||
plugin -> "/replication".equals(plugin.name)
|
||||
|| plugin.className.endsWith(ReplicationHandler.class.getSimpleName());
|
||||
|
||||
Function<NamedList, Boolean> isSlaveModeEnabled =
|
||||
params -> ofNullable(params)
|
||||
.map(configuration -> {
|
||||
Object enable = configuration.get("enable");
|
||||
return enable == null ||
|
||||
(enable instanceof String ? StrUtils.parseBool((String)enable) : Boolean.TRUE.equals(enable));})
|
||||
.orElse(false);
|
||||
|
||||
return core.getSolrConfig().getPluginInfos(SolrRequestHandler.class.getName())
|
||||
.stream()
|
||||
.filter(PluginInfo::isEnabled)
|
||||
.filter(onlyReplicationHandler)
|
||||
.findFirst()
|
||||
.map(plugin -> plugin.initArgs)
|
||||
.map(params -> params.get("slave"))
|
||||
.map(NamedList.class::cast)
|
||||
.map(isSlaveModeEnabled)
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
-258
@@ -1,258 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.solr.lifecycle;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService;
|
||||
import org.alfresco.solr.AlfrescoCoreAdminHandler;
|
||||
import org.alfresco.solr.AlfrescoSolrDataModel;
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.SolrKeyResourceLoader;
|
||||
import org.alfresco.solr.client.SOLRAPIClient;
|
||||
import org.alfresco.solr.client.SOLRAPIClientFactory;
|
||||
import org.alfresco.solr.content.SolrContentStore;
|
||||
import org.alfresco.solr.tracker.AclTracker;
|
||||
import org.alfresco.solr.tracker.CascadeTracker;
|
||||
import org.alfresco.solr.tracker.CommitTracker;
|
||||
import org.alfresco.solr.tracker.ContentTracker;
|
||||
import org.alfresco.solr.tracker.MetadataTracker;
|
||||
import org.alfresco.solr.tracker.ModelTracker;
|
||||
import org.alfresco.solr.tracker.SolrTrackerScheduler;
|
||||
import org.alfresco.solr.tracker.Tracker;
|
||||
import org.alfresco.solr.tracker.TrackerRegistry;
|
||||
import org.apache.solr.core.CloseHook;
|
||||
import org.apache.solr.core.CoreContainer;
|
||||
import org.apache.solr.core.CoreDescriptorDecorator;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Deals with core registration when the core is loaded.
|
||||
*
|
||||
* @author Gethin James
|
||||
*/
|
||||
public class SolrCoreLoadRegistration {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
/**
|
||||
* Registers with the admin handler the information server and the trackers.
|
||||
*/
|
||||
public static void registerForCore(AlfrescoCoreAdminHandler adminHandler, CoreContainer coreContainer, SolrCore core,
|
||||
String coreName)
|
||||
{
|
||||
|
||||
|
||||
TrackerRegistry trackerRegistry = adminHandler.getTrackerRegistry();
|
||||
Properties props = new CoreDescriptorDecorator(core.getCoreDescriptor()).getProperties();
|
||||
//Prepare cores
|
||||
SolrResourceLoader loader = core.getLatestSchema().getResourceLoader();
|
||||
SolrKeyResourceLoader keyResourceLoader = new SolrKeyResourceLoader(loader);
|
||||
SOLRAPIClientFactory clientFactory = new SOLRAPIClientFactory();
|
||||
SOLRAPIClient repositoryClient = clientFactory.getSOLRAPIClient(props, keyResourceLoader,
|
||||
AlfrescoSolrDataModel.getInstance().getDictionaryService(CMISStrictDictionaryService.DEFAULT),
|
||||
AlfrescoSolrDataModel.getInstance().getNamespaceDAO());
|
||||
//Start content store
|
||||
SolrContentStore contentStore = new SolrContentStore(coreContainer.getSolrHome());
|
||||
SolrInformationServer srv = new SolrInformationServer(adminHandler, core, repositoryClient, contentStore);
|
||||
props.putAll(srv.getProps());
|
||||
adminHandler.getInformationServers().put(coreName, srv);
|
||||
|
||||
SolrTrackerScheduler scheduler = adminHandler.getScheduler();
|
||||
|
||||
// Prevents other threads from registering the ModelTracker at the same time
|
||||
// Create model tracker and load all the persisted models
|
||||
createModelTracker(coreName,
|
||||
trackerRegistry,
|
||||
props,
|
||||
coreContainer.getSolrHome(),
|
||||
repositoryClient,
|
||||
srv,
|
||||
scheduler);
|
||||
|
||||
|
||||
log.info("Starting to track " + coreName);
|
||||
if (Boolean.parseBoolean(props.getProperty("enable.alfresco.tracking", "false")))
|
||||
{
|
||||
|
||||
if (trackerRegistry.hasTrackersForCore(coreName))
|
||||
{
|
||||
log.info("Trackers for " + coreName+ " is already registered, shutting them down.");
|
||||
shutdownTrackers(coreName, trackerRegistry.getTrackersForCore(coreName),scheduler);
|
||||
trackerRegistry.removeTrackersForCore(coreName);
|
||||
adminHandler.getInformationServers().remove(coreName);
|
||||
}
|
||||
|
||||
List<Tracker> trackers = createCoreTrackers(coreName, trackerRegistry, props, scheduler, repositoryClient, srv);
|
||||
|
||||
CommitTracker commitTracker = new CommitTracker(props, repositoryClient, coreName, srv, trackers);
|
||||
trackerRegistry.register(coreName, commitTracker);
|
||||
scheduler.schedule(commitTracker, coreName, props);
|
||||
log.info("The Trackers are now scheduled to run");
|
||||
trackers.add(commitTracker); //Add the commitTracker to the list of scheduled trackers that can be shutdown
|
||||
|
||||
core.addCloseHook(new CloseHook()
|
||||
{
|
||||
@Override
|
||||
public void preClose(SolrCore core)
|
||||
{
|
||||
log.info("Shutting down " + core.getName());
|
||||
SolrCoreLoadRegistration.shutdownTrackers(core.getName(), trackers, scheduler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postClose(SolrCore core)
|
||||
{
|
||||
// Nothing to be done here
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the trackers
|
||||
*
|
||||
* @param coreName
|
||||
* @param trackerRegistry
|
||||
* @param props
|
||||
* @param scheduler
|
||||
* @param repositoryClient
|
||||
* @param srv
|
||||
* @return A list of trackers
|
||||
*/
|
||||
private static List<Tracker> createCoreTrackers(String coreName,
|
||||
TrackerRegistry trackerRegistry,
|
||||
Properties props,
|
||||
SolrTrackerScheduler scheduler,
|
||||
SOLRAPIClient repositoryClient,
|
||||
SolrInformationServer srv) {
|
||||
List<Tracker> trackers = new ArrayList<Tracker>();
|
||||
|
||||
AclTracker aclTracker = new AclTracker(props, repositoryClient, coreName, srv);
|
||||
trackerRegistry.register(coreName, aclTracker);
|
||||
scheduler.schedule(aclTracker, coreName, props);
|
||||
|
||||
ContentTracker contentTrkr = new ContentTracker(props, repositoryClient, coreName, srv);
|
||||
trackerRegistry.register(coreName, contentTrkr);
|
||||
scheduler.schedule(contentTrkr, coreName, props);
|
||||
|
||||
MetadataTracker metaTrkr = new MetadataTracker(props, repositoryClient, coreName, srv);
|
||||
trackerRegistry.register(coreName, metaTrkr);
|
||||
scheduler.schedule(metaTrkr, coreName, props);
|
||||
|
||||
CascadeTracker cascadeTrkr = new CascadeTracker(props, repositoryClient, coreName, srv);
|
||||
trackerRegistry.register(coreName, cascadeTrkr);
|
||||
scheduler.schedule(cascadeTrkr, coreName, props);
|
||||
|
||||
//The CommitTracker will acquire these locks in order
|
||||
//The ContentTracker will likely have the longest runs so put it first to ensure the MetadataTracker is not paused while
|
||||
//waiting for the ContentTracker to release it's lock.
|
||||
//The aclTracker will likely have the shortest runs so put it last.
|
||||
trackers.add(cascadeTrkr);
|
||||
trackers.add(contentTrkr);
|
||||
trackers.add(metaTrkr);
|
||||
trackers.add(aclTracker);
|
||||
return trackers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create model tracker and load persisted models.
|
||||
*
|
||||
* @param coreName
|
||||
* @param trackerRegistry
|
||||
* @param props
|
||||
* @param solrHome
|
||||
* @param repositoryClient
|
||||
* @param srv
|
||||
* @param scheduler
|
||||
* @return true if model tracker has been created, false if it already exists.
|
||||
*/
|
||||
private synchronized static void createModelTracker(String coreName,
|
||||
TrackerRegistry trackerRegistry,
|
||||
Properties props,
|
||||
String solrHome,
|
||||
SOLRAPIClient repositoryClient,
|
||||
SolrInformationServer srv,
|
||||
SolrTrackerScheduler scheduler)
|
||||
{
|
||||
ModelTracker mTracker = trackerRegistry.getModelTracker();
|
||||
if (mTracker == null)
|
||||
{
|
||||
log.debug("Creating ModelTracker");
|
||||
mTracker = new ModelTracker(solrHome, props, repositoryClient,
|
||||
coreName, srv);
|
||||
|
||||
trackerRegistry.setModelTracker(mTracker);
|
||||
log.info("Ensuring first model sync.");
|
||||
mTracker.ensureFirstModelSync();
|
||||
log.info("Done ensuring first model sync.");
|
||||
|
||||
//Scheduling the ModelTracker.
|
||||
scheduler.schedule(mTracker, coreName, props);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the trackers for a core.
|
||||
*
|
||||
* The trackers are only deleted from the scheduler if they are the exact same instance of the Tracker class
|
||||
* passed into this method.
|
||||
* For example, you could have 2 cores of the same name and have the trackers registered with the scheduler BUT
|
||||
* the scheduler only keys by core name. The Collection<Tracker>s passed into this method are only removed
|
||||
* from the scheduler if the instances are == (equal). See scheduler.deleteJobForTrackerInstance()
|
||||
*
|
||||
* Trackers are not removed from the registry because the registry only keys by core name; its possible to
|
||||
* have multiple cores of the same name running. Left over trackers in the registry are cleaned up by the CoreContainer
|
||||
* shutdown, that happens in the the AlfrescoCoreAdminHandler.shutdown().
|
||||
*
|
||||
* @param coreName The name of the core
|
||||
* @param coreTrackers A collection of trackers
|
||||
* @param scheduler The scheduler
|
||||
*/
|
||||
public static void shutdownTrackers(String coreName, Collection<Tracker> coreTrackers, SolrTrackerScheduler scheduler)
|
||||
{
|
||||
try
|
||||
{
|
||||
log.info("Shutting down " + coreName + " with " + coreTrackers.size() + " trackers.");
|
||||
|
||||
// Sets the shutdown flag on the trackers to stop them from doing any more work
|
||||
coreTrackers.forEach(tracker -> tracker.setShutdown(true));
|
||||
|
||||
if (!scheduler.isShutdown())
|
||||
{
|
||||
coreTrackers.forEach(tracker -> scheduler.deleteJobForTrackerInstance(coreName,tracker) );
|
||||
}
|
||||
|
||||
coreTrackers.forEach(tracker -> tracker.shutdown());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("Failed to shutdown trackers for core "+coreName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
-52
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.alfresco.solr.tracker;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Properties;
|
||||
@@ -31,7 +32,6 @@ import org.alfresco.solr.client.SOLRAPIClient;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class that provides common {@link Tracker} behaviour.
|
||||
*
|
||||
@@ -39,20 +39,18 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public abstract class AbstractTracker implements Tracker
|
||||
{
|
||||
public static final long TIME_STEP_32_DAYS_IN_MS = 1000 * 60 * 60 * 24 * 32L;
|
||||
public static final long TIME_STEP_1_HR_IN_MS = 60 * 60 * 1000L;
|
||||
public static final String SHARD_METHOD_ACLID = "ACL_ID";
|
||||
public static final String SHARD_METHOD_DBID = "DB_ID";
|
||||
protected final static Logger log = LoggerFactory.getLogger(AbstractTracker.class);
|
||||
static final long TIME_STEP_32_DAYS_IN_MS = 1000 * 60 * 60 * 24 * 32L;
|
||||
static final long TIME_STEP_1_HR_IN_MS = 60 * 60 * 1000L;
|
||||
static final String SHARD_METHOD_DBID = "DB_ID";
|
||||
|
||||
protected final static Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
protected Properties props;
|
||||
protected SOLRAPIClient client;
|
||||
protected InformationServer infoSrv;
|
||||
InformationServer infoSrv;
|
||||
protected String coreName;
|
||||
protected StoreRef storeRef;
|
||||
protected long batchCount;
|
||||
protected boolean isSlave = false;
|
||||
protected boolean isMaster = true;
|
||||
protected String alfrescoVersion;
|
||||
protected TrackerStats trackerStats;
|
||||
protected boolean runPostModelLoadInit = true;
|
||||
@@ -71,14 +69,10 @@ public abstract class AbstractTracker implements Tracker
|
||||
protected volatile boolean rollback;
|
||||
protected final Type type;
|
||||
|
||||
|
||||
/*
|
||||
* A thread handler can be used by subclasses, but they have to intentionally instantiate it.
|
||||
*/
|
||||
protected ThreadHandler threadHandler;
|
||||
|
||||
|
||||
|
||||
ThreadHandler threadHandler;
|
||||
|
||||
/**
|
||||
* Default constructor, strictly for testing.
|
||||
@@ -98,8 +92,6 @@ public abstract class AbstractTracker implements Tracker
|
||||
storeRef = new StoreRef(p.getProperty("alfresco.stores", "workspace://SpacesStore"));
|
||||
batchCount = Integer.parseInt(p.getProperty("alfresco.batch.count", "5000"));
|
||||
maxLiveSearchers = Integer.parseInt(p.getProperty("alfresco.maxLiveSearchers", "2"));
|
||||
isSlave = Boolean.parseBoolean(p.getProperty("enable.slave", "false"));
|
||||
isMaster = Boolean.parseBoolean(p.getProperty("enable.master", "true"));
|
||||
|
||||
shardCount = Integer.parseInt(p.getProperty("shard.count", "1"));
|
||||
shardInstance = Integer.parseInt(p.getProperty("shard.instance", "0"));
|
||||
@@ -115,19 +107,19 @@ public abstract class AbstractTracker implements Tracker
|
||||
|
||||
this.type = type;
|
||||
|
||||
log.info("Solr built for Alfresco version: " + alfrescoVersion);
|
||||
LOGGER.info("Solr built for Alfresco version: {}", alfrescoVersion);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses must implement behaviour that completes the following steps, in order:
|
||||
*
|
||||
* <ol>
|
||||
* <li>Purge</li>
|
||||
* <li>Reindex</li>
|
||||
* <li>Index</li>
|
||||
* <li>Track repository</li>
|
||||
* </ol>
|
||||
* @throws Throwable
|
||||
*/
|
||||
protected abstract void doTrack() throws Throwable;
|
||||
|
||||
@@ -146,7 +138,7 @@ public abstract class AbstractTracker implements Tracker
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
||||
// Ignore
|
||||
}
|
||||
|
||||
|
||||
@@ -158,12 +150,7 @@ public abstract class AbstractTracker implements Tracker
|
||||
|
||||
getTrackerState();
|
||||
|
||||
|
||||
if(state == null) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return state == null;
|
||||
|
||||
}
|
||||
/**
|
||||
@@ -173,8 +160,9 @@ public abstract class AbstractTracker implements Tracker
|
||||
@Override
|
||||
public void track()
|
||||
{
|
||||
if(runLock.availablePermits() == 0) {
|
||||
log.info("... " + this.getClass().getSimpleName() + " for core [" + coreName + "] is already in use "+ this.getClass());
|
||||
if(runLock.availablePermits() == 0)
|
||||
{
|
||||
LOGGER.info("... {} for core [{}] is already in use {}", this.getClass().getSimpleName(), coreName, getClass());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -184,15 +172,14 @@ public abstract class AbstractTracker implements Tracker
|
||||
* The runLock ensures that for each tracker type (metadata, content, commit, cascade) only one tracker will
|
||||
* be running at a time.
|
||||
*/
|
||||
|
||||
runLock.acquire();
|
||||
|
||||
if(state==null && Boolean.parseBoolean(System.getProperty("alfresco.test", "false")))
|
||||
if (state==null && Boolean.parseBoolean(System.getProperty("alfresco.test", "false")))
|
||||
{
|
||||
assert(assertTrackerStateRemainsNull());
|
||||
}
|
||||
|
||||
log.info("... Running " + this.getClass().getSimpleName() + " for core [" + coreName + "].");
|
||||
LOGGER.info("... Running {} for core [{}]", this.getClass().getSimpleName(), coreName);
|
||||
|
||||
if(this.state == null)
|
||||
{
|
||||
@@ -200,8 +187,8 @@ public abstract class AbstractTracker implements Tracker
|
||||
* Set the global state for the tracker here.
|
||||
*/
|
||||
this.state = getTrackerState();
|
||||
log.debug("##### Setting tracker global state.");
|
||||
log.debug("State set: " + this.state.toString());
|
||||
LOGGER.debug("##### Setting tracker global state.");
|
||||
LOGGER.debug("State set: {}", this.state.toString());
|
||||
this.state.setRunning(true);
|
||||
}
|
||||
else
|
||||
@@ -219,38 +206,39 @@ public abstract class AbstractTracker implements Tracker
|
||||
catch(IndexTrackingShutdownException t)
|
||||
{
|
||||
setRollback(true);
|
||||
log.info("Stopping index tracking for " + getClass().getSimpleName() + " - " + coreName);
|
||||
LOGGER.info("Stopping index tracking for {} - {}", getClass().getSimpleName(), coreName);
|
||||
}
|
||||
catch(Throwable t)
|
||||
{
|
||||
setRollback(true);
|
||||
if (t instanceof SocketTimeoutException || t instanceof ConnectException)
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
if (LOGGER.isDebugEnabled())
|
||||
{
|
||||
// DEBUG, so give the whole stack trace
|
||||
log.warn("Tracking communication timed out for " + getClass().getSimpleName() + " - " + coreName, t);
|
||||
LOGGER.warn("Tracking communication timed out for {} - {}", getClass().getSimpleName(), coreName, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't need the stack trace. It timed out.
|
||||
log.warn("Tracking communication timed out for " + getClass().getSimpleName() + " - " + coreName);
|
||||
LOGGER.warn("Tracking communication timed out for for {} - {}", getClass().getSimpleName(), coreName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("Tracking failed for " + getClass().getSimpleName() + " - " + coreName, t);
|
||||
LOGGER.error("Tracking failed for for {} - {}", getClass().getSimpleName(), coreName, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
log.error("Semaphore interrupted for " + getClass().getSimpleName() + " - " + coreName, e);
|
||||
LOGGER.error("Semaphore interrupted for for {} - {}", getClass().getSimpleName(), coreName, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
infoSrv.unregisterTrackerThread();
|
||||
if(state != null) {
|
||||
if(state != null)
|
||||
{
|
||||
//During a rollback state is set to null.
|
||||
state.setRunning(false);
|
||||
state.setCheck(false);
|
||||
@@ -259,15 +247,18 @@ public abstract class AbstractTracker implements Tracker
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getRollback() {
|
||||
public boolean getRollback()
|
||||
{
|
||||
return this.rollback;
|
||||
}
|
||||
|
||||
public void setRollback(boolean rollback) {
|
||||
public void setRollback(boolean rollback)
|
||||
{
|
||||
this.rollback = rollback;
|
||||
}
|
||||
|
||||
private void continueState() {
|
||||
private void continueState()
|
||||
{
|
||||
infoSrv.continueState(state);
|
||||
state.incrementTrackerCycles();
|
||||
}
|
||||
@@ -289,8 +280,6 @@ public abstract class AbstractTracker implements Tracker
|
||||
return this.infoSrv.getTrackerInitialState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allows time for the scheduled asynchronous tasks to complete
|
||||
@@ -309,6 +298,7 @@ public abstract class AbstractTracker implements Tracker
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// Nothing to be done here
|
||||
}
|
||||
}
|
||||
currentRunnable = this.threadHandler.peekHeadReindexWorker();
|
||||
@@ -327,15 +317,22 @@ public abstract class AbstractTracker implements Tracker
|
||||
throw new IndexTrackingShutdownException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAlreadyInShutDownMode()
|
||||
{
|
||||
return shutdown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShutdown(boolean shutdown)
|
||||
{
|
||||
this.shutdown = shutdown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown()
|
||||
{
|
||||
log.warn("Core "+ coreName+" shutdown called on tracker. " + getClass().getSimpleName() + " " + hashCode());
|
||||
setShutdown(true);
|
||||
if(this.threadHandler != null)
|
||||
{
|
||||
@@ -343,15 +340,16 @@ public abstract class AbstractTracker implements Tracker
|
||||
}
|
||||
}
|
||||
|
||||
public Semaphore getWriteLock() {
|
||||
public Semaphore getWriteLock()
|
||||
{
|
||||
return this.writeLock;
|
||||
}
|
||||
|
||||
public Semaphore getRunLock() {
|
||||
public Semaphore getRunLock()
|
||||
{
|
||||
return this.runLock;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Alfresco version Solr was built for
|
||||
*/
|
||||
@@ -370,6 +368,4 @@ public abstract class AbstractTracker implements Tracker
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
-5
@@ -288,11 +288,6 @@ public class AclTracker extends AbstractTracker
|
||||
protected void trackRepository() throws IOException, AuthenticationException, JSONException
|
||||
{
|
||||
checkShutdown();
|
||||
|
||||
if(!isMaster && isSlave)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TrackerState state = super.getTrackerState();
|
||||
|
||||
|
||||
+2
-2
@@ -50,14 +50,14 @@ public class CascadeTracker extends AbstractTracker implements Tracker
|
||||
public CascadeTracker(Properties p, SOLRAPIClient client, String coreName,
|
||||
InformationServer informationServer)
|
||||
{
|
||||
super(p, client, coreName, informationServer, Tracker.Type.Cascade);
|
||||
super(p, client, coreName, informationServer, Tracker.Type.CASCADE);
|
||||
|
||||
threadHandler = new ThreadHandler(p, coreName, "CascadeTracker");
|
||||
}
|
||||
|
||||
CascadeTracker()
|
||||
{
|
||||
super(Tracker.Type.Cascade);
|
||||
super(Tracker.Type.CASCADE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -51,7 +51,7 @@ public class CommitTracker extends AbstractTracker
|
||||
**/
|
||||
CommitTracker()
|
||||
{
|
||||
super(Tracker.Type.Commit);
|
||||
super(Tracker.Type.COMMIT);
|
||||
}
|
||||
|
||||
public CommitTracker(Properties p,
|
||||
@@ -60,7 +60,7 @@ public class CommitTracker extends AbstractTracker
|
||||
InformationServer informationServer,
|
||||
List<Tracker> trackers)
|
||||
{
|
||||
super(p, client, coreName, informationServer, Tracker.Type.Commit);
|
||||
super(p, client, coreName, informationServer, Tracker.Type.COMMIT);
|
||||
|
||||
//Set the trackers
|
||||
for(Tracker tracker : trackers) {
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ public class ContentTracker extends AbstractTracker implements Tracker
|
||||
public ContentTracker(Properties p, SOLRAPIClient client, String coreName,
|
||||
InformationServer informationServer)
|
||||
{
|
||||
super(p, client, coreName, informationServer, Tracker.Type.Content);
|
||||
super(p, client, coreName, informationServer, Tracker.Type.CONTENT);
|
||||
contentReadBatchSize = Integer.parseInt(p.getProperty("alfresco.contentReadBatchSize", "100"));
|
||||
contentUpdateBatchSize = Integer.parseInt(p.getProperty("alfresco.contentUpdateBatchSize", "1000"));
|
||||
threadHandler = new ThreadHandler(p, coreName, "ContentTracker");
|
||||
@@ -53,7 +53,7 @@ public class ContentTracker extends AbstractTracker implements Tracker
|
||||
|
||||
ContentTracker()
|
||||
{
|
||||
super(Tracker.Type.Content);
|
||||
super(Tracker.Type.CONTENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Solr Client
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.solr.tracker;
|
||||
|
||||
import static java.util.Optional.of;
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static org.alfresco.solr.tracker.DocRouterFactory.SHARD_KEY_KEY;
|
||||
|
||||
import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService;
|
||||
import org.alfresco.repo.dictionary.NamespaceDAO;
|
||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||
import org.alfresco.repo.index.shard.ShardState;
|
||||
import org.alfresco.repo.index.shard.ShardStateBuilder;
|
||||
import org.alfresco.repo.search.impl.QueryParserUtils;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.solr.AlfrescoCoreAdminHandler;
|
||||
import org.alfresco.solr.AlfrescoSolrDataModel;
|
||||
import org.alfresco.solr.InformationServer;
|
||||
import org.alfresco.solr.NodeReport;
|
||||
import org.alfresco.solr.TrackerState;
|
||||
import org.alfresco.solr.client.SOLRAPIClient;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Superclass for all components which are able to inform Alfresco about the hosting node state.
|
||||
* This has been introduced in SEARCH-1752 for splitting the dual responsibility of the {@link MetadataTracker}.
|
||||
* As consequence of that, this class contains all the members needed for obtaining a valid
|
||||
* {@link org.alfresco.repo.index.shard.ShardState} that can be periodically communicated to Alfresco.
|
||||
*
|
||||
* @author Andrea Gazzarini
|
||||
* @since 1.5
|
||||
* @see <a href="https://issues.alfresco.com/jira/browse/SEARCH-1752">SEARCH-1752</a>
|
||||
*/
|
||||
public abstract class CoreStatePublisher extends AbstractTracker
|
||||
{
|
||||
DocRouter docRouter;
|
||||
private final boolean isMaster;
|
||||
|
||||
/** The string representation of the shard key. */
|
||||
private Optional<String> shardKey;
|
||||
|
||||
/** The property to use for determining the shard. */
|
||||
protected Optional<QName> shardProperty = Optional.empty();
|
||||
|
||||
CoreStatePublisher(
|
||||
boolean isMaster,
|
||||
Properties p,
|
||||
SOLRAPIClient client,
|
||||
String coreName,
|
||||
InformationServer informationServer,
|
||||
Type type)
|
||||
{
|
||||
super(p, client, coreName, informationServer, type);
|
||||
this.isMaster = isMaster;
|
||||
shardMethod = p.getProperty("shard.method", SHARD_METHOD_DBID);
|
||||
shardKey = ofNullable(p.getProperty(SHARD_KEY_KEY));
|
||||
|
||||
firstUpdateShardProperty();
|
||||
|
||||
docRouter = DocRouterFactory.getRouter(p, ShardMethodEnum.getShardMethod(shardMethod));
|
||||
}
|
||||
|
||||
CoreStatePublisher(Type type)
|
||||
{
|
||||
super(type);
|
||||
this.isMaster = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the {@link org.alfresco.solr.client.Node} associated with the given dbid.
|
||||
*
|
||||
* @param dbid the node identifier.
|
||||
* @return the {@link org.alfresco.solr.client.Node} associated with the given dbid.
|
||||
*/
|
||||
public NodeReport checkNode(Long dbid)
|
||||
{
|
||||
NodeReport nodeReport = new NodeReport();
|
||||
nodeReport.setDbid(dbid);
|
||||
|
||||
this.infoSrv.addCommonNodeReportInfo(nodeReport);
|
||||
|
||||
return nodeReport;
|
||||
}
|
||||
|
||||
private void firstUpdateShardProperty()
|
||||
{
|
||||
shardKey.ifPresent( shardKeyName -> {
|
||||
updateShardProperty();
|
||||
if (shardProperty.isEmpty())
|
||||
{
|
||||
LOGGER.warn("Sharding property {} was set to {}, but no such property was found.", SHARD_KEY_KEY, shardKeyName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the shard property using the shard key.
|
||||
*/
|
||||
void updateShardProperty()
|
||||
{
|
||||
shardKey.ifPresent(shardKeyName -> {
|
||||
Optional<QName> updatedShardProperty = getShardProperty(shardKeyName);
|
||||
if (!shardProperty.equals(updatedShardProperty))
|
||||
{
|
||||
if (updatedShardProperty.isEmpty())
|
||||
{
|
||||
LOGGER.warn("The model defining {} property has been disabled", shardKeyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.info("New {} property found for {} ", SHARD_KEY_KEY, shardKeyName);
|
||||
}
|
||||
}
|
||||
shardProperty = updatedShardProperty;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the field name, returns the name of the property definition.
|
||||
* If the property definition is not found, Empty optional is returned.
|
||||
*
|
||||
* @param field the field name.
|
||||
* @return the name of the associated property definition if present, Optional.Empty() otherwise
|
||||
*/
|
||||
static Optional<QName> getShardProperty(String field)
|
||||
{
|
||||
if (StringUtils.isBlank(field))
|
||||
{
|
||||
throw new IllegalArgumentException("Sharding property " + SHARD_KEY_KEY + " has not been set.");
|
||||
}
|
||||
|
||||
AlfrescoSolrDataModel dataModel = AlfrescoSolrDataModel.getInstance();
|
||||
NamespaceDAO namespaceDAO = dataModel.getNamespaceDAO();
|
||||
DictionaryService dictionaryService = dataModel.getDictionaryService(CMISStrictDictionaryService.DEFAULT);
|
||||
PropertyDefinition propertyDef = QueryParserUtils.matchPropertyDefinition("http://www.alfresco.org/model/content/1.0",
|
||||
namespaceDAO,
|
||||
dictionaryService,
|
||||
field);
|
||||
|
||||
return ofNullable(propertyDef).map(PropertyDefinition::getName);
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link ShardState}, as the name suggests, encapsulates/stores the state of the shard which hosts this
|
||||
* {@link MetadataTracker} instance.
|
||||
*
|
||||
* The {@link ShardState} is primarily used in two places:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Transaction tracking: (see {@link MetadataTracker#trackTransactions()}): for pulling/tracking transactions from Alfresco</li>
|
||||
* <li>
|
||||
* DynamicSharding: when the {@link MetadataTracker} is running on a slave instance it doesn't actually act
|
||||
* as a tracker, it calls Alfresco to register the state of the node (the shard) without pulling any transactions.
|
||||
* As consequence of that, Alfresco will be aware about the shard which will be included in subsequent queries.
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @return the {@link ShardState} instance which stores the current state of the hosting shard.
|
||||
*/
|
||||
ShardState getShardState()
|
||||
{
|
||||
TrackerState transactionsTrackerState = getTrackerState();
|
||||
TrackerState changeSetsTrackerState =
|
||||
of(infoSrv.getAdminHandler())
|
||||
.map(AlfrescoCoreAdminHandler::getTrackerRegistry)
|
||||
.map(registry -> registry.getTrackerForCore(coreName, AclTracker.class))
|
||||
.map(Tracker::getTrackerState)
|
||||
.orElse(transactionsTrackerState);
|
||||
|
||||
HashMap<String, String> propertyBag = new HashMap<>();
|
||||
propertyBag.put("coreName", coreName);
|
||||
HashMap<String, String> extendedPropertyBag = new HashMap<>(propertyBag);
|
||||
updateShardProperty();
|
||||
|
||||
shardProperty.ifPresent(p -> extendedPropertyBag.putAll(docRouter.getProperties(p)));
|
||||
|
||||
return ShardStateBuilder.shardState()
|
||||
.withMaster(isMaster)
|
||||
.withLastUpdated(System.currentTimeMillis())
|
||||
.withLastIndexedChangeSetCommitTime(changeSetsTrackerState.getLastIndexedChangeSetCommitTime())
|
||||
.withLastIndexedChangeSetId(changeSetsTrackerState.getLastIndexedChangeSetId())
|
||||
.withLastIndexedTxCommitTime(transactionsTrackerState.getLastIndexedTxCommitTime())
|
||||
.withLastIndexedTxId(transactionsTrackerState.getLastIndexedTxId())
|
||||
.withPropertyBag(extendedPropertyBag)
|
||||
.withShardInstance()
|
||||
.withBaseUrl(infoSrv.getBaseUrl())
|
||||
.withPort(infoSrv.getPort())
|
||||
.withHostName(infoSrv.getHostName())
|
||||
.withShard()
|
||||
.withInstance(shardInstance)
|
||||
.withFloc()
|
||||
.withNumberOfShards(shardCount)
|
||||
.withAddedStoreRef(storeRef)
|
||||
.withTemplate(shardTemplate)
|
||||
.withHasContent(transformContent)
|
||||
.withShardMethod(ShardMethodEnum.getShardMethod(shardMethod))
|
||||
.withPropertyBag(propertyBag)
|
||||
.endFloc()
|
||||
.endShard()
|
||||
.endShardInstance()
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link DocRouter} instance in use on this node.
|
||||
*
|
||||
* @return the {@link DocRouter} instance in use on this node.
|
||||
*/
|
||||
public DocRouter getDocRouter()
|
||||
{
|
||||
return this.docRouter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the hosting core is master or standalone.
|
||||
*
|
||||
* @return true if the hosting core is master or standalone.
|
||||
*/
|
||||
public boolean isOnMasterOrStandalone()
|
||||
{
|
||||
return isMaster;
|
||||
}
|
||||
}
|
||||
+23
-213
@@ -20,27 +20,15 @@ package org.alfresco.solr.tracker;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.httpclient.AuthenticationException;
|
||||
import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService;
|
||||
import org.alfresco.repo.dictionary.NamespaceDAO;
|
||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||
import org.alfresco.repo.index.shard.ShardState;
|
||||
import org.alfresco.repo.index.shard.ShardStateBuilder;
|
||||
import org.alfresco.repo.search.impl.QueryParserUtils;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.solr.AlfrescoCoreAdminHandler;
|
||||
import org.alfresco.solr.AlfrescoSolrDataModel;
|
||||
import org.alfresco.solr.BoundedDeque;
|
||||
import org.alfresco.solr.InformationServer;
|
||||
import org.alfresco.solr.NodeReport;
|
||||
@@ -53,95 +41,41 @@ import org.alfresco.solr.client.SOLRAPIClient;
|
||||
import org.alfresco.solr.client.Transaction;
|
||||
import org.alfresco.solr.client.Transactions;
|
||||
import org.apache.commons.codec.EncoderException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.JSONException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static java.util.Optional.of;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static org.alfresco.solr.tracker.DocRouterFactory.SHARD_KEY_KEY;
|
||||
|
||||
/*
|
||||
* This tracks two things: transactions and metadata nodes
|
||||
* @author Ahmed Owian
|
||||
*/
|
||||
public class MetadataTracker extends AbstractTracker implements Tracker
|
||||
public class MetadataTracker extends CoreStatePublisher implements Tracker
|
||||
{
|
||||
|
||||
protected final static Logger log = LoggerFactory.getLogger(MetadataTracker.class);
|
||||
private static final int DEFAULT_TRANSACTION_DOCS_BATCH_SIZE = 100;
|
||||
private static final int DEFAULT_NODE_BATCH_SIZE = 10;
|
||||
private int transactionDocsBatchSize = DEFAULT_TRANSACTION_DOCS_BATCH_SIZE;
|
||||
private int nodeBatchSize = DEFAULT_NODE_BATCH_SIZE;
|
||||
private ConcurrentLinkedQueue<Long> transactionsToReindex = new ConcurrentLinkedQueue<Long>();
|
||||
private ConcurrentLinkedQueue<Long> transactionsToIndex = new ConcurrentLinkedQueue<Long>();
|
||||
private ConcurrentLinkedQueue<Long> transactionsToPurge = new ConcurrentLinkedQueue<Long>();
|
||||
private ConcurrentLinkedQueue<Long> nodesToReindex = new ConcurrentLinkedQueue<Long>();
|
||||
private ConcurrentLinkedQueue<Long> nodesToIndex = new ConcurrentLinkedQueue<Long>();
|
||||
private ConcurrentLinkedQueue<Long> nodesToPurge = new ConcurrentLinkedQueue<Long>();
|
||||
private ConcurrentLinkedQueue<String> queriesToReindex = new ConcurrentLinkedQueue<String>();
|
||||
private DocRouter docRouter;
|
||||
/** The string representation of the shard key. */
|
||||
private Optional<String> shardKey;
|
||||
/** The property to use for determining the shard. */
|
||||
private Optional<QName> shardProperty = Optional.empty();
|
||||
private ConcurrentLinkedQueue<Long> transactionsToReindex = new ConcurrentLinkedQueue<>();
|
||||
private ConcurrentLinkedQueue<Long> transactionsToIndex = new ConcurrentLinkedQueue<>();
|
||||
private ConcurrentLinkedQueue<Long> transactionsToPurge = new ConcurrentLinkedQueue<>();
|
||||
private ConcurrentLinkedQueue<Long> nodesToReindex = new ConcurrentLinkedQueue<>();
|
||||
private ConcurrentLinkedQueue<Long> nodesToIndex = new ConcurrentLinkedQueue<>();
|
||||
private ConcurrentLinkedQueue<Long> nodesToPurge = new ConcurrentLinkedQueue<>();
|
||||
private ConcurrentLinkedQueue<String> queriesToReindex = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public MetadataTracker(Properties p, SOLRAPIClient client, String coreName,
|
||||
public MetadataTracker(final boolean isMaster, Properties p, SOLRAPIClient client, String coreName,
|
||||
InformationServer informationServer)
|
||||
{
|
||||
super(p, client, coreName, informationServer, Tracker.Type.MetaData);
|
||||
super(isMaster, p, client, coreName, informationServer, Tracker.Type.METADATA);
|
||||
transactionDocsBatchSize = Integer.parseInt(p.getProperty("alfresco.transactionDocsBatchSize", "100"));
|
||||
shardMethod = p.getProperty("shard.method", SHARD_METHOD_DBID);
|
||||
shardKey = ofNullable(p.getProperty(SHARD_KEY_KEY));
|
||||
firstUpdateShardProperty();
|
||||
docRouter = DocRouterFactory.getRouter(p, ShardMethodEnum.getShardMethod(shardMethod));
|
||||
nodeBatchSize = Integer.parseInt(p.getProperty("alfresco.nodeBatchSize", "10"));
|
||||
threadHandler = new ThreadHandler(p, coreName, "MetadataTracker");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the shard property using the shard key.
|
||||
*/
|
||||
private void updateShardProperty()
|
||||
{
|
||||
shardKey.ifPresent(shardKeyName -> {
|
||||
Optional<QName> updatedShardProperty = getShardProperty(shardKeyName);
|
||||
if (!shardProperty.equals(updatedShardProperty))
|
||||
{
|
||||
if (updatedShardProperty.isEmpty())
|
||||
{
|
||||
log.warn("The model defining " + shardKeyName + " property has been disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("New " + SHARD_KEY_KEY + " property found for " + shardKeyName);
|
||||
}
|
||||
}
|
||||
shardProperty = updatedShardProperty;
|
||||
});
|
||||
}
|
||||
|
||||
private void firstUpdateShardProperty()
|
||||
{
|
||||
shardKey.ifPresent( shardKeyName -> {
|
||||
updateShardProperty();
|
||||
if (shardProperty.isEmpty())
|
||||
{
|
||||
log.warn("Sharding property " + SHARD_KEY_KEY + " was set to " + shardKeyName + ", but no such property was found.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
MetadataTracker()
|
||||
{
|
||||
super(Tracker.Type.MetaData);
|
||||
}
|
||||
|
||||
public DocRouter getDocRouter() {
|
||||
return this.docRouter;
|
||||
super(Tracker.Type.METADATA);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,7 +94,8 @@ public class MetadataTracker extends AbstractTracker implements Tracker
|
||||
}
|
||||
}
|
||||
|
||||
public void maintenance() throws Exception {
|
||||
public void maintenance() throws Exception
|
||||
{
|
||||
purgeTransactions();
|
||||
purgeNodes();
|
||||
reindexTransactions();
|
||||
@@ -170,7 +105,8 @@ public class MetadataTracker extends AbstractTracker implements Tracker
|
||||
indexNodes();
|
||||
}
|
||||
|
||||
public boolean hasMaintenance() throws Exception {
|
||||
public boolean hasMaintenance()
|
||||
{
|
||||
return transactionsToReindex.size() > 0 ||
|
||||
transactionsToIndex.size() > 0 ||
|
||||
transactionsToPurge.size() > 0 ||
|
||||
@@ -180,30 +116,11 @@ public class MetadataTracker extends AbstractTracker implements Tracker
|
||||
queriesToReindex.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void trackRepository() throws IOException, AuthenticationException, JSONException, EncoderException
|
||||
{
|
||||
log.debug("####### MetadataTracker trackRepository Start #######");
|
||||
checkShutdown();
|
||||
|
||||
if(!isMaster && isSlave)
|
||||
{
|
||||
// Dynamic registration
|
||||
/*
|
||||
* This section allows Solr's master/slave setup to be used with dynamic shard registration.
|
||||
* In this scenario the slave is polling a "tracking" Solr node. The code below calls
|
||||
* the repo to register the state of the node without pulling any real transactions from the repo.
|
||||
*
|
||||
* This allows the repo to register the replica so that it will be included in queries. But the slave Solr node
|
||||
* will pull its data from a "tracking" Solr node using Solr's master/slave replication, rather then tracking the repository.
|
||||
*
|
||||
*/
|
||||
ShardState shardstate = getShardState();
|
||||
client.getTransactions(0L, null, 0L, null, 0, shardstate);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check we are tracking the correct repository
|
||||
TrackerState state = super.getTrackerState();
|
||||
log.debug("####### MetadataTracker check CYCLE #######");
|
||||
@@ -233,67 +150,6 @@ public class MetadataTracker extends AbstractTracker implements Tracker
|
||||
trackTransactions();
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link ShardState}, as the name suggests, encapsulates/stores the state of the shard which hosts this
|
||||
* {@link MetadataTracker} instance.
|
||||
*
|
||||
* The {@link ShardState} is primarily used in two places:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Transaction tracking: (see {@link #trackTransactions()}): for pulling/tracking transactions from Alfresco</li>
|
||||
* <li>
|
||||
* DynamicSharding: when the {@link MetadataTracker} is running on a slave instance it doesn't actually act
|
||||
* as a tracker, it calls Alfresco to register the state of the node (the shard) without pulling any transactions.
|
||||
* As consequence of that, Alfresco will be aware about the shard which will be included in subsequent queries.
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @return the {@link ShardState} instance which stores the current state of the hosting shard.
|
||||
*/
|
||||
ShardState getShardState()
|
||||
{
|
||||
TrackerState transactionsTrackerState = super.getTrackerState();
|
||||
TrackerState changeSetsTrackerState =
|
||||
of(infoSrv.getAdminHandler())
|
||||
.map(AlfrescoCoreAdminHandler::getTrackerRegistry)
|
||||
.map(registry -> registry.getTrackerForCore(coreName, AclTracker.class))
|
||||
.map(Tracker::getTrackerState)
|
||||
.orElse(transactionsTrackerState);
|
||||
|
||||
HashMap<String, String> propertyBag = new HashMap<>();
|
||||
propertyBag.put("coreName", coreName);
|
||||
HashMap<String, String> extendedPropertyBag = new HashMap<>(propertyBag);
|
||||
updateShardProperty();
|
||||
|
||||
shardProperty.ifPresent(p -> extendedPropertyBag.putAll(docRouter.getProperties(p)));
|
||||
|
||||
return ShardStateBuilder.shardState()
|
||||
.withMaster(isMaster)
|
||||
.withLastUpdated(System.currentTimeMillis())
|
||||
.withLastIndexedChangeSetCommitTime(changeSetsTrackerState.getLastIndexedChangeSetCommitTime())
|
||||
.withLastIndexedChangeSetId(changeSetsTrackerState.getLastIndexedChangeSetId())
|
||||
.withLastIndexedTxCommitTime(transactionsTrackerState.getLastIndexedTxCommitTime())
|
||||
.withLastIndexedTxId(transactionsTrackerState.getLastIndexedTxId())
|
||||
.withPropertyBag(extendedPropertyBag)
|
||||
.withShardInstance()
|
||||
.withBaseUrl(infoSrv.getBaseUrl())
|
||||
.withPort(infoSrv.getPort())
|
||||
.withHostName(infoSrv.getHostName())
|
||||
.withShard()
|
||||
.withInstance(shardInstance)
|
||||
.withFloc()
|
||||
.withNumberOfShards(shardCount)
|
||||
.withAddedStoreRef(storeRef)
|
||||
.withTemplate(shardTemplate)
|
||||
.withHasContent(transformContent)
|
||||
.withShardMethod(ShardMethodEnum.getShardMethod(shardMethod))
|
||||
.withPropertyBag(propertyBag)
|
||||
.endFloc()
|
||||
.endShard()
|
||||
.endShardInstance()
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the first and last TX time
|
||||
* @param state the state of this tracker
|
||||
@@ -1032,24 +888,18 @@ public class MetadataTracker extends AbstractTracker implements Tracker
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public NodeReport checkNode(Long dbid)
|
||||
{
|
||||
NodeReport nodeReport = new NodeReport();
|
||||
nodeReport.setDbid(dbid);
|
||||
NodeReport nodeReport = super.checkNode(dbid);
|
||||
|
||||
// In DB
|
||||
|
||||
GetNodesParameters parameters = new GetNodesParameters();
|
||||
parameters.setFromNodeId(dbid);
|
||||
parameters.setToNodeId(dbid);
|
||||
List<Node> dbnodes;
|
||||
try
|
||||
{
|
||||
dbnodes = client.getNodes(parameters, 1);
|
||||
List<Node> dbnodes = client.getNodes(parameters, 1);
|
||||
if (dbnodes.size() == 1)
|
||||
{
|
||||
Node dbnode = dbnodes.get(0);
|
||||
@@ -1059,41 +909,31 @@ public class MetadataTracker extends AbstractTracker implements Tracker
|
||||
else
|
||||
{
|
||||
nodeReport.setDbNodeStatus(SolrApiNodeStatus.UNKNOWN);
|
||||
nodeReport.setDbTx(-1l);
|
||||
nodeReport.setDbTx(-1L);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
nodeReport.setDbNodeStatus(SolrApiNodeStatus.UNKNOWN);
|
||||
nodeReport.setDbTx(-2l);
|
||||
nodeReport.setDbTx(-2L);
|
||||
}
|
||||
catch (JSONException e)
|
||||
{
|
||||
nodeReport.setDbNodeStatus(SolrApiNodeStatus.UNKNOWN);
|
||||
nodeReport.setDbTx(-3l);
|
||||
nodeReport.setDbTx(-3L);
|
||||
}
|
||||
catch (AuthenticationException e1)
|
||||
{
|
||||
nodeReport.setDbNodeStatus(SolrApiNodeStatus.UNKNOWN);
|
||||
nodeReport.setDbTx(-4l);
|
||||
nodeReport.setDbTx(-4L);
|
||||
}
|
||||
|
||||
this.infoSrv.addCommonNodeReportInfo(nodeReport);
|
||||
|
||||
return nodeReport;
|
||||
}
|
||||
|
||||
public NodeReport checkNode(Node node)
|
||||
{
|
||||
NodeReport nodeReport = new NodeReport();
|
||||
nodeReport.setDbid(node.getId());
|
||||
|
||||
nodeReport.setDbNodeStatus(node.getStatus());
|
||||
nodeReport.setDbTx(node.getTxnId());
|
||||
|
||||
this.infoSrv.addCommonNodeReportInfo(nodeReport);
|
||||
|
||||
return nodeReport;
|
||||
return checkNode(node.getId());
|
||||
}
|
||||
|
||||
public List<Node> getFullNodesForDbTransaction(Long txid)
|
||||
@@ -1230,34 +1070,4 @@ public class MetadataTracker extends AbstractTracker implements Tracker
|
||||
{
|
||||
this.queriesToReindex.offer(query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given the field name, returns the name of the property definition.
|
||||
* If the property definition is not found, Empty optional is returned.
|
||||
*
|
||||
* @param field
|
||||
*
|
||||
* @return the name of the associated property definition if present, Optional.Empty() otherwise
|
||||
*
|
||||
*/
|
||||
public static Optional<QName> getShardProperty(String field)
|
||||
{
|
||||
if (StringUtils.isBlank(field))
|
||||
{
|
||||
throw new IllegalArgumentException("Sharding property " + SHARD_KEY_KEY + " has not been set.");
|
||||
}
|
||||
AlfrescoSolrDataModel dataModel = AlfrescoSolrDataModel.getInstance();
|
||||
NamespaceDAO namespaceDAO = dataModel.getNamespaceDAO();
|
||||
DictionaryService dictionaryService = dataModel.getDictionaryService(CMISStrictDictionaryService.DEFAULT);
|
||||
PropertyDefinition propertyDef = QueryParserUtils.matchPropertyDefinition("http://www.alfresco.org/model/content/1.0",
|
||||
namespaceDAO,
|
||||
dictionaryService,
|
||||
field);
|
||||
if (propertyDef == null)
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
return of(propertyDef.getName());
|
||||
}
|
||||
}
|
||||
|
||||
+14
-20
@@ -103,10 +103,10 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
public ModelTracker(String solrHome, Properties p, SOLRAPIClient client, String coreName,
|
||||
InformationServer informationServer)
|
||||
{
|
||||
super(p, client, coreName, informationServer, Tracker.Type.Model);
|
||||
super(p, client, coreName, informationServer, Tracker.Type.MODEL);
|
||||
String normalSolrHome = SolrResourceLoader.normalizeDir(solrHome);
|
||||
alfrescoModelDir = new File(ConfigUtil.locateProperty("solr.model.dir", normalSolrHome+"alfrescoModels"));
|
||||
log.info("Alfresco Model dir " + alfrescoModelDir);
|
||||
LOGGER.info("Alfresco Model dir " + alfrescoModelDir);
|
||||
if (!alfrescoModelDir.exists())
|
||||
{
|
||||
alfrescoModelDir.mkdir();
|
||||
@@ -115,12 +115,16 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
loadPersistedModels();
|
||||
}
|
||||
|
||||
public boolean hasMaintenance() {
|
||||
@Override
|
||||
public boolean hasMaintenance()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void maintenance() {
|
||||
|
||||
@Override
|
||||
public void maintenance()
|
||||
{
|
||||
// Nothing to be done here
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,7 +187,7 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
*/
|
||||
ModelTracker()
|
||||
{
|
||||
super(Tracker.Type.Model);
|
||||
super(Tracker.Type.MODEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,7 +197,7 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
int registeredSearcherCount = this.infoSrv.getRegisteredSearcherCount();
|
||||
if (registeredSearcherCount >= getMaxLiveSearchers())
|
||||
{
|
||||
log.info(".... skipping tracking registered searcher count = " + registeredSearcherCount);
|
||||
LOGGER.info(".... skipping tracking registered searcher count = " + registeredSearcherCount);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -203,7 +207,7 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
|
||||
public void trackModels(boolean onlyFirstTime) throws AuthenticationException, IOException, JSONException
|
||||
{
|
||||
boolean requiresWriteLock = false;
|
||||
boolean requiresWriteLock;
|
||||
modelLock.readLock().lock();
|
||||
try
|
||||
{
|
||||
@@ -264,17 +268,13 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
log.error("Model tracking failed for core: "+ coreName, t);
|
||||
LOGGER.error("Model tracking failed for core: "+ coreName, t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks models. Reflects changes and updates on disk copy
|
||||
*
|
||||
* @throws AuthenticationException
|
||||
* @throws IOException
|
||||
* @throws JSONException
|
||||
*/
|
||||
private void trackModelsImpl() throws AuthenticationException, IOException, JSONException
|
||||
{
|
||||
@@ -480,16 +480,10 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
}
|
||||
|
||||
return expandedQName;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param alfrescoModelDir
|
||||
* @param modelName
|
||||
*/
|
||||
private void removeMatchingModels(File alfrescoModelDir, QName modelName)
|
||||
{
|
||||
|
||||
final String prefix = modelName.toPrefixString(this.infoSrv.getNamespaceDAO()).replace(":", ".") + ".";
|
||||
final String postFix = ".xml";
|
||||
|
||||
@@ -540,7 +534,7 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
{
|
||||
loadedModels.add(modelName);
|
||||
}
|
||||
log.info("Loading model " + model.getName());
|
||||
LOGGER.info("Loading model " + model.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package org.alfresco.solr.tracker;
|
||||
|
||||
import static org.alfresco.solr.tracker.Tracker.Type.NODE_STATE_PUBLISHER;
|
||||
|
||||
import org.alfresco.httpclient.AuthenticationException;
|
||||
import org.alfresco.repo.index.shard.ShardState;
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.TrackerState;
|
||||
import org.alfresco.solr.client.SOLRAPIClient;
|
||||
import org.apache.commons.codec.EncoderException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Despite belonging to the Tracker ecosystem, this component is actually a publisher, which periodically informs
|
||||
* Alfresco about the state of the hosting slave core.
|
||||
* As the name suggests, this worker is scheduled only when the owning core acts as a slave.
|
||||
* It allows Solr's master/slave setup to be used with dynamic shard registration.
|
||||
*
|
||||
* In this scenario the slave is polling a "tracking" Solr node. The tracker below calls
|
||||
* the repo to register the state of the node without pulling any real transactions from the repo.
|
||||
*
|
||||
* This allows the repo to register the replica so that it will be included in queries. But the slave Solr node
|
||||
* will pull its data from a "tracking" Solr node using Solr's master/slave replication, rather then tracking the repository.
|
||||
*
|
||||
* @author Andrea Gazzarini
|
||||
* @since 1.5
|
||||
*/
|
||||
public class SlaveCoreStatePublisher extends CoreStatePublisher
|
||||
{
|
||||
public SlaveCoreStatePublisher(
|
||||
boolean isMaster,
|
||||
Properties coreProperties,
|
||||
SOLRAPIClient repositoryClient,
|
||||
String name,
|
||||
SolrInformationServer informationServer)
|
||||
{
|
||||
super(isMaster, coreProperties, repositoryClient, name, informationServer, NODE_STATE_PUBLISHER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTrack()
|
||||
{
|
||||
try
|
||||
{
|
||||
ShardState shardstate = getShardState();
|
||||
client.getTransactions(0L, null, 0L, null, 0, shardstate);
|
||||
}
|
||||
catch (EncoderException | IOException | AuthenticationException exception )
|
||||
{
|
||||
LOGGER.error("Unable to publish this node state. " +
|
||||
"A failure condition has been met during the outbound subscription message encoding process. " +
|
||||
"See the stacktrace below for further details.", exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maintenance()
|
||||
{
|
||||
// Do nothing here
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnMasterOrStandalone()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMaintenance()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* When running in a slave mode, we need to recreate the tracker state every time.
|
||||
* This because in that context we don't have any tracker updating the state (e.g. lastIndexedChangeSetCommitTime,
|
||||
* lastIndexedChangeSetId)
|
||||
*
|
||||
* @return a new, fresh and up to date instance of {@link TrackerState}.
|
||||
*/
|
||||
@Override
|
||||
public TrackerState getTrackerState()
|
||||
{
|
||||
return infoSrv.getTrackerInitialState();
|
||||
}
|
||||
}
|
||||
+16
-11
@@ -76,18 +76,20 @@ public class SolrTrackerScheduler
|
||||
{
|
||||
log.error("Failed to schedule " + jobType + " Job.", e);
|
||||
}
|
||||
|
||||
private String getCron(Properties props, String cronType)
|
||||
{
|
||||
String cron = props.getProperty(cronType);
|
||||
return cron == null ? props.getProperty("alfresco.cron",DEFAULT_CRON) : cron;
|
||||
return cron == null ? props.getProperty("alfresco.cron", DEFAULT_CRON) : cron;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules individual trackers based on the solrcore properties.
|
||||
*
|
||||
* @author Michael Suzuki
|
||||
* @param tracker
|
||||
* @param coreName
|
||||
* @param props
|
||||
* @param tracker the tracker to bo scheduled.
|
||||
* @param coreName the owning core name.
|
||||
* @param props the core properties.
|
||||
*/
|
||||
public void schedule(Tracker tracker, String coreName, Properties props)
|
||||
{
|
||||
@@ -98,27 +100,30 @@ public class SolrTrackerScheduler
|
||||
Trigger trigger;
|
||||
try
|
||||
{
|
||||
String cron = null;
|
||||
String cron;
|
||||
switch (tracker.getType())
|
||||
{
|
||||
case ACL:
|
||||
cron = getCron(props,"alfresco.acl.tracker.cron");
|
||||
break;
|
||||
case Model:
|
||||
case MODEL:
|
||||
cron = getCron(props,"alfresco.model.tracker.cron");
|
||||
break;
|
||||
case Content:
|
||||
case CONTENT:
|
||||
cron = getCron(props,"alfresco.content.tracker.cron");
|
||||
break;
|
||||
case MetaData:
|
||||
case METADATA:
|
||||
cron = getCron(props,"alfresco.metadata.tracker.cron");
|
||||
break;
|
||||
case Cascade:
|
||||
case CASCADE:
|
||||
cron = getCron(props,"alfresco.cascade.tracker.cron");
|
||||
break;
|
||||
case Commit:
|
||||
case COMMIT:
|
||||
cron = getCron(props,"alfresco.commit.tracker.cron");
|
||||
break;
|
||||
case NODE_STATE_PUBLISHER:
|
||||
cron = getCron(props,"alfresco.nodestate.tracker.cron");
|
||||
break;
|
||||
default:
|
||||
cron = props.getProperty("alfresco.cron",DEFAULT_CRON);
|
||||
break;
|
||||
@@ -161,7 +166,7 @@ public class SolrTrackerScheduler
|
||||
* identical to the instance that is passed in. If they are identical then the job is deleted.
|
||||
* Otherwise, another core (of the same name) scheduled this job, so its left alone.
|
||||
*
|
||||
* @param coreName
|
||||
* @param coreName the core name.
|
||||
* @param tracker Specific instance of a tracker
|
||||
*/
|
||||
public void deleteJobForTrackerInstance(String coreName, Tracker tracker)
|
||||
|
||||
+11
-7
@@ -36,7 +36,9 @@ public interface Tracker
|
||||
String getAlfrescoVersion();
|
||||
|
||||
void setShutdown(boolean shutdown);
|
||||
|
||||
|
||||
boolean isAlreadyInShutDownMode();
|
||||
|
||||
void shutdown();
|
||||
|
||||
boolean getRollback();
|
||||
@@ -51,12 +53,14 @@ public interface Tracker
|
||||
|
||||
Type getType();
|
||||
|
||||
enum Type{
|
||||
Model,
|
||||
Content,
|
||||
enum Type
|
||||
{
|
||||
MODEL,
|
||||
CONTENT,
|
||||
ACL,
|
||||
Cascade,
|
||||
Commit,
|
||||
MetaData
|
||||
CASCADE,
|
||||
COMMIT,
|
||||
METADATA,
|
||||
NODE_STATE_PUBLISHER
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2019 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.solr.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public abstract class Utils
|
||||
{
|
||||
/**
|
||||
* Returns the same input collection if that is not null, otherwise a new empty collection.
|
||||
* Provides a safe way for iterating over a returned collection (which could be null).
|
||||
*
|
||||
* @param values the collection.
|
||||
* @param <T> the collection type.
|
||||
* @return the same input collection if that is not null, otherwise a new empty collection.
|
||||
*/
|
||||
public static <T> Collection<T> notNullOrEmpty(Collection<T> values)
|
||||
{
|
||||
return values != null ? values : Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given input in an Integer, otherwise it returns null.
|
||||
*
|
||||
* @param value the numeric string.
|
||||
* @return the corresponding Integer or null in case the input is NaN.
|
||||
*/
|
||||
public static Integer toIntOrNull(String value)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Integer.valueOf(value);
|
||||
}
|
||||
catch(NumberFormatException nfe)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -87,7 +87,7 @@ import static org.alfresco.repo.search.adaptor.lucene.QueryConstants.FIELD_VERSI
|
||||
* @author Michael Suzuki
|
||||
*/
|
||||
@ThreadLeakLingering(linger = 5000)
|
||||
public abstract class AbstractAlfrescoDistributedTest extends SolrTestInitializer
|
||||
public abstract class AbstractAlfrescoDistributedIT extends SolrITInitializer
|
||||
{
|
||||
protected static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
@@ -760,8 +760,6 @@ public abstract class AbstractAlfrescoDistributedTest extends SolrTestInitialize
|
||||
params.remove("distrib");
|
||||
setDistributedParams(params);
|
||||
QueryResponse rsp = queryRandomShard(json, params);
|
||||
System.out.println("Cluster Response:"+rsp);
|
||||
System.out.println("Control Response:"+controlRsp);
|
||||
solrComparator.compareResponses(rsp, controlRsp);
|
||||
return rsp;
|
||||
}
|
||||
+3
-4
@@ -27,7 +27,6 @@ import org.alfresco.solr.client.NodeMetaData;
|
||||
import org.alfresco.solr.client.SOLRAPIQueueClient;
|
||||
import org.alfresco.solr.client.Transaction;
|
||||
import org.alfresco.solr.tracker.Tracker;
|
||||
import org.alfresco.util.SearchLanguageConversion;
|
||||
import org.apache.chemistry.opencmis.commons.impl.json.JSONArray;
|
||||
import org.apache.chemistry.opencmis.commons.impl.json.JSONObject;
|
||||
import org.apache.chemistry.opencmis.commons.impl.json.JSONValue;
|
||||
@@ -84,17 +83,17 @@ import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Base class that provides the solr test harness.
|
||||
* This is used to manage the embedded solr used for unit and integration testing.
|
||||
* This is used to manage the embedded solr used for integration testing.
|
||||
* The abstract also provides helper method that interacts with the
|
||||
* embedded solr.
|
||||
*
|
||||
* @author Michael Suzuki
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractAlfrescoSolrTests implements SolrTestFiles, AlfrescoSolrConstants
|
||||
public abstract class AbstractAlfrescoSolrIT implements SolrTestFiles, AlfrescoSolrConstants
|
||||
{
|
||||
static AlfrescoCoreAdminHandler admin;
|
||||
private static Log LOG = LogFactory.getLog(AbstractAlfrescoSolrTests.class);
|
||||
private static Log LOG = LogFactory.getLog(AbstractAlfrescoSolrIT.class);
|
||||
private static boolean CORE_NOT_YET_CREATED = true;
|
||||
|
||||
/**
|
||||
+2
-2
@@ -43,7 +43,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.*;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class AdminHandlerDistributedTest extends AbstractAlfrescoDistributedTest
|
||||
public class AdminHandlerDistributedIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
final String JETTY_SERVER_ID = this.getClass().getSimpleName();
|
||||
@@ -52,7 +52,7 @@ public class AdminHandlerDistributedTest extends AbstractAlfrescoDistributedTest
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
{
|
||||
initSolrServers(2, "AdminHandlerDistributedTest", null);
|
||||
initSolrServers(2, "AdminHandlerDistributedIT", null);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
+2
-1
@@ -11,7 +11,8 @@ import org.junit.Test;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class AdminHandlerTest extends AbstractAlfrescoSolrTests {
|
||||
public class AdminHandlerIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
|
||||
static CoreAdminHandler admin;
|
||||
|
||||
+179
-10
@@ -20,15 +20,23 @@ package org.alfresco.solr;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.alfresco.solr.AlfrescoCoreAdminHandler.ALFRESCO_CORE_NAME;
|
||||
import static org.alfresco.solr.AlfrescoCoreAdminHandler.ARCHIVE_CORE_NAME;
|
||||
import static org.alfresco.solr.AlfrescoCoreAdminHandler.ARG_TXID;
|
||||
import static org.alfresco.solr.AlfrescoCoreAdminHandler.STORE_REF_MAP;
|
||||
import static org.alfresco.solr.AlfrescoCoreAdminHandler.VERSION_CORE_NAME;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -42,13 +50,18 @@ import java.util.stream.Collectors;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.solr.adapters.IOpenBitSet;
|
||||
import org.alfresco.solr.tracker.AclTracker;
|
||||
import org.alfresco.solr.tracker.DocRouter;
|
||||
import org.alfresco.solr.tracker.IndexHealthReport;
|
||||
import org.alfresco.solr.tracker.MetadataTracker;
|
||||
import org.alfresco.solr.tracker.PropertyRouter;
|
||||
import org.alfresco.solr.tracker.SlaveCoreStatePublisher;
|
||||
import org.alfresco.solr.tracker.TrackerRegistry;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.params.CoreAdminParams;
|
||||
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.SolrCore;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.junit.Before;
|
||||
@@ -60,7 +73,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
/** Unit tests for {@link org.alfresco.solr.AlfrescoCoreAdminHandler}. */
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AlfrescoCoreAdminHandlerTest
|
||||
public class AlfrescoCoreAdminHandlerIT
|
||||
{
|
||||
/** The string representing a transaction report. */
|
||||
private static final String TXREPORT = "TXREPORT";
|
||||
@@ -105,6 +118,169 @@ public class AlfrescoCoreAdminHandlerTest
|
||||
when(req.getParams()).thenReturn(params);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractShardsWithEmptyParameter_shouldReturnAnEmptyList()
|
||||
{
|
||||
assertTrue(alfrescoCoreAdminHandler.extractShards("", Integer.MAX_VALUE).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractShardsWithNullParameter_shouldReturnAnEmptyList()
|
||||
{
|
||||
assertTrue(alfrescoCoreAdminHandler.extractShards(null, Integer.MAX_VALUE).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractShardsWithOneInvalidShard_shouldReturnAnEmptyList()
|
||||
{
|
||||
assertTrue(alfrescoCoreAdminHandler.extractShards("This is an invalid shard id", Integer.MAX_VALUE).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractShardsWithOneShards_shouldReturnSingletonList()
|
||||
{
|
||||
assertEquals(singletonList(1), alfrescoCoreAdminHandler.extractShards("1", Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractShardsWithSeveralValidShards_shouldReturnAllOfThemInTheList()
|
||||
{
|
||||
assertEquals(asList(1,5,6,11,23), alfrescoCoreAdminHandler.extractShards("1,5,6,11,23", Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractShardsWithSeveralValidShards_shouldReturnOnlyValidIdentifiers()
|
||||
{
|
||||
assertEquals(asList(1,5,6,11,23), alfrescoCoreAdminHandler.extractShards("1,5,A,6,xyz,11,BB,23,o01z", Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractShardsWithSeveralValidShardsAndLimit_shouldConsiderOnlyShardsLesserThanLimit()
|
||||
{
|
||||
assertEquals(asList(1,5,6,11,12), alfrescoCoreAdminHandler.extractShards("1,5,6,11,23,25,99,223,12", 23));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAlfrescoCoreWhenInputIsNull_shouldReturnFalse()
|
||||
{
|
||||
assertFalse(alfrescoCoreAdminHandler.hasAlfrescoCore(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAlfrescoCoreWhenWeHaveNoCore_shouldReturnFalse()
|
||||
{
|
||||
assertFalse(alfrescoCoreAdminHandler.hasAlfrescoCore(emptyList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAlfrescoCoreWhenDoesntHaveAnyTracker_shouldReturnFalse()
|
||||
{
|
||||
assertFalse(alfrescoCoreAdminHandler.hasAlfrescoCore(emptyList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAlfrescoCoreWithRegisteredTrackers_shouldReturnTrue()
|
||||
{
|
||||
when(trackerRegistry.hasTrackersForCore("CoreD")).thenReturn(true);
|
||||
assertTrue(alfrescoCoreAdminHandler.hasAlfrescoCore(asList(dummyCore("CoreA"), dummyCore("CoreB"), dummyCore("CoreC"), dummyCore("CoreD"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trackerRegistryHasNoCoreNames_itShouldReturnAnEmptyList()
|
||||
{
|
||||
assertTrue(alfrescoCoreAdminHandler.coreNames().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void coreDetectedAsMasterOrStandalone()
|
||||
{
|
||||
MetadataTracker coreStatePublisher = mock(MetadataTracker.class);
|
||||
|
||||
when(trackerRegistry.getTrackerForCore(anyString(), eq(MetadataTracker.class)))
|
||||
.thenReturn(coreStatePublisher);
|
||||
|
||||
assertTrue(alfrescoCoreAdminHandler.isMasterOrStandalone("ThisIsTheCoreName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void coreDetectedAsSlave()
|
||||
{
|
||||
when(trackerRegistry.getTrackerForCore(anyString(), eq(MetadataTracker.class))).thenReturn(null);
|
||||
assertFalse(alfrescoCoreAdminHandler.isMasterOrStandalone("ThisIsTheCoreName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void coreIsMaster_thenCoreStatePublisherInstanceCorrespondsToMetadataTracker()
|
||||
{
|
||||
MetadataTracker coreStatePublisher = mock(MetadataTracker.class);
|
||||
|
||||
when(trackerRegistry.getTrackerForCore(anyString(), eq(MetadataTracker.class)))
|
||||
.thenReturn(coreStatePublisher);
|
||||
|
||||
assertSame(coreStatePublisher, alfrescoCoreAdminHandler.coreStatePublisher("ThisIsTheCoreName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void coreIsSlave_thenCoreStatePublisherInstanceCorrespondsToSlaveCoreStatePublisher()
|
||||
{
|
||||
SlaveCoreStatePublisher coreStatePublisher = mock(SlaveCoreStatePublisher.class);
|
||||
|
||||
when(trackerRegistry.getTrackerForCore(anyString(), eq(MetadataTracker.class))).thenReturn(null);
|
||||
when(trackerRegistry.getTrackerForCore(anyString(), eq(SlaveCoreStatePublisher.class))).thenReturn(coreStatePublisher);
|
||||
|
||||
assertSame(coreStatePublisher, alfrescoCoreAdminHandler.coreStatePublisher("ThisIsTheCoreName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void coreIsSlave_thenDocRouterIsNull()
|
||||
{
|
||||
String coreName = "aCore";
|
||||
when(trackerRegistry.getTrackerForCore(eq(coreName), eq(MetadataTracker.class))).thenReturn(null);
|
||||
assertNull(alfrescoCoreAdminHandler.getDocRouter("aCore"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void coreIsMaster_thenDocRouterIsProperlyReturned()
|
||||
{
|
||||
DocRouter expectedRouter = new PropertyRouter("someProperty_.{1,35}");
|
||||
|
||||
MetadataTracker coreStatePublisher = mock(MetadataTracker.class);
|
||||
when(coreStatePublisher.getDocRouter()).thenReturn(expectedRouter);
|
||||
when(trackerRegistry.getTrackerForCore(anyString(), eq(MetadataTracker.class))).thenReturn(coreStatePublisher);
|
||||
|
||||
assertSame(expectedRouter, alfrescoCoreAdminHandler.getDocRouter("aCore"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void targetCoreNameCanBeSpecifiedInSeveralWays()
|
||||
{
|
||||
String coreName = "ThisIsTheCoreName";
|
||||
|
||||
ModifiableSolrParams params = new ModifiableSolrParams();
|
||||
|
||||
assertNull(alfrescoCoreAdminHandler.coreName(params));
|
||||
|
||||
params.set(CoreAdminParams.CORE, coreName);
|
||||
|
||||
assertEquals(coreName, alfrescoCoreAdminHandler.coreName(params));
|
||||
|
||||
params.remove(CoreAdminParams.CORE);
|
||||
assertNull(alfrescoCoreAdminHandler.coreName(params));
|
||||
|
||||
params.set("coreName", coreName);
|
||||
|
||||
assertEquals(coreName, alfrescoCoreAdminHandler.coreName(params));
|
||||
assertEquals(coreName, alfrescoCoreAdminHandler.coreName(params));
|
||||
}
|
||||
|
||||
|
||||
private SolrCore dummyCore(String name)
|
||||
{
|
||||
SolrCore core = mock(SolrCore.class);
|
||||
when(core.getName()).thenReturn(name);
|
||||
return core;
|
||||
}
|
||||
|
||||
/** Check that a transaction report can be generated. */
|
||||
@Test
|
||||
public void handleCustomActionTXReportSuccess() throws Exception
|
||||
@@ -143,8 +319,6 @@ public class AlfrescoCoreAdminHandlerTest
|
||||
public void handleCustomActionTXReportMissingTXId()
|
||||
{
|
||||
when(params.get(CoreAdminParams.ACTION)).thenReturn(TXREPORT);
|
||||
when(params.get(ARG_TXID)).thenReturn(null);
|
||||
|
||||
alfrescoCoreAdminHandler.handleCustomAction(req, rsp);
|
||||
|
||||
verify(rsp, never()).add(anyString(), any());
|
||||
@@ -156,11 +330,8 @@ public class AlfrescoCoreAdminHandlerTest
|
||||
{
|
||||
when(params.get(CoreAdminParams.ACTION)).thenReturn(TXREPORT);
|
||||
when(params.get(CoreAdminParams.CORE)).thenReturn(null);
|
||||
when(params.get(ARG_TXID)).thenReturn(TX_ID);
|
||||
|
||||
alfrescoCoreAdminHandler.handleCustomAction(req, rsp);
|
||||
|
||||
verify(rsp, never()).add(anyString(), any());
|
||||
}
|
||||
|
||||
/** Check that when an unknown action is provided we don't generate a report. */
|
||||
@@ -212,10 +383,9 @@ public class AlfrescoCoreAdminHandlerTest
|
||||
public void coreNamesAreTrimmed_oneCoreNameAtTime() {
|
||||
AlfrescoCoreAdminHandler spy = spy(new AlfrescoCoreAdminHandler() {
|
||||
@Override
|
||||
protected boolean newCore(String coreName, int numShards, StoreRef storeRef, String templateName, int replicationFactor, int nodeInstance, int numNodes, String shardIds, Properties extraProperties, SolrQueryResponse rsp)
|
||||
protected void newCore(String coreName, int numShards, StoreRef storeRef, String templateName, int replicationFactor, int nodeInstance, int numNodes, String shardIds, Properties extraProperties, SolrQueryResponse rsp)
|
||||
{
|
||||
// Do nothing here otherwise we cannot spy it
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -238,10 +408,9 @@ public class AlfrescoCoreAdminHandlerTest
|
||||
public void validAndInvalidCoreNames() {
|
||||
AlfrescoCoreAdminHandler spy = spy(new AlfrescoCoreAdminHandler() {
|
||||
@Override
|
||||
protected boolean newCore(String coreName, int numShards, StoreRef storeRef, String templateName, int replicationFactor, int nodeInstance, int numNodes, String shardIds, Properties extraProperties, SolrQueryResponse rsp)
|
||||
protected void newCore(String coreName, int numShards, StoreRef storeRef, String templateName, int replicationFactor, int nodeInstance, int numNodes, String shardIds, Properties extraProperties, SolrQueryResponse rsp)
|
||||
{
|
||||
// Do nothing here otherwise we cannot spy it
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
+3
-2
@@ -37,8 +37,9 @@ import org.quartz.SchedulerException;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class AlfrescoSolrReloadTest extends AbstractAlfrescoSolrTests {
|
||||
private static Log logger = LogFactory.getLog(org.alfresco.solr.tracker.AlfrescoSolrTrackerTest.class);
|
||||
public class AlfrescoSolrReloadIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(org.alfresco.solr.tracker.AlfrescoSolrTrackerIT.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
+1
-1
@@ -77,7 +77,7 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests.SolrServletRequest;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT.SolrServletRequest;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class AlfrescoTrackerRegistrationTest extends AbstractAlfrescoSolrTests
|
||||
public class AlfrescoTrackerRegistrationIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
+1
-1
@@ -51,7 +51,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.getCore;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class CoresCreateUpdateDistributedTest extends AbstractAlfrescoDistributedTest
|
||||
public class CoresCreateUpdateDistributedIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
final static String JETTY_SERVER_ID = "CoresCreateUpdateDistributedTest";
|
||||
+1
-1
@@ -40,7 +40,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.getCore;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class CoresCreateViaPropertyTest extends AbstractAlfrescoDistributedTest
|
||||
public class CoresCreateViaPropertyIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
final static String JETTY_SERVER_ID = "CoresCreateViaPropertyTest";
|
||||
-75
@@ -72,79 +72,4 @@ public class SolrDataModelTest
|
||||
Long actualId = AlfrescoSolrDataModel.parseTransactionId(id);
|
||||
assertEquals(expectedId, actualId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void smokeTestCMISModel()
|
||||
{
|
||||
AlfrescoSolrDataModel dataModel = new AlfrescoSolrDataModel();
|
||||
|
||||
// load test model containing content properties multiple
|
||||
ClassLoader cl = SolrDataModelTest.class.getClassLoader();
|
||||
InputStream modelStream = cl.getResourceAsStream("alfresco/model/dictionaryModel.xml");
|
||||
|
||||
assertNotNull(modelStream);
|
||||
M2Model model = M2Model.createModel(modelStream);
|
||||
dataModel.putModel(model);
|
||||
|
||||
modelStream = cl.getResourceAsStream("alfresco/model/cmisModel.xml");
|
||||
assertNotNull(modelStream);
|
||||
model = M2Model.createModel(modelStream);
|
||||
dataModel.putModel(model);
|
||||
|
||||
assertEquals(2, dataModel.getAlfrescoModels().size());
|
||||
|
||||
assertEquals(1, dataModel.getIndexedFieldNamesForProperty(OBJECT_ID).getFields().size());
|
||||
assertEquals(4, dataModel.getIndexedFieldNamesForProperty(NAME).getFields().size());
|
||||
assertEquals(1, dataModel.getIndexedFieldNamesForProperty(CREATION_DATE).getFields().size());
|
||||
assertEquals(0, dataModel.getIndexedFieldNamesForProperty(IS_IMMUTABLE).getFields().size());
|
||||
assertEquals(0, dataModel.getIndexedFieldNamesForProperty(IS_PRIVATE_WOKING_COPY).getFields().size());
|
||||
assertEquals(1, dataModel.getIndexedFieldNamesForProperty(CONTENT_STREAM_LENGTH).getFields().size());
|
||||
|
||||
assertEquals(1, dataModel .getQueryableFields(OBJECT_ID, null, FieldUse.FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(OBJECT_ID, null, FieldUse.COMPLETION).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(OBJECT_ID, null, FieldUse.FTS).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(OBJECT_ID, null, FieldUse.ID).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(OBJECT_ID, null, FieldUse.MULTI_FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(OBJECT_ID, null, FieldUse.SORT).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(OBJECT_ID, null, FieldUse.STATS).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(OBJECT_ID, null, FieldUse.SUGGESTION).getFields().size());
|
||||
|
||||
assertEquals(1, dataModel .getQueryableFields(NAME, null, FieldUse.FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(NAME, null, FieldUse.COMPLETION).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(NAME, null, FieldUse.FTS).getFields().size());
|
||||
assertEquals(2, dataModel .getQueryableFields(NAME, null, FieldUse.ID).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(NAME, null, FieldUse.MULTI_FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(NAME, null, FieldUse.SORT).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(NAME, null, FieldUse.STATS).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(NAME, null, FieldUse.SUGGESTION).getFields().size());
|
||||
|
||||
assertEquals(1, dataModel .getQueryableFields(CREATION_DATE, null, FieldUse.FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CREATION_DATE, null, FieldUse.COMPLETION).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CREATION_DATE, null, FieldUse.FTS).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CREATION_DATE, null, FieldUse.ID).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CREATION_DATE, null, FieldUse.MULTI_FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CREATION_DATE, null, FieldUse.SORT).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CREATION_DATE, null, FieldUse.STATS).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CREATION_DATE, null, FieldUse.SUGGESTION).getFields().size());
|
||||
|
||||
assertEquals(1, dataModel .getQueryableFields(IS_PRIVATE_WOKING_COPY, null, FieldUse.FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(IS_PRIVATE_WOKING_COPY, null, FieldUse.COMPLETION).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(IS_PRIVATE_WOKING_COPY, null, FieldUse.FTS).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(IS_PRIVATE_WOKING_COPY, null, FieldUse.ID).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(IS_PRIVATE_WOKING_COPY, null, FieldUse.MULTI_FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(IS_PRIVATE_WOKING_COPY, null, FieldUse.SORT).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(IS_PRIVATE_WOKING_COPY, null, FieldUse.STATS).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(IS_PRIVATE_WOKING_COPY, null, FieldUse.SUGGESTION).getFields().size());
|
||||
|
||||
assertEquals(1, dataModel .getQueryableFields(CONTENT_STREAM_LENGTH, null, FieldUse.FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CONTENT_STREAM_LENGTH, null, FieldUse.COMPLETION).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CONTENT_STREAM_LENGTH, null, FieldUse.FTS).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CONTENT_STREAM_LENGTH, null, FieldUse.ID).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CONTENT_STREAM_LENGTH, null, FieldUse.MULTI_FACET).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CONTENT_STREAM_LENGTH, null, FieldUse.SORT).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CONTENT_STREAM_LENGTH, null, FieldUse.STATS).getFields().size());
|
||||
assertEquals(1, dataModel .getQueryableFields(CONTENT_STREAM_LENGTH, null, FieldUse.SUGGESTION).getFields().size());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.createCoreUsingTemplate;
|
||||
* @author Michael Suzuki
|
||||
*/
|
||||
@ThreadLeakLingering(linger = 5000)
|
||||
public abstract class SolrTestInitializer extends SolrTestCaseJ4
|
||||
public abstract class SolrITInitializer extends SolrTestCaseJ4
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.*;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class TemplatesDistributedTest extends AbstractAlfrescoDistributedTest
|
||||
public class TemplatesDistributedIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
final static String JETTY_SERVER_ID = "TemplatesDistributedTest";
|
||||
+3
-3
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
package org.alfresco.solr.highlight;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
@@ -35,9 +35,9 @@ import org.junit.Test;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class AlfrescoHighligherDistributedTest extends AbstractAlfrescoDistributedTest
|
||||
public class AlfrescoHighligherDistributedIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(AlfrescoHighligherDistributedTest.class);
|
||||
private static Log logger = LogFactory.getLog(AlfrescoHighligherDistributedIT.class);
|
||||
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
+4
-20
@@ -22,13 +22,9 @@ package org.alfresco.solr.highlight;
|
||||
import java.util.Map;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AlfrescoCoreAdminHandler;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.alfresco.solr.client.*;
|
||||
import org.alfresco.solr.dataload.TestDataProvider;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.index.Term;
|
||||
@@ -37,39 +33,27 @@ import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
import org.apache.solr.common.params.HighlightParams;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.response.BasicResultContext;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.of;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.stream.IntStream.range;
|
||||
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.alfresco.model.ContentModel.PROP_CREATOR;
|
||||
import static org.alfresco.model.ContentModel.PROP_RATING_SCHEME;
|
||||
import static org.alfresco.model.ContentModel.TYPE_CONTENT;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.*;
|
||||
import static org.apache.solr.SolrJettyTestBase.jetty;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class AlfrescoHighlighterTest extends AbstractAlfrescoSolrTests
|
||||
public class AlfrescoHighlighterIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(AlfrescoHighlighterTest.class);
|
||||
private static Log logger = LogFactory.getLog(AlfrescoHighlighterIT.class);
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
|
||||
@BeforeClass
|
||||
-176
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.alfresco.solr.highlight;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.handler.component.AlfrescoSolrHighlighter;
|
||||
import org.apache.solr.handler.component.HighlightComponent;
|
||||
import org.apache.solr.highlight.PostingsSolrHighlighter;
|
||||
import org.apache.solr.highlight.SolrHighlighter;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.TestCase.*;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class TestPostingsSolrHighlighter extends AbstractAlfrescoSolrTests
|
||||
{
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
{
|
||||
initAlfrescoCore("schema.xml");
|
||||
// test our config is sane, just to be sure:
|
||||
|
||||
// postingshighlighter should be used
|
||||
SolrHighlighter highlighter = HighlightComponent.getHighlighter(getCore());
|
||||
assertTrue("wrong highlighter: " + highlighter.getClass(), highlighter instanceof AlfrescoSolrHighlighter);
|
||||
|
||||
// 'text' and 'text3' should have offsets, 'text2' should not
|
||||
IndexSchema schema = getCore().getLatestSchema();
|
||||
assertTrue(schema.getField("text").storeOffsetsWithPositions());
|
||||
assertTrue(schema.getField("text3").storeOffsetsWithPositions());
|
||||
assertFalse(schema.getField("text2").storeOffsetsWithPositions());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
|
||||
// if you override setUp or tearDown, you better call
|
||||
// the super classes version
|
||||
clearIndex();
|
||||
assertU(adoc("text", "document one", "text2", "document one", "text3", "crappy document", "id", "101"));
|
||||
assertU(adoc("text", "second document", "text2", "second document", "text3", "crappier document", "id", "102"));
|
||||
assertU(commit());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimple() {
|
||||
assertQ("simplest test",
|
||||
req("q", "text:document", "sort", "id asc", "hl", "true"),
|
||||
"count(//lst[@name='highlighting']/*)=2",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text']/str='<em>document</em> one'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text']/str='second <em>document</em>'");
|
||||
}
|
||||
|
||||
public void testPagination() {
|
||||
assertQ("pagination test",
|
||||
req("q", "text:document", "sort", "id asc", "hl", "true", "rows", "1", "start", "1"),
|
||||
"count(//lst[@name='highlighting']/*)=1",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text']/str='second <em>document</em>'");
|
||||
}
|
||||
|
||||
public void testEmptySnippet() {
|
||||
assertQ("null snippet test",
|
||||
req("q", "text:one OR *:*", "sort", "id asc", "hl", "true"),
|
||||
"count(//lst[@name='highlighting']/*)=2",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text']/str='document <em>one</em>'",
|
||||
"count(//lst[@name='highlighting']/lst[@name='102']/arr[@name='text']/*)=0");
|
||||
}
|
||||
|
||||
public void testDefaultSummary() {
|
||||
assertQ("null snippet test",
|
||||
req("q", "text:one OR *:*", "sort", "id asc", "hl", "true", "hl.defaultSummary", "true"),
|
||||
"count(//lst[@name='highlighting']/*)=2",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text']/str='document <em>one</em>'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text']/str='second document'");
|
||||
}
|
||||
|
||||
public void testDifferentField() {
|
||||
assertQ("highlighting text3",
|
||||
req("q", "text3:document", "sort", "id asc", "hl", "true", "hl.fl", "text3"),
|
||||
"count(//lst[@name='highlighting']/*)=2",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text3']/str='crappy <em>document</em>'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text3']/str='crappier <em>document</em>'");
|
||||
}
|
||||
|
||||
public void testTwoFields() {
|
||||
assertQ("highlighting text and text3",
|
||||
req("q", "text:document text3:document", "sort", "id asc", "hl", "true", "hl.fl", "text,text3"),
|
||||
"count(//lst[@name='highlighting']/*)=2",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text']/str='<em>document</em> one'",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text3']/str='crappy <em>document</em>'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text']/str='second <em>document</em>'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text3']/str='crappier <em>document</em>'");
|
||||
}
|
||||
/**
|
||||
public void testMisconfiguredField() {
|
||||
ignoreException("was indexed without offsets");
|
||||
try {
|
||||
assertQ("should fail, has no offsets",
|
||||
req("q", "text2:document", "sort", "id asc", "hl", "true", "hl.fl", "text2"));
|
||||
fail();
|
||||
} catch (Exception expected) {
|
||||
// expected
|
||||
}
|
||||
resetExceptionIgnores();
|
||||
}
|
||||
**/
|
||||
public void testTags() {
|
||||
assertQ("different pre/post tags",
|
||||
req("q", "text:document", "sort", "id asc", "hl", "true", "hl.tag.pre", "[", "hl.tag.post", "]"),
|
||||
"count(//lst[@name='highlighting']/*)=2",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text']/str='[document] one'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text']/str='second [document]'");
|
||||
}
|
||||
|
||||
public void testTagsPerField() {
|
||||
assertQ("highlighting text and text3",
|
||||
req("q", "text:document text3:document", "sort", "id asc", "hl", "true", "hl.fl", "text,text3", "f.text3.hl.tag.pre", "[", "f.text3.hl.tag.post", "]"),
|
||||
"count(//lst[@name='highlighting']/*)=2",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text']/str='<em>document</em> one'",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text3']/str='crappy [document]'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text']/str='second <em>document</em>'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text3']/str='crappier [document]'");
|
||||
}
|
||||
|
||||
public void testBreakIterator() {
|
||||
assertQ("different breakiterator",
|
||||
req("q", "text:document", "sort", "id asc", "hl", "true", "hl.bs.type", "WORD"),
|
||||
"count(//lst[@name='highlighting']/*)=2",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text']/str='<em>document</em>'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text']/str='<em>document</em>'");
|
||||
}
|
||||
|
||||
public void testBreakIterator2() {
|
||||
assertU(adoc("text", "Document one has a first sentence. Document two has a second sentence.", "id", "103"));
|
||||
assertU(commit());
|
||||
assertQ("different breakiterator",
|
||||
req("q", "text:document", "sort", "id asc", "hl", "true", "hl.bs.type", "WHOLE"),
|
||||
"//lst[@name='highlighting']/lst[@name='103']/arr[@name='text']/str='<em>Document</em> one has a first sentence. <em>Document</em> two has a second sentence.'");
|
||||
}
|
||||
|
||||
public void testEncoder() {
|
||||
assertU(adoc("text", "Document one has a first <i>sentence</i>.", "id", "103"));
|
||||
assertU(commit());
|
||||
assertQ("html escaped",
|
||||
req("q", "text:document", "sort", "id asc", "hl", "true", "hl.encoder", "html"),
|
||||
"//lst[@name='highlighting']/lst[@name='103']/arr[@name='text']/str='<em>Document</em> one has a first <i>sentence</i>.'");
|
||||
}
|
||||
|
||||
public void testWildcard() {
|
||||
assertQ("simplest test",
|
||||
req("q", "text:doc*ment", "sort", "id asc", "hl", "true", "hl.highlightMultiTerm", "true"),
|
||||
"count(//lst[@name='highlighting']/*)=2",
|
||||
"//lst[@name='highlighting']/lst[@name='101']/arr[@name='text']/str='<em>document</em> one'",
|
||||
"//lst[@name='highlighting']/lst[@name='102']/arr[@name='text']/str='second <em>document</em>'");
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.solr.lifecycle;
|
||||
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.client.SOLRAPIClient;
|
||||
import org.alfresco.solr.tracker.AclTracker;
|
||||
import org.alfresco.solr.tracker.CascadeTracker;
|
||||
import org.alfresco.solr.tracker.ContentTracker;
|
||||
import org.alfresco.solr.tracker.MetadataTracker;
|
||||
import org.alfresco.solr.tracker.SolrTrackerScheduler;
|
||||
import org.alfresco.solr.tracker.Tracker;
|
||||
import org.alfresco.solr.tracker.TrackerRegistry;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link SolrCoreLoadListener}.
|
||||
*
|
||||
* @author Andrea Gazzarini
|
||||
* @since 1.5
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SolrCoreLoadListenerTest
|
||||
{
|
||||
private SolrCoreLoadListener listener;
|
||||
|
||||
@Mock
|
||||
private SolrCore core;
|
||||
|
||||
@Mock
|
||||
private SolrTrackerScheduler scheduler;
|
||||
|
||||
@Mock
|
||||
private SOLRAPIClient api;
|
||||
|
||||
@Mock
|
||||
private SolrInformationServer informationServer;
|
||||
|
||||
@Mock
|
||||
private TrackerRegistry registry;
|
||||
|
||||
private Properties coreProperties;
|
||||
|
||||
private String coreName = "XYZ";
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
listener = new SolrCoreLoadListener(core);
|
||||
when(core.getName()).thenReturn(coreName);
|
||||
|
||||
coreProperties = new Properties();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void coreTrackersRegistrationAndScheduling()
|
||||
{
|
||||
List<Tracker> coreTrackers = listener.createAndScheduleCoreTrackers(core, registry, coreProperties, scheduler, api, informationServer);
|
||||
|
||||
verify(registry).register(eq(coreName), any(AclTracker.class));
|
||||
verify(registry).register(eq(coreName), any(ContentTracker.class));
|
||||
verify(registry).register(eq(coreName), any(MetadataTracker.class));
|
||||
verify(registry).register(eq(coreName), any(CascadeTracker.class));
|
||||
|
||||
verify(scheduler).schedule(any(AclTracker.class), eq(coreName), same(coreProperties));
|
||||
verify(scheduler).schedule(any(ContentTracker.class), eq(coreName), same(coreProperties));
|
||||
verify(scheduler).schedule(any(MetadataTracker.class), eq(coreName), same(coreProperties));
|
||||
verify(scheduler).schedule(any(CascadeTracker.class), eq(coreName), same(coreProperties));
|
||||
|
||||
assertEquals(4, coreTrackers.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trackersShutDownProcedure()
|
||||
{
|
||||
List<Tracker> coreTrackers =
|
||||
asList(mock(AclTracker.class), mock(ContentTracker.class), mock(MetadataTracker.class), mock(CascadeTracker.class));
|
||||
|
||||
listener.shutdownTrackers(core, coreTrackers, scheduler, false);
|
||||
|
||||
coreTrackers.forEach(tracker -> verify(tracker).setShutdown(true));
|
||||
coreTrackers.forEach(tracker -> verify(scheduler).deleteJobForTrackerInstance(core.getName(), tracker));
|
||||
coreTrackers.forEach(tracker -> verify(tracker).shutdown());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noReplicationHandlerDefined_thenContentStoreIsInReadWriteMode() throws Exception
|
||||
{
|
||||
prepare("solrconfig_no_replication_handler_defined.xml");
|
||||
assertFalse("If no replication handler is defined, then we expect to run a RW content store.", listener.isSlaveModeEnabledFor(core));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyReplicationHandlerDefined_thenContentStoreIsInReadWriteMode() throws Exception
|
||||
{
|
||||
prepare("solrconfig_empty_replication_handler.xml");
|
||||
assertFalse("If an empty replication handler is defined, then we expect to run a RW content store.", listener.isSlaveModeEnabledFor(core));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void slaveReplicationHandlerDefinedButDisabled_thenContentStoreIsInReadWriteMode() throws Exception
|
||||
{
|
||||
prepare("solrconfig_slave_disabled_replication_handler.xml");
|
||||
assertFalse("If a slave replication handler is defined but disabled, then we expect to run a RW content store.", listener.isSlaveModeEnabledFor(core));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void masterReplicationHandlerDefined_thenContentStoreIsInReadWriteMode() throws Exception
|
||||
{
|
||||
prepare("solrconfig_master_replication_handler.xml");
|
||||
assertFalse("If a master replication handler is defined but disabled, then we expect to run a RW content store.", listener.isSlaveModeEnabledFor(core));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void masterReplicationHandlerDefinedButDisabled_thenContentStoreIsInReadWriteMode() throws Exception
|
||||
{
|
||||
prepare("solrconfig_master_disabled_replication_handler.xml");
|
||||
assertFalse("If a master replication handler is defined but disabled, then we expect to run a RW content store.", listener.isSlaveModeEnabledFor(core));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void slaveReplicationHandlerDefined_thenContentStoreIsInReadOnlyMode() throws Exception
|
||||
{
|
||||
prepare("solrconfig_slave_replication_handler.xml");
|
||||
assertTrue("If a slave replication handler is defined, then we expect to run a RO content store.", listener.isSlaveModeEnabledFor(core));
|
||||
}
|
||||
|
||||
private void prepare(String configName) throws Exception
|
||||
{
|
||||
SolrConfig solrConfig = new SolrConfig(configName, new InputSource(getClass().getResourceAsStream("/test-files/" + configName)));
|
||||
when(core.getSolrConfig()).thenReturn(solrConfig);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -22,7 +22,7 @@ package org.alfresco.solr.query;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
@@ -38,7 +38,7 @@ import org.junit.Test;
|
||||
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class AlfrescoReRankQParserPluginTest extends AbstractAlfrescoSolrTests
|
||||
public class AlfrescoReRankQParserPluginIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
+2
-2
@@ -21,7 +21,7 @@ package org.alfresco.solr.query;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
@@ -51,7 +51,7 @@ import static java.util.Collections.singletonList;
|
||||
import static java.util.stream.IntStream.range;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.*;
|
||||
|
||||
public class AlfrescoSolrFingerprintTest extends AbstractAlfrescoSolrTests
|
||||
public class AlfrescoSolrFingerprintIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
|
||||
+2
-16
@@ -19,31 +19,17 @@
|
||||
|
||||
package org.alfresco.solr.query;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.RefCount;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.ResultContext;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.search.DocIterator;
|
||||
import org.apache.solr.search.DocList;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
import org.apache.solr.util.RefCounted;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class AlfrescoSolrSpellcheckerTest extends AbstractAlfrescoSolrTests
|
||||
public class AlfrescoSolrSpellcheckerIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
+2
-2
@@ -34,7 +34,7 @@ import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.alfresco.solr.client.ContentPropertyValue;
|
||||
import org.alfresco.solr.client.MLTextPropertyValue;
|
||||
import org.alfresco.solr.client.PropertyValue;
|
||||
@@ -46,7 +46,7 @@ import org.junit.BeforeClass;
|
||||
* @author Michael Suzuki
|
||||
*
|
||||
*/
|
||||
public class AuthDataLoad extends AbstractAlfrescoSolrTests
|
||||
public class AuthDataLoad extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
static int count = 100;
|
||||
static long maxReader = 1000;
|
||||
|
||||
+1
-2
@@ -39,7 +39,7 @@ import org.junit.Test;
|
||||
* @author Michael Suzuki
|
||||
*
|
||||
*/
|
||||
public class AuthQueryTest extends AuthDataLoad
|
||||
public class AuthQueryIT extends AuthDataLoad
|
||||
{
|
||||
@Test
|
||||
public void checkAuth()
|
||||
@@ -109,7 +109,6 @@ public class AuthQueryTest extends AuthDataLoad
|
||||
searchParameters.setQuery(queryString);
|
||||
Query query = dataModel.getFTSQuery(new Pair<SearchParameters, Boolean>(searchParameters, Boolean.FALSE),
|
||||
solrQueryRequest, FTSQueryParser.RerankPhase.SINGLE_PASS);
|
||||
System.out.println("##################### Query:"+query);
|
||||
TopDocs docs = solrIndexSearcher.search(query, count * 2 + 10);
|
||||
|
||||
Assert.assertEquals(count, docs.totalHits);
|
||||
+3
-3
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
package org.alfresco.solr.query;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.client.solrj.response.FacetField;
|
||||
@@ -37,12 +37,12 @@ import static org.hamcrest.core.Is.is;
|
||||
|
||||
@SolrTestCaseJ4.SuppressSSL @LuceneTestCase.SuppressCodecs({ "Appending", "Lucene3x", "Lucene40", "Lucene41",
|
||||
"Lucene42", "Lucene43", "Lucene44", "Lucene45", "Lucene46", "Lucene47", "Lucene48",
|
||||
"Lucene49" }) public class DistributedAlfrescoSolrFacetingTest extends AbstractAlfrescoDistributedTest
|
||||
"Lucene49" }) public class DistributedAlfrescoSolrFacetingIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
{
|
||||
initSolrServers(2, "DistributedAlfrescoSolrFacetingTest", null);
|
||||
initSolrServers(2, "DistributedAlfrescoSolrFacetingIT", null);
|
||||
indexSampleDocumentsForFacetingMincount();
|
||||
|
||||
}
|
||||
+2
-2
@@ -34,7 +34,7 @@ import java.util.Random;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
@@ -61,7 +61,7 @@ import org.junit.Test;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedAlfrescoSolrFingerPrintIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
package org.alfresco.solr.query;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
@@ -32,7 +32,7 @@ import org.junit.Test;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedAlfrescoSolrSpellcheckerTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedAlfrescoSolrSpellcheckerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
+2
-3
@@ -20,19 +20,18 @@
|
||||
package org.alfresco.solr.query;
|
||||
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
|
||||
public class SolrAuthTest extends AbstractAlfrescoSolrTests
|
||||
public class SolrAuthIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
|
||||
@BeforeClass
|
||||
+2
-4
@@ -18,9 +18,7 @@
|
||||
*/
|
||||
package org.alfresco.solr.query;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.search.GeneralHighlightParameters;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -32,7 +30,7 @@ import org.junit.Test;
|
||||
* @author Michael Suzuki
|
||||
*
|
||||
*/
|
||||
public class UntokenisedFieldTest extends AbstractAlfrescoSolrTests
|
||||
public class UntokenisedFieldIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
String nodeRef = "workspace://SpacesStore/00000000-0000-1-4731-76966678";
|
||||
String nodeRefS = "noderef@s_@mytest" ;
|
||||
+2
-11
@@ -18,25 +18,16 @@
|
||||
*/
|
||||
package org.alfresco.solr.query.afts.qparser;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.stream.IntStream.range;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
/**
|
||||
* Supertype layer for all AFTS QParser tests.
|
||||
*
|
||||
* @author Andrea Gazzarini
|
||||
*/
|
||||
public abstract class AbstractQParserPluginTest extends AbstractAlfrescoSolrTests
|
||||
public abstract class AbstractQParserPluginIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void spinUpSolr() throws Exception
|
||||
+1
-1
@@ -24,7 +24,7 @@ import org.alfresco.util.ISO9075;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FieldNameEscapingTest extends AbstractQParserPluginTest implements QueryConstants
|
||||
public class FieldNameEscapingIT extends AbstractQParserPluginIT implements QueryConstants
|
||||
{
|
||||
private static TestDataProvider DATASETS_PROVIDER;
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class QParserPluginTest extends AbstractQParserPluginTest implements QueryConstants
|
||||
public class QParserPluginIT extends AbstractQParserPluginIT implements QueryConstants
|
||||
{
|
||||
/** The UTC time zone. */
|
||||
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
|
||||
+1
-1
@@ -49,7 +49,7 @@ import static com.google.common.collect.ImmutableMap.of;
|
||||
* This test set checks that in all these query types the default fields are involved in the search.
|
||||
*
|
||||
*/
|
||||
public class AFTSDefaultTextQueryTest extends AbstractRequestHandlerTest
|
||||
public class AFTSDefaultTextQueryIT extends AbstractRequestHandlerIT
|
||||
{
|
||||
|
||||
@BeforeClass
|
||||
+1
-1
@@ -39,7 +39,7 @@ import org.junit.Test;
|
||||
*
|
||||
* @author msuzuki
|
||||
*/
|
||||
public class AFTSDisjunctionTest extends AbstractRequestHandlerTest
|
||||
public class AFTSDisjunctionIT extends AbstractRequestHandlerIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
+1
-1
@@ -43,7 +43,7 @@ import java.util.Map;
|
||||
* @author eporciani
|
||||
* @author agazzarini
|
||||
*/
|
||||
public class AFTSIdentifierFieldsTest extends AbstractRequestHandlerTest
|
||||
public class AFTSIdentifierFieldsIT extends AbstractRequestHandlerIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
+1
-1
@@ -41,7 +41,7 @@ import java.util.Map;
|
||||
*
|
||||
* @author elia
|
||||
*/
|
||||
public class AFTSRangeQueryTest extends AbstractRequestHandlerTest
|
||||
public class AFTSRangeQueryIT extends AbstractRequestHandlerIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
+1
-1
@@ -20,7 +20,7 @@ import java.util.Locale;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class AFTSRequestHandlerTest extends AbstractRequestHandlerTest implements QueryConstants
|
||||
public class AFTSRequestHandlerIT extends AbstractRequestHandlerIT implements QueryConstants
|
||||
{
|
||||
private static TestDataProvider DATASETS_PROVIDER;
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package org.alfresco.solr.query.afts.requestHandler;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -12,7 +12,7 @@ import java.util.stream.Stream;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.stream.IntStream.range;
|
||||
|
||||
public abstract class AbstractRequestHandlerTest extends AbstractAlfrescoSolrTests
|
||||
public abstract class AbstractRequestHandlerIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void spinUpSolr() throws Exception
|
||||
+1
-1
@@ -9,7 +9,7 @@ import org.junit.Test;
|
||||
*
|
||||
* @author Andrea Gazzarini
|
||||
*/
|
||||
public class MNTTest extends AbstractRequestHandlerTest
|
||||
public class MNTIT extends AbstractRequestHandlerIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void loadData() throws Exception
|
||||
+1
-1
@@ -27,7 +27,7 @@ import org.junit.Test;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class AlfrescoCMISQParserPluginTest extends LoadCMISData implements QueryConstants
|
||||
public class AlfrescoCMISQParserPluginIT extends LoadCMISData implements QueryConstants
|
||||
{
|
||||
@Test
|
||||
public void cmisBasic() throws Exception
|
||||
+1
-1
@@ -31,7 +31,7 @@ import org.junit.Test;
|
||||
* @author Michael Suzuki
|
||||
*
|
||||
*/
|
||||
public class CmisTest extends LoadCMISData
|
||||
public class CmisIT extends LoadCMISData
|
||||
{
|
||||
@Before
|
||||
public void setup() throws Exception
|
||||
+2
-2
@@ -37,7 +37,7 @@ import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.alfresco.solr.AlfrescoSolrDataModel;
|
||||
import org.alfresco.solr.client.ContentPropertyValue;
|
||||
import org.alfresco.solr.client.MLTextPropertyValue;
|
||||
@@ -51,7 +51,7 @@ import org.junit.BeforeClass;
|
||||
* @author Michael Suzuki
|
||||
*
|
||||
*/
|
||||
public class LoadCMISData extends AbstractAlfrescoSolrTests
|
||||
public class LoadCMISData extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
protected static NodeRef testCMISContent00NodeRef;
|
||||
protected static NodeRef testCMISRootNodeRef;
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AclModCountRouterTest
|
||||
public class AclModCountRouterIT
|
||||
{
|
||||
private DocRouter router;
|
||||
|
||||
+3
-3
@@ -36,7 +36,7 @@ import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
@@ -62,9 +62,9 @@ import org.junit.Test;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class AlfrescoSolrTrackerExceptionTest extends AbstractAlfrescoSolrTests
|
||||
public class AlfrescoSolrTrackerExceptionIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(AlfrescoSolrTrackerTest.class);
|
||||
private static Log logger = LogFactory.getLog(AlfrescoSolrTrackerExceptionIT.class);
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
+3
-3
@@ -37,7 +37,7 @@ import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
@@ -64,9 +64,9 @@ import org.junit.Test;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class AlfrescoSolrTrackerTest extends AbstractAlfrescoSolrTests
|
||||
public class AlfrescoSolrTrackerIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(AlfrescoSolrTrackerTest.class);
|
||||
private static Log logger = LogFactory.getLog(AlfrescoSolrTrackerIT.class);
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
+3
-3
@@ -32,7 +32,7 @@ import java.util.Collection;
|
||||
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.alfresco.solr.AlfrescoCoreAdminHandler;
|
||||
|
||||
import org.alfresco.solr.client.Acl;
|
||||
@@ -58,9 +58,9 @@ import org.junit.Test;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class AlfrescoSolrTrackerRollbackTest extends AbstractAlfrescoSolrTests
|
||||
public class AlfrescoSolrTrackerRollbackIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(AlfrescoSolrTrackerTest.class);
|
||||
private static Log logger = LogFactory.getLog(AlfrescoSolrTrackerIT.class);
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
+2
-2
@@ -36,7 +36,7 @@ import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
import org.alfresco.repo.index.shard.ShardState;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.alfresco.solr.AlfrescoCoreAdminHandler;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
@@ -70,7 +70,7 @@ import java.util.stream.Collectors;
|
||||
*
|
||||
* @author agazzarini
|
||||
*/
|
||||
public class AlfrescoSolrTrackerStateTest extends AbstractAlfrescoSolrTests
|
||||
public class AlfrescoSolrTrackerStateIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
+2
-2
@@ -35,7 +35,7 @@ import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrIT;
|
||||
import org.alfresco.solr.client.*;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.*;
|
||||
@@ -52,7 +52,7 @@ import java.util.List;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class CascadeTrackerTest extends AbstractAlfrescoSolrTests
|
||||
public class CascadeTrackerIT extends AbstractAlfrescoSolrIT
|
||||
{
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ import org.mockito.Spy;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ContentTrackerTest
|
||||
public class ContentTrackerIT
|
||||
{
|
||||
private ContentTracker contentTracker;
|
||||
|
||||
@@ -137,7 +137,7 @@ public class ContentTrackerTest
|
||||
@Test
|
||||
public void typeCheck()
|
||||
{
|
||||
Assert.assertTrue(contentTracker.getType().equals(Tracker.Type.Content));
|
||||
Assert.assertTrue(contentTracker.getType().equals(Tracker.Type.CONTENT));
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -46,7 +46,7 @@ import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DateMonthRouterTest
|
||||
public class DateMonthRouterIT
|
||||
{
|
||||
private Random randomizer = new Random();
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@
|
||||
package org.alfresco.solr.tracker;
|
||||
|
||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
@@ -57,7 +57,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.list;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedAclIdAlfrescoSolrTrackerTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedAclIdAlfrescoSolrTrackerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
|
||||
@BeforeClass
|
||||
+2
-2
@@ -19,7 +19,7 @@
|
||||
package org.alfresco.solr.tracker;
|
||||
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.Node;
|
||||
@@ -50,7 +50,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.getTransaction;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedAlfrescoSolrJsonTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedAlfrescoSolrJsonIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
+2
-2
@@ -19,7 +19,7 @@
|
||||
package org.alfresco.solr.tracker;
|
||||
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
@@ -56,7 +56,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.list;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedAlfrescoSolrTrackerTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedAlfrescoSolrTrackerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
|
||||
@BeforeClass
|
||||
+2
-2
@@ -19,7 +19,7 @@
|
||||
package org.alfresco.solr.tracker;
|
||||
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
@@ -54,7 +54,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.indexAclChangeSet;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedAlfrescoSolrTrackerRaceTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedAlfrescoSolrTrackerRaceIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
|
||||
@BeforeClass
|
||||
+2
-2
@@ -33,7 +33,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.indexAclChangeSet;
|
||||
|
||||
import org.alfresco.repo.index.shard.ShardState;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.AlfrescoCoreAdminHandler;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
@@ -68,7 +68,7 @@ import java.util.stream.Collectors;
|
||||
* @author agazzarini
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class DistributedAlfrescoSolrTrackerStateTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedAlfrescoSolrTrackerStateIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
+2
-2
@@ -30,7 +30,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.indexAclChangeSet;
|
||||
import static org.carrot2.shaded.guava.common.collect.ImmutableList.of;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
@@ -55,7 +55,7 @@ import java.util.Properties;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedCascadeTrackerTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedCascadeTrackerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
private Node parentFolder;
|
||||
private NodeMetaData parentFolderMetadata;
|
||||
+2
-2
@@ -21,7 +21,7 @@ package org.alfresco.solr.tracker;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.AlfrescoSolrDataModel;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
@@ -63,7 +63,7 @@ import static org.alfresco.solr.AlfrescoSolrUtils.indexAclChangeSet;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public abstract class DistributedDateAbstractSolrTrackerTest extends AbstractAlfrescoDistributedTest
|
||||
public abstract class DistributedDateAbstractSolrTrackerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
@Test
|
||||
public void testDateMonth() throws Exception
|
||||
+3
-3
@@ -33,7 +33,7 @@ import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.AlfrescoSolrDataModel;
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
@@ -63,13 +63,13 @@ import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class DistributedDateMonthAlfrescoSolrTrackerTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedDateMonthAlfrescoSolrTrackerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
@BeforeClass
|
||||
@SuppressWarnings("unused")
|
||||
public static void initData() throws Throwable
|
||||
{
|
||||
initSolrServers(5, DistributedDateMonthAlfrescoSolrTrackerTest.class.getSimpleName(), getShardMethod());
|
||||
initSolrServers(5, DistributedDateMonthAlfrescoSolrTrackerIT.class.getSimpleName(), getShardMethod());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
+1
-1
@@ -33,7 +33,7 @@ import java.util.Properties;
|
||||
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedDateQuarterAlfrescoSolrTrackerTest extends DistributedDateAbstractSolrTrackerTest
|
||||
public class DistributedDateQuarterAlfrescoSolrTrackerIT extends DistributedDateAbstractSolrTrackerIT
|
||||
{
|
||||
|
||||
@BeforeClass
|
||||
+2
-2
@@ -33,12 +33,12 @@ import java.util.Properties;
|
||||
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedDateSplitYearAlfrescoSolrTrackerTest extends DistributedDateAbstractSolrTrackerTest
|
||||
public class DistributedDateSplitYearAlfrescoSolrTrackerIT extends DistributedDateAbstractSolrTrackerIT
|
||||
{
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
{
|
||||
initSolrServers(3, "DistributedDateSplitYearAlfrescoSolrTrackerTest", getShardMethod());
|
||||
initSolrServers(3, "DistributedDateSplitYearAlfrescoSolrTrackerIT", getShardMethod());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
+3
-3
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
package org.alfresco.solr.tracker;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
@@ -53,12 +53,12 @@ import static org.alfresco.solr.AlfrescoSolrUtils.list;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedDbidRangeAlfrescoSolrTrackerTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedDbidRangeAlfrescoSolrTrackerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
{
|
||||
initSolrServers(2, "DistributedDbidRangeAlfrescoSolrTrackerTest", getShardMethod());
|
||||
initSolrServers(2, "DistributedDbidRangeAlfrescoSolrTrackerIT", getShardMethod());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
+3
-3
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
package org.alfresco.solr.tracker;
|
||||
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
@@ -56,12 +56,12 @@ import static org.alfresco.solr.AlfrescoSolrUtils.list;
|
||||
*/
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedExpandDbidRangeAlfrescoSolrTrackerTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedExpandDbidRangeAlfrescoSolrTrackerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
{
|
||||
initSolrServers(2, "DistributedExpandDbidRangeAlfrescoSolrTrackerTest", getShardMethod());
|
||||
initSolrServers(2, "DistributedExpandDbidRangeAlfrescoSolrTrackerIT", getShardMethod());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
+2
-2
@@ -21,7 +21,7 @@ package org.alfresco.solr.tracker;
|
||||
import java.util.Properties;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
@@ -53,7 +53,7 @@ import static org.carrot2.shaded.guava.common.collect.ImmutableList.of;
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@SolrTestCaseJ4.SuppressObjectReleaseTracker (bugUrl = "RAMDirectory")
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedExplicitShardIdWithStaticPropertyRouterTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedExplicitShardIdWithStaticPropertyRouterIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
private final int timeout = 100000;
|
||||
+3
-3
@@ -20,7 +20,7 @@ package org.alfresco.solr.tracker;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
@@ -62,12 +62,12 @@ import static org.alfresco.solr.tracker.DocRouterFactory.SHARD_KEY_KEY;
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@SolrTestCaseJ4.SuppressObjectReleaseTracker (bugUrl = "RAMDirectory")
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedExplicitShardRoutingTrackerTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedExplicitShardRoutingTrackerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
{
|
||||
initSolrServers(3, "DistributedExplicitShardRoutingTrackerTest", getProperties());
|
||||
initSolrServers(3, "DistributedExplicitShardRoutingTrackerIT", getProperties());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
+3
-3
@@ -41,7 +41,7 @@ import com.carrotsearch.randomizedtesting.RandomizedContext;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.SolrInformationServer;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
@@ -66,7 +66,7 @@ import org.junit.Test;
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
@SolrTestCaseJ4.SuppressObjectReleaseTracker (bugUrl = "RAMDirectory")
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedPropertyBasedAlfrescoSolrTrackerTest extends AbstractAlfrescoDistributedTest
|
||||
public class DistributedPropertyBasedAlfrescoSolrTrackerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
private static final String[] DOMAINS = {"alfresco.com", "king.com", "gmail.com", "yahoo.com", "cookie.es"};
|
||||
private static final Map<String,Integer> domainsCount = new HashMap<>();
|
||||
@@ -78,7 +78,7 @@ public class DistributedPropertyBasedAlfrescoSolrTrackerTest extends AbstractAlf
|
||||
{
|
||||
domainsCount.put(domain,0);
|
||||
}
|
||||
initSolrServers(4, "DistributedPropertyBasedAlfrescoSolrTrackerTest", getProperties());
|
||||
initSolrServers(4, "DistributedPropertyBasedAlfrescoSolrTrackerIT", getProperties());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
+1
-1
@@ -41,7 +41,7 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ExplicitIDRouterTest
|
||||
public class ExplicitIDRouterIT
|
||||
{
|
||||
private DocRouter router;
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ExplicitIDWithLRISRouterTest
|
||||
public class ExplicitIDWithLRISRouterIT
|
||||
{
|
||||
private DocRouter router;
|
||||
|
||||
+7
-6
@@ -47,7 +47,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MetadataTrackerTest
|
||||
@@ -58,20 +58,23 @@ public class MetadataTrackerTest
|
||||
|
||||
@Mock
|
||||
private SOLRAPIClient repositoryClient;
|
||||
private String coreName = "theCoreName";
|
||||
|
||||
@Mock
|
||||
private InformationServer srv;
|
||||
|
||||
@Spy
|
||||
private Properties props;
|
||||
|
||||
@Mock
|
||||
private TrackerStats trackerStats;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
public void setUp()
|
||||
{
|
||||
doReturn("workspace://SpacesStore").when(props).getProperty("alfresco.stores");
|
||||
when(srv.getTrackerStats()).thenReturn(trackerStats);
|
||||
this.metadataTracker = spy(new MetadataTracker(props, repositoryClient, coreName, srv));
|
||||
String coreName = "theCoreName";
|
||||
this.metadataTracker = spy(new MetadataTracker(true, props, repositoryClient, coreName, srv));
|
||||
|
||||
ModelTracker modelTracker = mock(ModelTracker.class);
|
||||
when(modelTracker.hasModels()).thenReturn(true);
|
||||
@@ -197,6 +200,4 @@ public class MetadataTrackerTest
|
||||
|
||||
assertSame(nodes4Tx, nodes);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-3
@@ -56,7 +56,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ModelTrackerTest
|
||||
public class ModelTrackerIT
|
||||
{
|
||||
private ModelTracker modelTracker;
|
||||
|
||||
@@ -102,8 +102,6 @@ public class ModelTrackerTest
|
||||
when(props.getProperty("alfresco.stores", "workspace://SpacesStore")).thenReturn("workspace://SpacesStore");
|
||||
when(props.getProperty("alfresco.batch.count", "5000")).thenReturn("5000");
|
||||
when(props.getProperty("alfresco.maxLiveSearchers", "2")).thenReturn("2");
|
||||
when(props.getProperty("enable.slave", "false")).thenReturn("false");
|
||||
when(props.getProperty("enable.master", "true")).thenReturn("true");
|
||||
when(props.getProperty("shard.count", "1")).thenReturn("1");
|
||||
when(props.getProperty("shard.instance", "0")).thenReturn("0");
|
||||
when(this.srv.getTrackerStats()).thenReturn(trackerStats);
|
||||
+1
-1
@@ -42,7 +42,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PropertyRouterTest
|
||||
public class PropertyRouterIT
|
||||
{
|
||||
private PropertyRouter router;
|
||||
|
||||
+1
-3
@@ -73,8 +73,6 @@ public class SolrTrackerSchedulerTest
|
||||
props.put("alfresco.stores", "workspace://SpacesStore");
|
||||
props.put("alfresco.batch.count", "5000");
|
||||
props.put("alfresco.maxLiveSearchers", "2");
|
||||
props.put("enable.slave", "false");
|
||||
props.put("enable.master", "true");
|
||||
props.put("shard.count", "1");
|
||||
props.put("shard.instance", "0");
|
||||
props.put("shard.method", "SHARD_METHOD_DBID");
|
||||
@@ -128,7 +126,7 @@ public class SolrTrackerSchedulerTest
|
||||
{
|
||||
String exp = "0/4 * * * * ? *";
|
||||
props.put("alfresco.metadata.tracker.cron", exp);
|
||||
MetadataTracker metadataTracker = new MetadataTracker(props, client, exp, informationServer);
|
||||
MetadataTracker metadataTracker = new MetadataTracker(true, props, client, exp, informationServer);
|
||||
this.trackerScheduler.schedule(metadataTracker, CORE_NAME, props);
|
||||
verify(spiedQuartzScheduler).scheduleJob(any(JobDetail.class), any(Trigger.class));
|
||||
checkCronExpression(exp);
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@ package org.alfresco.solr.transformer;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedIT;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
@@ -58,14 +58,14 @@ import static org.alfresco.solr.AlfrescoSolrUtils.list;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
@SolrTestCaseJ4.SuppressSSL
|
||||
public class CachedDocTransformerTest extends AbstractAlfrescoDistributedTest
|
||||
public class CachedDocTransformerIT extends AbstractAlfrescoDistributedIT
|
||||
{
|
||||
public static final String ALFRESCO_JSON = "{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}]}";
|
||||
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
{
|
||||
initSolrServers(1, "CachedDocTransformerTest", null);
|
||||
initSolrServers(1, "CachedDocTransformerIT", null);
|
||||
populateAlfrescoData();
|
||||
}
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ import org.apache.lucene.util.automaton.CharacterRunAutomaton;
|
||||
import org.apache.lucene.util.automaton.RegExp;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MinHashFilterTest extends BaseTokenStreamTestCase
|
||||
public class MinHashFilterIT extends BaseTokenStreamTestCase
|
||||
{
|
||||
@Test
|
||||
public void testIntHash() {
|
||||
+1
-1
@@ -43,7 +43,7 @@ import org.mockito.Mock;
|
||||
/**
|
||||
* Unit tests for the {@link AlfrescoLukeRequestHandler}.
|
||||
*/
|
||||
public class AlfrescoLukeRequestHandlerTest
|
||||
public class AlfrescoLukeRequestHandlerIT
|
||||
{
|
||||
/** The reference to text for a search term. */
|
||||
private static final BytesRef TERM_TEXT = new BytesRef("TermText");
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<config>
|
||||
<luceneMatchVersion>6.6.5</luceneMatchVersion>
|
||||
<dataDir>/tmp/test</dataDir>
|
||||
<schemaFactory class="ClassicIndexSchemaFactory" />
|
||||
<indexConfig>
|
||||
<lockType>${solr.lock.type:native}</lockType>
|
||||
</indexConfig>
|
||||
|
||||
<requestDispatcher handleSelect="true">
|
||||
<requestParsers
|
||||
enableRemoteStreaming="true"
|
||||
multipartUploadLimitInKB="2048000"
|
||||
formdataUploadLimitInKB="2048" />
|
||||
<httpCaching never304="true" />
|
||||
</requestDispatcher>
|
||||
|
||||
<requestHandler name="/replication" class="io.sease.labs.solr.handler.ReplicationHandler">
|
||||
<lst name="master">
|
||||
<str name="replicateAfter">commit</str>
|
||||
<str name="confFiles">schema.xml</str>
|
||||
</lst>
|
||||
</requestHandler>
|
||||
|
||||
<requestHandler name="/def" class="solr.SearchHandler" default="true">
|
||||
<lst name="defaults">
|
||||
<bool name="sow">false</bool>
|
||||
<str name="df">id</str>
|
||||
<str name="defType">lucene</str>
|
||||
</lst>
|
||||
</requestHandler>
|
||||
|
||||
<admin>
|
||||
<defaultQuery>Query me!</defaultQuery>
|
||||
</admin>
|
||||
</config>
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<config>
|
||||
<luceneMatchVersion>6.6.5</luceneMatchVersion>
|
||||
<dataDir>/tmp/test</dataDir>
|
||||
<schemaFactory class="ClassicIndexSchemaFactory" />
|
||||
<indexConfig>
|
||||
<lockType>${solr.lock.type:native}</lockType>
|
||||
</indexConfig>
|
||||
|
||||
<requestDispatcher handleSelect="true">
|
||||
<requestParsers
|
||||
enableRemoteStreaming="true"
|
||||
multipartUploadLimitInKB="2048000"
|
||||
formdataUploadLimitInKB="2048" />
|
||||
<httpCaching never304="true" />
|
||||
</requestDispatcher>
|
||||
|
||||
<requestHandler name="/replication" class="io.sease.labs.solr.handler.ReplicationHandler">
|
||||
<lst name="master">
|
||||
<str name="enable">false</str>
|
||||
<str name="replicateAfter">commit</str>
|
||||
<str name="confFiles">schema.xml</str>
|
||||
</lst>
|
||||
</requestHandler>
|
||||
|
||||
<requestHandler name="/def" class="solr.SearchHandler" default="true">
|
||||
<lst name="defaults">
|
||||
<bool name="sow">false</bool>
|
||||
<str name="df">id</str>
|
||||
<str name="defType">lucene</str>
|
||||
</lst>
|
||||
</requestHandler>
|
||||
|
||||
<admin>
|
||||
<defaultQuery>Query me!</defaultQuery>
|
||||
</admin>
|
||||
</config>
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<config>
|
||||
<luceneMatchVersion>6.6.5</luceneMatchVersion>
|
||||
<dataDir>/tmp/test</dataDir>
|
||||
<schemaFactory class="ClassicIndexSchemaFactory" />
|
||||
<indexConfig>
|
||||
<lockType>${solr.lock.type:native}</lockType>
|
||||
</indexConfig>
|
||||
|
||||
<requestDispatcher handleSelect="true">
|
||||
<requestParsers
|
||||
enableRemoteStreaming="true"
|
||||
multipartUploadLimitInKB="2048000"
|
||||
formdataUploadLimitInKB="2048" />
|
||||
<httpCaching never304="true" />
|
||||
</requestDispatcher>
|
||||
|
||||
<requestHandler name="/replication" class="io.sease.labs.solr.handler.ReplicationHandler">
|
||||
<lst name="master">
|
||||
<str name="replicateAfter">commit</str>
|
||||
<str name="confFiles">schema.xml</str>
|
||||
</lst>
|
||||
</requestHandler>
|
||||
|
||||
<requestHandler name="/def" class="solr.SearchHandler" default="true">
|
||||
<lst name="defaults">
|
||||
<bool name="sow">false</bool>
|
||||
<str name="df">id</str>
|
||||
<str name="defType">lucene</str>
|
||||
</lst>
|
||||
</requestHandler>
|
||||
|
||||
<admin>
|
||||
<defaultQuery>Query me!</defaultQuery>
|
||||
</admin>
|
||||
</config>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user