Fix for ALF-10561 SOLR stops indexing if it is given a property that is neither indexed or stored - it throws an exception

Fix ALF-10358 	SOLR No easy way to get the current last TX indexed to monitor how the SOLR index is building

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30857 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Andrew Hind
2011-09-29 14:28:46 +00:00
parent c3fe5d4b53
commit c5f94ae12e
6 changed files with 357 additions and 1 deletions

View File

@@ -1035,7 +1035,7 @@
<property name="httpClientFactory" ref="solrHttpClientFactory"/>
</bean>
<bean id="solr" class="org.alfresco.repo.management.subsystems.ChildApplicationContextFactory" parent="abstractPropertyBackedBean">
<bean id="solr" class="org.alfresco.repo.search.impl.solr.SolrChildApplicationContextFactory" parent="abstractPropertyBackedBean">
<property name="autoStart">
<value>false</value>
</property>

View File

@@ -56,6 +56,10 @@
</property>
</bean>
<bean id="search.solrAdminHTTPCLient" class="org.alfresco.repo.search.impl.solr.SolrAdminHTTPClient" init-method="init">
<property name="httpClientFactory" ref="solrHttpClientFactory"/>
</bean>
<bean id="search.lucene.alfresco" class="org.alfresco.repo.search.impl.solr.SolrQueryLanguage" >
<property name="factories">

View File

@@ -0,0 +1,175 @@
/*
* Copyright (C) 2005-2010 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.repo.search.impl.solr;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.httpclient.HttpClientFactory;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParserException;
import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchParameters.FieldFacet;
import org.alfresco.service.cmr.search.SearchParameters.FieldFacetMethod;
import org.alfresco.service.cmr.search.SearchParameters.FieldFacetSort;
import org.alfresco.service.cmr.search.SearchParameters.SortDefinition;
import org.alfresco.service.cmr.security.PermissionService;
import org.apache.commons.codec.net.URLCodec;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* @author Andy
*/
public class SolrAdminHTTPClient
{
static Log s_logger = LogFactory.getLog(SolrAdminHTTPClient.class);
private String baseUrl;
private HttpClient httpClient;
private HttpClientFactory httpClientFactory;
public SolrAdminHTTPClient()
{
}
public void init()
{
StringBuilder sb = new StringBuilder();
sb.append("/solr/admin/cores");
this.baseUrl = sb.toString();
httpClient = httpClientFactory.getHttpClient();
HttpClientParams params = httpClient.getParams();
params.setBooleanParameter(HttpClientParams.PREEMPTIVE_AUTHENTICATION, true);
httpClient.getState().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), new UsernamePasswordCredentials("admin", "admin"));
}
public void setHttpClientFactory(HttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory;
}
public JSONObject execute(HashMap<String, String>args)
{
try
{
URLCodec encoder = new URLCodec();
StringBuilder url = new StringBuilder();
for(String key : args.keySet())
{
String value = args.get(key);
if(url.length() == 0)
{
url.append(baseUrl);
url.append("?");
url.append(encoder.encode(key, "UTF-8"));
url.append("=");
url.append(encoder.encode(value, "UTF-8"));
}
else
{
url.append("&");
url.append(encoder.encode(key, "UTF-8"));
url.append("=");
url.append(encoder.encode(value, "UTF-8"));
}
}
PostMethod post = new PostMethod(url.toString());
try
{
httpClient.executeMethod(post);
if(post.getStatusCode() == HttpStatus.SC_MOVED_PERMANENTLY || post.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY)
{
Header locationHeader = post.getResponseHeader("location");
if (locationHeader != null)
{
String redirectLocation = locationHeader.getValue();
post.setURI(new URI(redirectLocation, true));
httpClient.executeMethod(post);
}
}
if (post.getStatusCode() != HttpServletResponse.SC_OK)
{
throw new LuceneQueryParserException("Request failed " + post.getStatusCode() + " " + url.toString());
}
Reader reader = new BufferedReader(new InputStreamReader(post.getResponseBodyAsStream()));
// TODO - replace with streaming-based solution e.g. SimpleJSON ContentHandler
JSONObject json = new JSONObject(new JSONTokener(reader));
return json;
}
finally
{
post.releaseConnection();
}
}
catch (UnsupportedEncodingException e)
{
throw new LuceneQueryParserException("", e);
}
catch (HttpException e)
{
throw new LuceneQueryParserException("", e);
}
catch (IOException e)
{
throw new LuceneQueryParserException("", e);
}
catch (JSONException e)
{
throw new LuceneQueryParserException("", e);
}
}
}

View File

@@ -0,0 +1,162 @@
/*
* Copyright (C) 2005-2010 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.repo.search.impl.solr;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParserException;
import org.alfresco.service.cmr.repository.datatype.Duration;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.context.ApplicationContext;
/**
* @author Andy
*/
public class SolrChildApplicationContextFactory extends ChildApplicationContextFactory
{
private static String ALFRESCO_ACTIVE = "tracker.alfresco.active";
private static String ALFRESCO_LAG = "tracker.alfresco.lag";
private static String ALFRESCO_LAG_DURATION = "tracker.alfresco.lag.duration";
private static String ARCHIVE_ACTIVE = "tracker.archive.active";
private static String ARCHIVE_LAG = "tracker.archive.lag";
private static String ARCHIVE_LAG_DURATION = "tracker.archive.lag.duration";
@Override
public boolean isUpdateable(String name)
{
// TODO Auto-generated method stub
return super.isUpdateable(name)
&& !name.equals(SolrChildApplicationContextFactory.ALFRESCO_ACTIVE) && !name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG)
&& !name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG_DURATION) && !name.equals(SolrChildApplicationContextFactory.ARCHIVE_ACTIVE)
&& !name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG) && !name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG_DURATION);
}
@Override
public String getProperty(String name)
{
if (name.equals(SolrChildApplicationContextFactory.ALFRESCO_ACTIVE)
|| name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG) || name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG_DURATION) || name.equals(SolrChildApplicationContextFactory.ARCHIVE_ACTIVE)
|| name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG) || name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG_DURATION))
{
try
{
ApplicationContext ctx = getApplicationContext();
SolrAdminHTTPClient adminClient = (SolrAdminHTTPClient) ctx.getBean("search.solrAdminHTTPCLient");
HashMap<String, String> args = new HashMap<String, String>();
args.put("action", "SUMMARY");
args.put("wt", "json");
JSONObject json = adminClient.execute(args);
JSONObject summary = json.getJSONObject("Summary");
Date now = new Date();
JSONObject alfresco = summary.getJSONObject("alfresco");
String alfrescoLag = alfresco.getString("Lag");
String alfrescoActive = alfresco.getString("Active");
String alfrescoDuration = alfresco.getString("Duration");
JSONObject archive = summary.getJSONObject("archive");
String archiveLag = archive.getString("Lag");
String archiveActive = archive.getString("Active");
String archiveDuration = archive.getString("Duration");
if (name.equals(SolrChildApplicationContextFactory.ALFRESCO_ACTIVE))
{
return alfrescoActive;
}
else if (name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG))
{
return alfrescoLag;
}
else if (name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG_DURATION))
{
return alfrescoDuration;
}
else if (name.equals(SolrChildApplicationContextFactory.ARCHIVE_ACTIVE))
{
return archiveActive;
}
else if (name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG))
{
return archiveLag;
}
else if (name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG_DURATION))
{
return archiveDuration;
}
else
{
return "Unavailable";
}
}
catch (LuceneQueryParserException lqe)
{
return "Unavailable: " + lqe.getMessage();
}
catch (JSONException e)
{
return "Unavailable: " + e.getMessage();
}
}
else
{
return super.getProperty(name);
}
}
@Override
public Set<String> getPropertyNames()
{
Set<String> result = new TreeSet<String>();
result.add(SolrChildApplicationContextFactory.ALFRESCO_ACTIVE);
result.add(SolrChildApplicationContextFactory.ALFRESCO_LAG);
result.add(SolrChildApplicationContextFactory.ALFRESCO_LAG_DURATION);
result.add(SolrChildApplicationContextFactory.ARCHIVE_ACTIVE);
result.add(SolrChildApplicationContextFactory.ARCHIVE_LAG);
result.add(SolrChildApplicationContextFactory.ARCHIVE_LAG_DURATION);
result.addAll(super.getPropertyNames());
return result;
}
public void setProperty(String name, String value)
{
if (name.equals(SolrChildApplicationContextFactory.ALFRESCO_ACTIVE)
|| name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG) || name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG_DURATION) || name.equals(SolrChildApplicationContextFactory.ARCHIVE_ACTIVE)
|| name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG) || name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG_DURATION))
{
throw new IllegalStateException("Illegal write to property \"" + name + "\"");
}
super.setProperty(name, value);
}
}

View File

@@ -142,4 +142,10 @@ public interface SOLRTrackingComponent
* @param enabled
*/
void setEnabled(boolean enabled);
/**
* Get the last transaction timestamp from the repo
* @return
*/
public Long getMaxTxnCommitTime();
}

View File

@@ -796,4 +796,13 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent
more = callback.handleNodeMetaData(row);
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.solr.SOLRTrackingComponent#getLastTransactionTimestamp()
*/
@Override
public Long getMaxTxnCommitTime()
{
return nodeDAO.getMaxTxnCommitTime();
}
}