mirror of
https://github.com/Alfresco/SearchServices.git
synced 2026-09-16 18:12:56 +00:00
Merge branch 'fix/SEARCH_2175_CascadeTracker' into 'master'
Fix/search 2175 cascade tracker See merge request search_discovery/insightengine!463
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2020 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;
|
||||
|
||||
/**
|
||||
* Marker exception thrown for indicating a failure in obtaining / releasing a lock.
|
||||
*/
|
||||
public class AlfrescoLockException extends Exception
|
||||
{
|
||||
AlfrescoLockException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+64
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Alfresco Software Limited.
|
||||
* Copyright (C) 2020 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -69,6 +69,7 @@ import static org.alfresco.repo.search.adaptor.lucene.QueryConstants.FIELD_TXCOM
|
||||
import static org.alfresco.repo.search.adaptor.lucene.QueryConstants.FIELD_TXID;
|
||||
import static org.alfresco.repo.search.adaptor.lucene.QueryConstants.FIELD_TYPE;
|
||||
import static org.alfresco.repo.search.adaptor.lucene.QueryConstants.FIELD_VERSION;
|
||||
import static org.alfresco.solr.utils.Utils.notNullOrEmpty;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -85,7 +86,6 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -296,6 +296,8 @@ public class SolrInformationServer implements InformationServer
|
||||
private String skippingDocsQueryString;
|
||||
private boolean isSkippingDocsInitialized;
|
||||
|
||||
private long maxAllowedTimeForAcquiringDbIdLock;
|
||||
|
||||
protected enum FTSStatus {New, Dirty, Clean}
|
||||
|
||||
static class DocListCollector implements Collector, LeafCollector
|
||||
@@ -451,7 +453,7 @@ public class SolrInformationServer implements InformationServer
|
||||
this.core = core;
|
||||
this.nativeRequestHandler = core.getRequestHandler(REQUEST_HANDLER_NATIVE);
|
||||
this.cloud = new Cloud();
|
||||
this.repositoryClient = repositoryClient;
|
||||
this.repositoryClient = Objects.requireNonNull(repositoryClient);
|
||||
this.solrContentStore = solrContentStore;
|
||||
|
||||
Properties p = core.getResourceLoader().getCoreProperties();
|
||||
@@ -461,6 +463,8 @@ public class SolrInformationServer implements InformationServer
|
||||
holeRetention = Integer.parseInt(p.getProperty("alfresco.hole.retention", "3600000"));
|
||||
minHash = Boolean.parseBoolean(p.getProperty("alfresco.fingerprint", "true"));
|
||||
|
||||
maxAllowedTimeForAcquiringDbIdLock = Long.parseLong(p.getProperty("alfresco.tracker.maxNodeLockMs", "120000"));
|
||||
|
||||
dataModel = AlfrescoSolrDataModel.getInstance();
|
||||
|
||||
contentStreamLimit = Integer.parseInt(p.getProperty("alfresco.contentStreamLimit", "10000000"));
|
||||
@@ -1502,7 +1506,7 @@ public class SolrInformationServer implements InformationServer
|
||||
NodeMetaDataParameters nmdp = new NodeMetaDataParameters();
|
||||
nmdp.setFromNodeId(node.getId());
|
||||
nmdp.setToNodeId(node.getId());
|
||||
List<NodeMetaData> nodeMetaDatas;
|
||||
Collection<NodeMetaData> nodeMetaDatas;
|
||||
if ((node.getStatus() == SolrApiNodeStatus.DELETED)
|
||||
|| cascadeTrackingEnabled() && ((node.getStatus() == SolrApiNodeStatus.NON_SHARD_DELETED)
|
||||
|| (node.getStatus() == SolrApiNodeStatus.NON_SHARD_UPDATED)))
|
||||
@@ -1513,13 +1517,14 @@ public class SolrInformationServer implements InformationServer
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeMetaDatas = repositoryClient.getNodesMetaData(nmdp, Integer.MAX_VALUE);
|
||||
nmdp.setMaxResults(Integer.MAX_VALUE);
|
||||
nodeMetaDatas = getNodesMetaDataFromRepository(nmdp);
|
||||
}
|
||||
|
||||
NodeMetaData nodeMetaData;
|
||||
if (!nodeMetaDatas.isEmpty())
|
||||
{
|
||||
nodeMetaData = nodeMetaDatas.get(0);
|
||||
nodeMetaData = nodeMetaDatas.iterator().next();
|
||||
if (!(nodeMetaData.getTxnId() > node.getTxnId()))
|
||||
{
|
||||
if (node.getStatus() == SolrApiNodeStatus.DELETED)
|
||||
@@ -1557,15 +1562,15 @@ public class SolrInformationServer implements InformationServer
|
||||
NodeMetaDataParameters nmdp = new NodeMetaDataParameters();
|
||||
nmdp.setFromNodeId(node.getId());
|
||||
nmdp.setToNodeId(node.getId());
|
||||
|
||||
List<NodeMetaData> nodeMetaDatas = repositoryClient.getNodesMetaData(nmdp, Integer.MAX_VALUE);
|
||||
nmdp.setMaxResults(Integer.MAX_VALUE);
|
||||
Collection<NodeMetaData> nodeMetaDatas = getNodesMetaDataFromRepository(nmdp);
|
||||
|
||||
AddUpdateCommand addDocCmd = new AddUpdateCommand(request);
|
||||
addDocCmd.overwrite = overwrite;
|
||||
|
||||
if (!nodeMetaDatas.isEmpty())
|
||||
{
|
||||
NodeMetaData nodeMetaData = nodeMetaDatas.get(0);
|
||||
NodeMetaData nodeMetaData = nodeMetaDatas.iterator().next();
|
||||
if(node.getTxnId() == Long.MAX_VALUE) {
|
||||
//This is a re-index. We need to clear the txnId from the pr
|
||||
this.cleanContentCache.remove(nodeMetaData.getTxnId());
|
||||
@@ -1722,8 +1727,9 @@ public class SolrInformationServer implements InformationServer
|
||||
nmdp.setIncludePaths(true);
|
||||
nmdp.setIncludeProperties(false);
|
||||
nmdp.setIncludeTxnId(true);
|
||||
nmdp.setMaxResults(1);
|
||||
// Gets only one
|
||||
List<NodeMetaData> nodeMetaDatas = repositoryClient.getNodesMetaData(nmdp, 1);
|
||||
Collection<NodeMetaData> nodeMetaDatas = getNodesMetaDataFromRepository(nmdp);
|
||||
allNodeMetaDatas.addAll(nodeMetaDatas);
|
||||
}
|
||||
|
||||
@@ -1808,6 +1814,14 @@ public class SolrInformationServer implements InformationServer
|
||||
processor.processAdd(addDocCmd);
|
||||
}
|
||||
}
|
||||
catch (AlfrescoLockException exception)
|
||||
{
|
||||
LOGGER.error(exception.getMessage());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LOGGER.error("Unable to update the text content of node {}. See the stacktrace below for further details.", dbId, exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock(dbId);
|
||||
@@ -1862,7 +1876,8 @@ public class SolrInformationServer implements InformationServer
|
||||
nmdp.setIncludeAspects(false);
|
||||
nmdp.setIncludePaths(false);
|
||||
nmdp.setIncludeParentAssociations(false);
|
||||
nodeMetaDatas.addAll(repositoryClient.getNodesMetaData(nmdp, Integer.MAX_VALUE));
|
||||
nmdp.setMaxResults(Integer.MAX_VALUE);
|
||||
nodeMetaDatas.addAll(getNodesMetaDataFromRepository(nmdp));
|
||||
}
|
||||
|
||||
for (NodeMetaData nodeMetaData : nodeMetaDatas)
|
||||
@@ -1907,7 +1922,8 @@ public class SolrInformationServer implements InformationServer
|
||||
nmdp.setIncludeChildAssociations(false);
|
||||
|
||||
// Fetches bulk metadata
|
||||
List<NodeMetaData> nodeMetaDatas = repositoryClient.getNodesMetaData(nmdp, Integer.MAX_VALUE);
|
||||
nmdp.setMaxResults(Integer.MAX_VALUE);
|
||||
Collection<NodeMetaData> nodeMetaDatas = getNodesMetaDataFromRepository(nmdp);
|
||||
|
||||
NEXT_NODE:
|
||||
for (NodeMetaData nodeMetaData : nodeMetaDatas)
|
||||
@@ -2484,11 +2500,12 @@ public class SolrInformationServer implements InformationServer
|
||||
NodeMetaDataParameters nmdp = new NodeMetaDataParameters();
|
||||
nmdp.setFromNodeId(dbId);
|
||||
nmdp.setToNodeId(dbId);
|
||||
List<NodeMetaData> nodeMetaDatas = repositoryClient.getNodesMetaData(nmdp, Integer.MAX_VALUE);
|
||||
nmdp.setMaxResults(Integer.MAX_VALUE);
|
||||
Collection<NodeMetaData> nodeMetaDatas = getNodesMetaDataFromRepository(nmdp);
|
||||
SolrInputDocument newDoc = null;
|
||||
if (!nodeMetaDatas.isEmpty())
|
||||
{
|
||||
NodeMetaData nodeMetaData = nodeMetaDatas.get(0);
|
||||
NodeMetaData nodeMetaData = nodeMetaDatas.iterator().next();
|
||||
newDoc = createNewDoc(nodeMetaData, DOC_TYPE_NODE);
|
||||
addFieldsToDoc(nodeMetaData, newDoc);
|
||||
boolean isContentIndexedForNode = isContentIndexedForNode(nodeMetaData.getProperties());
|
||||
@@ -3155,10 +3172,10 @@ public class SolrInformationServer implements InformationServer
|
||||
}
|
||||
}
|
||||
|
||||
private void lock(Object id) throws IOException
|
||||
private void lock(Object id) throws AlfrescoLockException
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
while(!lockRegistry.add(id))
|
||||
while (!lockRegistry.add(id))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -3169,9 +3186,9 @@ public class SolrInformationServer implements InformationServer
|
||||
// I don't think we are concerned with this exception.
|
||||
}
|
||||
|
||||
if(System.currentTimeMillis() - startTime > 120000)
|
||||
if (System.currentTimeMillis() - startTime > maxAllowedTimeForAcquiringDbIdLock)
|
||||
{
|
||||
throw new IOException("Unable to acquire lock on nodeId " + id + " after " + 120000 + " msecs.");
|
||||
throw new AlfrescoLockException("Unable to acquire lock on nodeId " + id + " after " + maxAllowedTimeForAcquiringDbIdLock + " msecs.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3375,12 +3392,13 @@ public class SolrInformationServer implements InformationServer
|
||||
nmdp.setIncludeProperties(false);
|
||||
nmdp.setIncludeType(false);
|
||||
nmdp.setIncludeTxnId(true);
|
||||
nmdp.setMaxResults(1);
|
||||
// Gets only one
|
||||
List<NodeMetaData> nodeMetaDatas = repositoryClient.getNodesMetaData(nmdp, 1);
|
||||
Collection<NodeMetaData> nodeMetaDatas = getNodesMetaDataFromRepository(nmdp);
|
||||
|
||||
if (!nodeMetaDatas.isEmpty())
|
||||
{
|
||||
NodeMetaData nodeMetaData = nodeMetaDatas.get(0);
|
||||
NodeMetaData nodeMetaData = nodeMetaDatas.iterator().next();
|
||||
|
||||
// Only cascade update nods we know can not have changed and must be in this shard
|
||||
// Node in the current TX will be explicitly updated in the outer loop
|
||||
@@ -3432,6 +3450,14 @@ public class SolrInformationServer implements InformationServer
|
||||
LOGGER.debug("No child doc found to update {}", childId);
|
||||
}
|
||||
}
|
||||
catch (AlfrescoLockException exception)
|
||||
{
|
||||
LOGGER.error(exception.getMessage());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LOGGER.error("Cascade update failure on child document {}. See the stacktrace below for further details.", childId, exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock(nodeId);
|
||||
@@ -3823,4 +3849,22 @@ public class SolrInformationServer implements InformationServer
|
||||
{
|
||||
solrContentStore.flushChangeSet();
|
||||
}
|
||||
|
||||
private Collection<NodeMetaData> getNodesMetaDataFromRepository(NodeMetaDataParameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
return notNullOrEmpty(repositoryClient.getNodesMetaData(parameters));
|
||||
}
|
||||
catch (JSONException exception)
|
||||
{
|
||||
// Nothing to be done here: the exception has been already logged in repositoryClient
|
||||
return Collections.emptyList();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LOGGER.error("Unable to get nodes metadata from repository. See the stacktrace below for further details.", exception);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-16
@@ -20,7 +20,6 @@ package org.alfresco.solr.tracker;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Properties;
|
||||
@@ -45,7 +44,7 @@ public abstract class AbstractTracker implements Tracker
|
||||
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 final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected Properties props;
|
||||
protected SOLRAPIClient client;
|
||||
@@ -73,6 +72,7 @@ public abstract class AbstractTracker implements Tracker
|
||||
*/
|
||||
protected Throwable rollbackCausedBy;
|
||||
protected final Type type;
|
||||
protected final String trackerId;
|
||||
|
||||
/*
|
||||
* A thread handler can be used by subclasses, but they have to intentionally instantiate it.
|
||||
@@ -85,8 +85,9 @@ public abstract class AbstractTracker implements Tracker
|
||||
protected AbstractTracker(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
this.trackerId = type + "@" + hashCode();
|
||||
}
|
||||
|
||||
|
||||
protected AbstractTracker(Properties p, SOLRAPIClient client, String coreName, InformationServer informationServer,Type type)
|
||||
{
|
||||
this.props = p;
|
||||
@@ -109,6 +110,8 @@ public abstract class AbstractTracker implements Tracker
|
||||
this.trackerStats = this.infoSrv.getTrackerStats();
|
||||
|
||||
this.type = type;
|
||||
|
||||
this.trackerId = type + "@" + hashCode();
|
||||
}
|
||||
|
||||
|
||||
@@ -121,8 +124,10 @@ public abstract class AbstractTracker implements Tracker
|
||||
* <li>Index</li>
|
||||
* <li>Track repository</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param iterationId an identifier which is uniquely associated with a given iteration.
|
||||
*/
|
||||
protected abstract void doTrack() throws Throwable;
|
||||
protected abstract void doTrack(String iterationId) throws Throwable;
|
||||
|
||||
|
||||
private boolean assertTrackerStateRemainsNull() {
|
||||
@@ -156,14 +161,16 @@ public abstract class AbstractTracker implements Tracker
|
||||
}
|
||||
/**
|
||||
* Template method - subclasses must implement the {@link Tracker}-specific indexing
|
||||
* by implementing the abstract method {@link #doTrack()}.
|
||||
* by implementing the abstract method {@link #doTrack(String)}.
|
||||
*/
|
||||
@Override
|
||||
public void track()
|
||||
{
|
||||
String iterationId = "IT #" + System.currentTimeMillis();
|
||||
|
||||
if(runLock.availablePermits() == 0)
|
||||
{
|
||||
LOGGER.info("... {} for core [{}] is already in use {}", this.getClass().getSimpleName(), coreName, getClass());
|
||||
logger.info("[{} / {} / {}] Tracker already registered.", coreName, trackerId, iterationId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -180,13 +187,11 @@ public abstract class AbstractTracker implements Tracker
|
||||
assert(assertTrackerStateRemainsNull());
|
||||
}
|
||||
|
||||
LOGGER.info("[CORE {}] Running {}", coreName, this.getClass().getSimpleName());
|
||||
|
||||
if(this.state == null)
|
||||
{
|
||||
this.state = getTrackerState();
|
||||
|
||||
LOGGER.debug("[CORE {}] Global Tracker State set to: {}", coreName, this.state.toString());
|
||||
logger.debug("[{} / {} / {}] Global Tracker State set to: {}", coreName, trackerId, iterationId, this.state.toString());
|
||||
this.state.setRunning(true);
|
||||
}
|
||||
else
|
||||
@@ -199,33 +204,33 @@ public abstract class AbstractTracker implements Tracker
|
||||
|
||||
try
|
||||
{
|
||||
doTrack();
|
||||
doTrack(iterationId);
|
||||
}
|
||||
catch(IndexTrackingShutdownException t)
|
||||
{
|
||||
setRollback(true, t);
|
||||
LOGGER.info("[CORE {}] Stopping index tracking for {}", coreName, getClass().getSimpleName());
|
||||
logger.info("[{} / {} / {}] Tracking cycle stopped. See the stacktrace below for further details.", coreName, trackerId, iterationId, t);
|
||||
}
|
||||
catch(Throwable t)
|
||||
{
|
||||
setRollback(true, t);
|
||||
if (t instanceof SocketTimeoutException || t instanceof ConnectException)
|
||||
{
|
||||
LOGGER.warn("[CORE {}] Tracking communication timed out for {}", coreName, getClass().getSimpleName());
|
||||
if (LOGGER.isDebugEnabled())
|
||||
logger.warn("[{} / {} / {}] Tracking communication timed out. See the stacktrace below for further details.", coreName, trackerId, iterationId);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
LOGGER.debug("[CORE {}] Stack trace", coreName, t);
|
||||
logger.debug("[{} / {} / {}] Stack trace", coreName, trackerId, iterationId, t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.error("[CORE {}] Tracking failed for {}", coreName, getClass().getSimpleName(), t);
|
||||
logger.error("[{} / {} / {}] Tracking failure. See the stacktrace below for further details.", coreName, trackerId, iterationId, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
LOGGER.error("[CORE {}] Semaphore interrupted for {}", coreName, getClass().getSimpleName(), e);
|
||||
logger.error("[{} / {} / {}] Semaphore interruption. See the stacktrace below for further details.", coreName, trackerId, iterationId, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ public class AclTracker extends AbstractTracker
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTrack() throws Throwable
|
||||
protected void doTrack(String iterationId) throws Throwable
|
||||
{
|
||||
trackRepository();
|
||||
}
|
||||
|
||||
+18
-6
@@ -36,6 +36,9 @@ import org.json.JSONException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.alfresco.solr.utils.Utils.notNullOrEmpty;
|
||||
|
||||
/*
|
||||
* This tracks Cascading Updates
|
||||
* @author Joel Bernstein
|
||||
@@ -61,13 +64,13 @@ public class CascadeTracker extends AbstractTracker implements Tracker
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTrack() throws AuthenticationException, IOException, JSONException, EncoderException
|
||||
protected void doTrack(String iterationId) throws AuthenticationException, IOException, JSONException, EncoderException
|
||||
{
|
||||
// MetadataTracker must wait until ModelTracker has run
|
||||
ModelTracker modelTracker = this.infoSrv.getAdminHandler().getTrackerRegistry().getModelTracker();
|
||||
if (modelTracker != null && modelTracker.hasModels())
|
||||
{
|
||||
trackRepository();
|
||||
trackRepository(iterationId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,10 +82,10 @@ public class CascadeTracker extends AbstractTracker implements Tracker
|
||||
return false;
|
||||
}
|
||||
|
||||
private void trackRepository() throws IOException, AuthenticationException, JSONException, EncoderException
|
||||
private void trackRepository(String iterationId) throws IOException, AuthenticationException, JSONException, EncoderException
|
||||
{
|
||||
checkShutdown();
|
||||
processCascades();
|
||||
processCascades(iterationId);
|
||||
}
|
||||
|
||||
private void updateTransactionsAfterAsynchronous(List<Transaction> txsIndexed)
|
||||
@@ -125,9 +128,8 @@ public class CascadeTracker extends AbstractTracker implements Tracker
|
||||
infoSrv.setCleanCascadeTxnFloor(-1);
|
||||
}
|
||||
|
||||
private void processCascades() throws IOException
|
||||
private void processCascades(String iterationId) throws IOException
|
||||
{
|
||||
//System.out.println("######### processCascades()");
|
||||
int num = 50;
|
||||
List<Transaction> txBatch = null;
|
||||
do {
|
||||
@@ -160,7 +162,17 @@ public class CascadeTracker extends AbstractTracker implements Tracker
|
||||
batch.add(stack.removeFirst());
|
||||
}
|
||||
|
||||
|
||||
CascadeIndexWorkerRunnable worker = new CascadeIndexWorkerRunnable(this.threadHandler, batch, infoSrv);
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
String nodes = notNullOrEmpty(batch).stream()
|
||||
.map(NodeMetaData::getId)
|
||||
.map(Object::toString)
|
||||
.collect(joining(","));
|
||||
logger.trace("[{} / {} / {} / {}] Worker has been created for nodes {}", coreName, trackerId, iterationId, worker.hashCode(), nodes);
|
||||
}
|
||||
this.threadHandler.scheduleTask(worker);
|
||||
}
|
||||
while (stack.size() > 0);
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ public class CommitTracker extends AbstractTracker
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTrack() throws Throwable
|
||||
protected void doTrack(String iterationId) throws Throwable
|
||||
{
|
||||
long currentTime = System.currentTimeMillis();
|
||||
boolean commitNeeded = false;
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ public class ContentTracker extends AbstractTracker implements Tracker
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTrack() throws Exception
|
||||
protected void doTrack(String iterationId) throws Exception
|
||||
{
|
||||
//System.out.println("############## Content Tracker doTrack()");
|
||||
try {
|
||||
|
||||
+3
-3
@@ -118,7 +118,7 @@ public abstract class CoreStatePublisher extends AbstractTracker
|
||||
updateShardProperty();
|
||||
if (shardProperty.isEmpty())
|
||||
{
|
||||
LOGGER.warn("Sharding property {} was set to {}, but no such property was found.", SHARD_KEY_KEY, shardKeyName);
|
||||
logger.warn("Sharding property {} was set to {}, but no such property was found.", SHARD_KEY_KEY, shardKeyName);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -134,11 +134,11 @@ public abstract class CoreStatePublisher extends AbstractTracker
|
||||
{
|
||||
if (updatedShardProperty.isEmpty())
|
||||
{
|
||||
LOGGER.warn("The model defining {} property has been disabled", shardKeyName);
|
||||
logger.warn("The model defining {} property has been disabled", shardKeyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.info("New {} property found for {} ", SHARD_KEY_KEY, shardKeyName);
|
||||
logger.info("New {} property found for {} ", SHARD_KEY_KEY, shardKeyName);
|
||||
}
|
||||
}
|
||||
shardProperty = updatedShardProperty;
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ public class MetadataTracker extends CoreStatePublisher implements Tracker
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTrack() throws AuthenticationException, IOException, JSONException, EncoderException
|
||||
protected void doTrack(String iterationId) throws AuthenticationException, IOException, JSONException, EncoderException
|
||||
{
|
||||
log.debug("### MetadataTracker doTrack ###");
|
||||
// MetadataTracker must wait until ModelTracker has run
|
||||
|
||||
+5
-5
@@ -106,7 +106,7 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
super(p, client, coreName, informationServer, Tracker.Type.MODEL);
|
||||
String normalSolrHome = SolrResourceLoader.normalizeDir(solrHome);
|
||||
alfrescoModelDir = new File(ConfigUtil.locateProperty("solr.model.dir", normalSolrHome+"alfrescoModels"));
|
||||
LOGGER.info("Alfresco Model dir " + alfrescoModelDir);
|
||||
logger.info("Alfresco Model dir " + alfrescoModelDir);
|
||||
if (!alfrescoModelDir.exists())
|
||||
{
|
||||
alfrescoModelDir.mkdir();
|
||||
@@ -191,13 +191,13 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTrack() throws AuthenticationException, IOException, JSONException
|
||||
protected void doTrack(String iterationId) throws AuthenticationException, IOException, JSONException
|
||||
{
|
||||
// Is the InformationServer ready to update
|
||||
int registeredSearcherCount = this.infoSrv.getRegisteredSearcherCount();
|
||||
if (registeredSearcherCount >= getMaxLiveSearchers())
|
||||
{
|
||||
LOGGER.info(".... skipping tracking registered searcher count = " + registeredSearcherCount);
|
||||
logger.info(".... skipping tracking registered searcher count = " + registeredSearcherCount);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
LOGGER.error("Model tracking failed for core: "+ coreName, t);
|
||||
logger.error("Model tracking failed for core: "+ coreName, t);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -534,7 +534,7 @@ public class ModelTracker extends AbstractTracker implements Tracker
|
||||
{
|
||||
loadedModels.add(modelName);
|
||||
}
|
||||
LOGGER.info("Loading model " + model.getName());
|
||||
logger.info("Loading model " + model.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -58,7 +58,7 @@ public class SlaveCoreStatePublisher extends CoreStatePublisher
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTrack()
|
||||
protected void doTrack(String iterationId)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -67,7 +67,7 @@ public class SlaveCoreStatePublisher extends CoreStatePublisher
|
||||
}
|
||||
catch (EncoderException | IOException | AuthenticationException exception )
|
||||
{
|
||||
LOGGER.error("Unable to publish this node state. " +
|
||||
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);
|
||||
}
|
||||
|
||||
+3
@@ -30,6 +30,9 @@ alfresco.hole.check.after=300000
|
||||
alfresco.batch.count=5000
|
||||
alfresco.recordUnindexedNodes=false
|
||||
|
||||
# max time (in msecs) a given tracker instance will try to acquire a lock on a given DBID
|
||||
alfresco.tracker.maxNodeLockMs=120000
|
||||
|
||||
# encryption
|
||||
|
||||
# none, https
|
||||
|
||||
+3
@@ -30,6 +30,9 @@ alfresco.hole.check.after=300000
|
||||
alfresco.batch.count=5000
|
||||
alfresco.recordUnindexedNodes=false
|
||||
|
||||
# max time (in msecs) a given tracker instance will try to acquire a lock on a given DBID
|
||||
alfresco.tracker.maxNodeLockMs=120000
|
||||
|
||||
# encryption
|
||||
|
||||
# none, https
|
||||
|
||||
+2
-2
@@ -71,7 +71,7 @@ public class ContentTrackerIT
|
||||
|
||||
public void doTrackWithNoContentDoesNothing() throws Exception
|
||||
{
|
||||
this.contentTracker.doTrack();
|
||||
this.contentTracker.doTrack("anIterationId");
|
||||
verify(srv, never()).updateContentToIndexAndCache(anyLong(), anyString());
|
||||
verify(srv, never()).commit();
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public class ContentTrackerIT
|
||||
.thenReturn(docs1)
|
||||
.thenReturn(docs2)
|
||||
.thenReturn(emptyList);
|
||||
this.contentTracker.doTrack();
|
||||
this.contentTracker.doTrack("anIterationId");
|
||||
|
||||
InOrder order = inOrder(srv);
|
||||
order.verify(srv).getDocsWithUncleanContent(0, READ_BATCH);
|
||||
|
||||
+2
-2
@@ -117,7 +117,7 @@ public class MetadataTrackerTest
|
||||
nodes.add(node );
|
||||
when(repositoryClient.getNodes(any(GetNodesParameters.class), anyInt())).thenReturn(nodes);
|
||||
|
||||
this.metadataTracker.doTrack();
|
||||
this.metadataTracker.doTrack("AnIterationId");
|
||||
|
||||
InOrder inOrder = inOrder(srv);
|
||||
inOrder.verify(srv).indexNodes(nodes, true);
|
||||
@@ -141,7 +141,7 @@ public class MetadataTrackerTest
|
||||
when(repositoryClient.getTransactions(anyLong(), anyLong(), anyLong(), anyLong(), anyInt(), any(ShardState.class))).thenReturn(txs);
|
||||
when(repositoryClient.getTransactions(anyLong(), anyLong(), anyLong(), anyLong(), anyInt())).thenReturn(txs);
|
||||
|
||||
this.metadataTracker.doTrack();
|
||||
this.metadataTracker.doTrack("AnIterationId");
|
||||
|
||||
verify(srv, never()).commit();
|
||||
}
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ public class ModelTrackerIT
|
||||
public void testDoTrack() throws AuthenticationException, IOException, JSONException
|
||||
{
|
||||
ModelTracker spiedModelTracker = spy(this.modelTracker);
|
||||
spiedModelTracker.doTrack();
|
||||
spiedModelTracker.doTrack("AnIterationId");
|
||||
|
||||
verify(this.srv).getRegisteredSearcherCount();
|
||||
verify(spiedModelTracker).trackModels(false);
|
||||
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2020 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.client;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import static java.util.stream.Collector.of;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* This is an enhanced {@link BufferedReader} used for transparently collect data from the incoming stream before
|
||||
* it gets consumed by the usual buffered reader logic. The data is not actually consumed, it is just buffered beside and
|
||||
* it can be printed in case we want to debug the underlying stream content.
|
||||
*
|
||||
* The name refers to the usage pattern: this reader is used for wrapping a character stream coming from a remote call and, in case
|
||||
* of issues, it collects the remaining (i.e. unread) part of the stream so it will be available for debugging purposes.
|
||||
*
|
||||
* It provides two different collecting modes:
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* windowing: the collected data is a window of the original stream (about 500 chars), and the character that
|
||||
* caused a stop in the reading is more or less in the middle of that window.
|
||||
* </li>
|
||||
* <li>
|
||||
* everything: the collected data is the whole character stream
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* The two modes are activated on each instance depending on the level of the {@link Logger} passed in input.
|
||||
* Specifically:
|
||||
*
|
||||
* <ul>
|
||||
* <li>DEBUG: enables the windowing mode</li>
|
||||
* <li>TRACE: enables the "collect everything" mode</li>
|
||||
* <li>other levels simply disables the buffering behaviour (i.e. nothing is collected)</li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
public class LookAheadBufferedReader extends BufferedReader
|
||||
{
|
||||
final static String BUFFERING_DISABLED_INFO_MESSAGE = "Not available: please set the logging LEVEL to DEBUG or TRACE.";
|
||||
|
||||
private interface BufferingMode
|
||||
{
|
||||
void append(char ch);
|
||||
|
||||
void forceAppend(char ch);
|
||||
|
||||
boolean canAccept(boolean force);
|
||||
}
|
||||
|
||||
private static class Windowing implements BufferingMode
|
||||
{
|
||||
private final LinkedList<Character> window = new LinkedList<>();
|
||||
private final int maxSize;
|
||||
|
||||
private Windowing(int maxSize)
|
||||
{
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void append(char ch)
|
||||
{
|
||||
window.add(ch);
|
||||
if (window.size() == maxSize)
|
||||
{
|
||||
window.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceAppend(char ch)
|
||||
{
|
||||
window.add(ch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept(boolean force)
|
||||
{
|
||||
return window.size() < (maxSize * 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return window.stream()
|
||||
.collect(
|
||||
of(
|
||||
StringBuilder::new,
|
||||
StringBuilder::append,
|
||||
StringBuilder::append,
|
||||
StringBuilder::toString));
|
||||
}
|
||||
}
|
||||
|
||||
private static class WholeValue implements BufferingMode
|
||||
{
|
||||
private final StringBuilder content = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public void append(char ch)
|
||||
{
|
||||
content.append(ch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceAppend(char ch)
|
||||
{
|
||||
content.append(ch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept(boolean force)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoOp implements BufferingMode
|
||||
{
|
||||
@Override
|
||||
public void append(char ch)
|
||||
{
|
||||
// Nothing to be done here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceAppend(char ch)
|
||||
{
|
||||
// Nothing to be done here
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept(boolean force)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return BUFFERING_DISABLED_INFO_MESSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
private final BufferingMode bufferingMode;
|
||||
|
||||
LookAheadBufferedReader(Reader in, final int windowSize, boolean isDebugEnabled, boolean isTraceEnabled)
|
||||
{
|
||||
super(in);
|
||||
if (isTraceEnabled)
|
||||
{
|
||||
bufferingMode = new WholeValue();
|
||||
}
|
||||
else if(isDebugEnabled)
|
||||
{
|
||||
bufferingMode = new Windowing(windowSize);
|
||||
}
|
||||
else {
|
||||
bufferingMode = new NoOp();
|
||||
}
|
||||
}
|
||||
|
||||
public LookAheadBufferedReader(Reader in, final int windowSize, Logger logger)
|
||||
{
|
||||
this(in, windowSize, logger.isDebugEnabled(), logger.isTraceEnabled());
|
||||
}
|
||||
|
||||
public LookAheadBufferedReader(Reader in, Logger logger)
|
||||
{
|
||||
this(in, 250, logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException
|
||||
{
|
||||
int ch = super.read();
|
||||
|
||||
if (ch != -1) bufferingMode.append((char)ch);
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
public String lookAheadAndGetBufferedContent()
|
||||
{
|
||||
try
|
||||
{
|
||||
int ch;
|
||||
while ((ch = super.read()) != -1 && bufferingMode.canAccept(true))
|
||||
{
|
||||
bufferingMode.forceAppend((char) ch);
|
||||
}
|
||||
}
|
||||
catch (Exception ignore)
|
||||
{
|
||||
// Ignore any I/O exception causing further reading on the underlying stream
|
||||
// Just return the collected data
|
||||
}
|
||||
return bufferingMode.toString();
|
||||
}
|
||||
|
||||
boolean isInWindowingMode()
|
||||
{
|
||||
return bufferingMode instanceof Windowing;
|
||||
}
|
||||
|
||||
boolean isInCollectEverythingMode()
|
||||
{
|
||||
return bufferingMode instanceof WholeValue;
|
||||
}
|
||||
|
||||
boolean isBufferingDisabled()
|
||||
{
|
||||
return bufferingMode instanceof NoOp;
|
||||
}
|
||||
}
|
||||
+29
-28
@@ -1,31 +1,32 @@
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
/*
|
||||
* #%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.client;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
/**
|
||||
* Stores node meta data query parameters for use in SOLR remote api calls
|
||||
@@ -39,7 +40,7 @@ public class NodeMetaDataParameters
|
||||
private Long toTxnId;
|
||||
|
||||
// default is 'all' results
|
||||
private int maxResults = 0;
|
||||
private OptionalInt maxResults = OptionalInt.empty();
|
||||
|
||||
private Long fromNodeId;
|
||||
private Long toNodeId;
|
||||
@@ -147,14 +148,14 @@ public class NodeMetaDataParameters
|
||||
this.includeParentAssociations = includeParentAssociations;
|
||||
}
|
||||
|
||||
public int getMaxResults()
|
||||
public OptionalInt getMaxResults()
|
||||
{
|
||||
return maxResults;
|
||||
}
|
||||
|
||||
public void setMaxResults(int maxResults)
|
||||
{
|
||||
this.maxResults = maxResults;
|
||||
this.maxResults = OptionalInt.of(maxResults);
|
||||
}
|
||||
|
||||
public List<Long> getNodeIds()
|
||||
|
||||
+149
-210
@@ -25,27 +25,15 @@
|
||||
*/
|
||||
package org.alfresco.solr.client;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.httpclient.AlfrescoHttpClient;
|
||||
import org.alfresco.httpclient.AuthenticationException;
|
||||
import org.alfresco.httpclient.GetRequest;
|
||||
import org.alfresco.httpclient.PostRequest;
|
||||
import org.alfresco.httpclient.Request;
|
||||
import org.alfresco.httpclient.Response;
|
||||
import org.alfresco.repo.dictionary.M2Model;
|
||||
import org.alfresco.repo.dictionary.NamespaceDAO;
|
||||
@@ -81,9 +69,23 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.extensions.surf.util.URLEncoder;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
// TODO error handling, including dealing with a repository that is not responsive (ConnectException in sendRemoteRequest)
|
||||
// TODO get text content transform status handling
|
||||
@@ -94,7 +96,7 @@ import com.fasterxml.jackson.core.JsonToken;
|
||||
*/
|
||||
public class SOLRAPIClient
|
||||
{
|
||||
protected final static Logger log = LoggerFactory.getLogger(SOLRAPIClient.class);
|
||||
protected final static Logger LOGGER = LoggerFactory.getLogger(SOLRAPIClient.class);
|
||||
private static final String GET_ACL_CHANGESETS_URL = "api/solr/aclchangesets";
|
||||
private static final String GET_ACLS = "api/solr/acls";
|
||||
private static final String GET_ACLS_READERS = "api/solr/aclsReaders";
|
||||
@@ -142,7 +144,7 @@ public class SOLRAPIClient
|
||||
this.jsonFactory = new JsonFactory();
|
||||
this.compression = compression;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the ACL ChangeSets
|
||||
*
|
||||
@@ -179,32 +181,7 @@ public class SOLRAPIClient
|
||||
url.append(args);
|
||||
|
||||
GetRequest req = new GetRequest(url.toString());
|
||||
Response response = null;
|
||||
JSONObject json = null;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(req);
|
||||
|
||||
if (response.getStatus() != HttpStatus.SC_OK)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(GET_ACL_CHANGESETS_URL + " return status:" + response.getStatus());
|
||||
}
|
||||
|
||||
Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8"));
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(response != null)
|
||||
{
|
||||
response.release();
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug(json.toString(3));
|
||||
}
|
||||
JSONObject json = callRepository(GET_ACL_CHANGESETS_URL, req);
|
||||
|
||||
JSONArray aclChangeSetsJSON = json.getJSONArray("aclChangeSets");
|
||||
List<AclChangeSet> aclChangeSets = new ArrayList<AclChangeSet>(aclChangeSetsJSON.length());
|
||||
@@ -217,8 +194,7 @@ public class SOLRAPIClient
|
||||
AclChangeSet aclChangeSet = new AclChangeSet(aclChangeSetId, commitTimeMs, aclCount);
|
||||
aclChangeSets.add(aclChangeSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Long maxChangeSetCommitTime = null;
|
||||
if(json.has("maxChangeSetCommitTime"))
|
||||
{
|
||||
@@ -273,32 +249,7 @@ public class SOLRAPIClient
|
||||
jsonReq.put("aclChangeSetIds", aclChangeSetIdsJSON);
|
||||
|
||||
PostRequest req = new PostRequest(url.toString(), jsonReq.toString(), "application/json");
|
||||
Response response = null;
|
||||
JSONObject json = null;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(req);
|
||||
|
||||
if (response.getStatus() != HttpStatus.SC_OK)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(GET_ACL_CHANGESETS_URL + " return status:" + response.getStatus());
|
||||
}
|
||||
|
||||
Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8"));
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(response != null)
|
||||
{
|
||||
response.release();
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug(json.toString(3));
|
||||
}
|
||||
JSONObject json = callRepository(GET_ACL_CHANGESETS_URL, req);
|
||||
|
||||
JSONArray aclsJSON = json.getJSONArray("acls");
|
||||
List<Acl> acls = new ArrayList<Acl>(aclsJSON.length());
|
||||
@@ -336,32 +287,7 @@ public class SOLRAPIClient
|
||||
jsonReq.put("aclIds", aclIdsJSON);
|
||||
|
||||
PostRequest req = new PostRequest(url.toString(), jsonReq.toString(), "application/json");
|
||||
Response response = null;
|
||||
JSONObject json = null;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(req);
|
||||
|
||||
if (response.getStatus() != HttpStatus.SC_OK)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(GET_ACLS_READERS + " return status:" + response.getStatus());
|
||||
}
|
||||
|
||||
Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8"));
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(response != null)
|
||||
{
|
||||
response.release();
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug(json.toString(3));
|
||||
}
|
||||
JSONObject json = callRepository(GET_ACLS_READERS, req);
|
||||
|
||||
JSONArray aclsReadersJSON = json.getJSONArray("aclsReaders");
|
||||
List<AclReaders> aclsReaders = new ArrayList<AclReaders>(aclsReadersJSON.length());
|
||||
@@ -421,7 +347,6 @@ public class SOLRAPIClient
|
||||
|
||||
public Transactions getTransactions(Long fromCommitTime, Long minTxnId, Long toCommitTime, Long maxTxnId, int maxResults, ShardState shardState) throws AuthenticationException, IOException, JSONException, EncoderException
|
||||
{
|
||||
log.debug("### get transactions ###");
|
||||
URLCodec encoder = new URLCodec();
|
||||
|
||||
StringBuilder url = new StringBuilder(GET_TRANSACTIONS_URL);
|
||||
@@ -448,7 +373,7 @@ public class SOLRAPIClient
|
||||
}
|
||||
if(shardState != null)
|
||||
{
|
||||
log.debug("### Shard state exists ###");
|
||||
LOGGER.debug("### Shard state exists ###");
|
||||
args.append(args.length() == 0 ? "?" : "&");
|
||||
args.append(encoder.encode("baseUrl")).append("=").append(encoder.encode(shardState.getShardInstance().getBaseUrl()));
|
||||
args.append("&").append(encoder.encode("hostName")).append("=").append(encoder.encode(shardState.getShardInstance().getHostName()));
|
||||
@@ -497,12 +422,14 @@ public class SOLRAPIClient
|
||||
}
|
||||
|
||||
url.append(args);
|
||||
log.debug("### GetRequest: " + url.toString());
|
||||
LOGGER.debug("### GetRequest: " + url.toString());
|
||||
GetRequest req = new GetRequest(url.toString());
|
||||
Response response = null;
|
||||
List<Transaction> transactions = new ArrayList<Transaction>();
|
||||
Long maxTxnCommitTime = null;
|
||||
Long maxTxnIdOnServer = null;
|
||||
|
||||
LookAheadBufferedReader reader = null;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(req);
|
||||
@@ -510,7 +437,8 @@ public class SOLRAPIClient
|
||||
{
|
||||
throw new AlfrescoRuntimeException("GetTransactions return status is " + response.getStatus());
|
||||
}
|
||||
Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8"));
|
||||
|
||||
reader = new LookAheadBufferedReader(new InputStreamReader(response.getContentAsStream(), StandardCharsets.UTF_8), LOGGER);
|
||||
JsonParser parser = jsonFactory.createParser(reader);
|
||||
|
||||
JsonToken token = parser.nextValue();
|
||||
@@ -556,18 +484,25 @@ public class SOLRAPIClient
|
||||
token = parser.nextValue();
|
||||
}
|
||||
parser.close();
|
||||
reader.close();
|
||||
|
||||
}
|
||||
catch (JSONException exception)
|
||||
{
|
||||
String message = "Received a malformed JSON payload. Request was \"" +
|
||||
req.getFullUri() +
|
||||
"Data: "
|
||||
+ ofNullable(reader)
|
||||
.map(LookAheadBufferedReader::lookAheadAndGetBufferedContent)
|
||||
.orElse("Not available");
|
||||
LOGGER.error(message);
|
||||
throw exception;
|
||||
}
|
||||
finally
|
||||
{
|
||||
log.debug("## end getTransactions");
|
||||
if(response != null)
|
||||
{
|
||||
response.release();
|
||||
}
|
||||
ofNullable(response).ifPresent(Response::release);
|
||||
ofNullable(reader).ifPresent(this::silentlyClose);
|
||||
}
|
||||
log.debug("### Transactions found maxTxnCommitTime: " + maxTxnCommitTime );
|
||||
|
||||
LOGGER.debug("### Transactions found maxTxnCommitTime: " + maxTxnCommitTime );
|
||||
return new Transactions(transactions, maxTxnCommitTime, maxTxnIdOnServer);
|
||||
}
|
||||
|
||||
@@ -637,35 +572,10 @@ public class SOLRAPIClient
|
||||
|
||||
|
||||
PostRequest req = new PostRequest(url.toString(), body.toString(), "application/json");
|
||||
|
||||
Response response = null;
|
||||
JSONObject json = null;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(req);
|
||||
if(response.getStatus() != HttpStatus.SC_OK)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("GetNodes return status is " + response.getStatus());
|
||||
}
|
||||
|
||||
Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8"));
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(response != null)
|
||||
{
|
||||
response.release();
|
||||
}
|
||||
}
|
||||
|
||||
if(log.isDebugEnabled())
|
||||
{
|
||||
log.debug(json.toString());
|
||||
}
|
||||
JSONObject json = callRepository(GET_NODES_URL, req);
|
||||
|
||||
JSONArray jsonNodes = json.getJSONArray("nodes");
|
||||
List<Node> nodes = new ArrayList<Node>(jsonNodes.length());
|
||||
List<Node> nodes = new ArrayList<>(jsonNodes.length());
|
||||
for(int i = 0; i < jsonNodes.length(); i++)
|
||||
{
|
||||
JSONObject jsonNodeInfo = jsonNodes.getJSONObject(i);
|
||||
@@ -821,7 +731,7 @@ public class SOLRAPIClient
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<NodeMetaData> getNodesMetaData(NodeMetaDataParameters params, int maxResults) throws AuthenticationException, IOException, JSONException
|
||||
public List<NodeMetaData> getNodesMetaData(NodeMetaDataParameters params) throws AuthenticationException, IOException, JSONException
|
||||
{
|
||||
List<Long> nodeIds = params.getNodeIds();
|
||||
|
||||
@@ -890,38 +800,16 @@ public class SOLRAPIClient
|
||||
body.put("includeTxnId", params.isIncludeTxnId());
|
||||
}
|
||||
|
||||
body.put("maxResults", maxResults);
|
||||
if (params.getMaxResults().isPresent())
|
||||
{
|
||||
body.put("maxResults", params.getMaxResults().getAsInt());
|
||||
}
|
||||
|
||||
PostRequest req = new PostRequest(url.toString(), body.toString(), "application/json");
|
||||
Response response = null;
|
||||
JSONObject json = null;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(req);
|
||||
if(response.getStatus() != HttpStatus.SC_OK)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("GetNodeMetaData return status is " + response.getStatus());
|
||||
}
|
||||
|
||||
Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8"));
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(response != null)
|
||||
{
|
||||
response.release();
|
||||
}
|
||||
}
|
||||
JSONObject json = callRepository(GET_METADATA_URL, req);
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug(json.toString(3));
|
||||
}
|
||||
|
||||
JSONArray jsonNodes = json.getJSONArray("nodes");
|
||||
|
||||
List<NodeMetaData> nodes = new ArrayList<NodeMetaData>(jsonNodes.length());
|
||||
List<NodeMetaData> nodes = new ArrayList<>(jsonNodes.length());
|
||||
for(int i = 0; i < jsonNodes.length(); i++)
|
||||
{
|
||||
JSONObject jsonNodeInfo = jsonNodes.getJSONObject(i);
|
||||
@@ -1159,7 +1047,7 @@ public class SOLRAPIClient
|
||||
return new GetTextContentResponse(response);
|
||||
}
|
||||
|
||||
public AlfrescoModel getModel(String coreName, QName modelName) throws AuthenticationException, IOException, JSONException
|
||||
public AlfrescoModel getModel(String coreName, QName modelName) throws AuthenticationException, IOException
|
||||
{
|
||||
// If the model is new to the SOLR side the prefix will be unknown so we can not generate prefixes for the request!
|
||||
// Always use the full QName with explicit URI
|
||||
@@ -1209,31 +1097,8 @@ public class SOLRAPIClient
|
||||
body.put("models", jsonModels);
|
||||
|
||||
PostRequest req = new PostRequest(url.toString(), body.toString(), "application/json");
|
||||
Response response = null;
|
||||
JSONObject json = null;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(req);
|
||||
if(response.getStatus() != HttpStatus.SC_OK)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(coreName + " GetModelsDiff return status is " + response.getStatus());
|
||||
}
|
||||
|
||||
Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8"));
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(response != null)
|
||||
{
|
||||
response.release();
|
||||
}
|
||||
}
|
||||
|
||||
if(log.isDebugEnabled())
|
||||
{
|
||||
log.debug(json.toString());
|
||||
}
|
||||
JSONObject json = callRepository(GET_MODELS_DIFF, req);
|
||||
|
||||
JSONArray jsonDiffs = json.getJSONArray("diffs");
|
||||
if(jsonDiffs == null)
|
||||
{
|
||||
@@ -1271,6 +1136,7 @@ public class SOLRAPIClient
|
||||
GetRequest get = new GetRequest(url.toString());
|
||||
Response response = null;
|
||||
JSONObject json = null;
|
||||
LookAheadBufferedReader reader = null;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(get);
|
||||
@@ -1280,19 +1146,29 @@ public class SOLRAPIClient
|
||||
+ response.getStatus() + " when invoking " + url);
|
||||
}
|
||||
|
||||
Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8"));
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
reader = new LookAheadBufferedReader(new InputStreamReader(response.getContentAsStream(), StandardCharsets.UTF_8), LOGGER);
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
}
|
||||
catch (JSONException exception)
|
||||
{
|
||||
String message = "Received a malformed JSON payload. Request was \"" +
|
||||
get.getFullUri() +
|
||||
"Data: "
|
||||
+ ofNullable(reader)
|
||||
.map(LookAheadBufferedReader::lookAheadAndGetBufferedContent)
|
||||
.orElse("Not available");
|
||||
LOGGER.error(message);
|
||||
throw exception;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
response.release();
|
||||
}
|
||||
ofNullable(response).ifPresent(Response::release);
|
||||
ofNullable(reader).ifPresent(this::silentlyClose);
|
||||
}
|
||||
if (log.isDebugEnabled())
|
||||
|
||||
if (LOGGER.isDebugEnabled())
|
||||
{
|
||||
log.debug(json.toString());
|
||||
LOGGER.debug(json.toString());
|
||||
}
|
||||
|
||||
return Long.parseLong(json.get("nextTransactionCommitTimeMs").toString());
|
||||
@@ -1318,6 +1194,7 @@ public class SOLRAPIClient
|
||||
GetRequest get = new GetRequest(url.toString());
|
||||
Response response = null;
|
||||
JSONObject json = null;
|
||||
LookAheadBufferedReader reader = null;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(get);
|
||||
@@ -1327,19 +1204,29 @@ public class SOLRAPIClient
|
||||
+ response.getStatus() + " when invoking " + url);
|
||||
}
|
||||
|
||||
Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8"));
|
||||
reader = new LookAheadBufferedReader(new InputStreamReader(response.getContentAsStream(), StandardCharsets.UTF_8), LOGGER);
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
}
|
||||
catch(JSONException exception)
|
||||
{
|
||||
String message = "Received a malformed JSON payload. Request was \"" +
|
||||
get.getFullUri() +
|
||||
"Data: "
|
||||
+ ofNullable(reader)
|
||||
.map(LookAheadBufferedReader::lookAheadAndGetBufferedContent)
|
||||
.orElse("Not available");
|
||||
LOGGER.error(message);
|
||||
throw exception;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
response.release();
|
||||
}
|
||||
ofNullable(response).ifPresent(Response::release);
|
||||
ofNullable(reader).ifPresent(this::silentlyClose);
|
||||
}
|
||||
if (log.isDebugEnabled())
|
||||
|
||||
if (LOGGER.isDebugEnabled())
|
||||
{
|
||||
log.debug(json.toString());
|
||||
LOGGER.debug(json.toString());
|
||||
}
|
||||
|
||||
return new Pair<Long, Long>(Long.parseLong(json.get("minTransactionCommitTimeMs").toString()),
|
||||
@@ -1692,4 +1579,56 @@ public class SOLRAPIClient
|
||||
{
|
||||
repositoryHttpClient.close();
|
||||
}
|
||||
|
||||
private JSONObject callRepository(String msgId, Request req) throws IOException, AuthenticationException
|
||||
{
|
||||
Response response = null;
|
||||
LookAheadBufferedReader reader = null;
|
||||
JSONObject json;
|
||||
try
|
||||
{
|
||||
response = repositoryHttpClient.sendRequest(req);
|
||||
if (response.getStatus() != HttpStatus.SC_OK)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(msgId + " return status:" + response.getStatus());
|
||||
}
|
||||
|
||||
reader = new LookAheadBufferedReader(new InputStreamReader(response.getContentAsStream(), StandardCharsets.UTF_8), LOGGER);
|
||||
json = new JSONObject(new JSONTokener(reader));
|
||||
|
||||
if (LOGGER.isDebugEnabled())
|
||||
{
|
||||
LOGGER.debug(json.toString(3));
|
||||
}
|
||||
return json;
|
||||
}
|
||||
catch (JSONException exception)
|
||||
{
|
||||
String message = "Received a malformed JSON payload. Request was \"" +
|
||||
req.getFullUri() +
|
||||
"Data: "
|
||||
+ ofNullable(reader)
|
||||
.map(LookAheadBufferedReader::lookAheadAndGetBufferedContent)
|
||||
.orElse("Not available");
|
||||
LOGGER.error(message);
|
||||
throw exception;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ofNullable(response).ifPresent(Response::release);
|
||||
ofNullable(reader).ifPresent(this::silentlyClose);
|
||||
}
|
||||
}
|
||||
|
||||
private void silentlyClose(Closeable closeable)
|
||||
{
|
||||
try
|
||||
{
|
||||
closeable.close();
|
||||
}
|
||||
catch (Exception ignore)
|
||||
{
|
||||
// Nothing to be done here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -285,7 +285,8 @@ public class SOLRAPIQueueClient extends SOLRAPIClient
|
||||
return allNodes;
|
||||
}
|
||||
|
||||
public List<NodeMetaData> getNodesMetaData(NodeMetaDataParameters params, int maxResults) throws AuthenticationException, IOException, JSONException
|
||||
@Override
|
||||
public List<NodeMetaData> getNodesMetaData(NodeMetaDataParameters params) throws AuthenticationException, IOException, JSONException
|
||||
{
|
||||
if(throwException) {
|
||||
throw new ConnectException("THROWING EXCEPTION, better be ready!");
|
||||
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
/*-
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 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.client;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
import static java.util.stream.IntStream.range;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LookAheadBufferedReaderTest
|
||||
{
|
||||
@Mock
|
||||
Reader reader;
|
||||
|
||||
private final String data = "1234567890ABCDEFGHILMNOPQRSTUVYXZ";
|
||||
|
||||
@Test
|
||||
public void windowingModeEnabled()
|
||||
{
|
||||
LookAheadBufferedReader classUnderTest = new LookAheadBufferedReader(reader, data.length(), true, false);
|
||||
assertTrue(classUnderTest.isInWindowingMode());
|
||||
assertFalse(classUnderTest.isInCollectEverythingMode());
|
||||
assertFalse(classUnderTest.isBufferingDisabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectEverythingModeEnabled()
|
||||
{
|
||||
LookAheadBufferedReader classUnderTest = new LookAheadBufferedReader(reader, data.length(), false, true);
|
||||
assertTrue(classUnderTest.isInCollectEverythingMode());
|
||||
assertFalse(classUnderTest.isInWindowingMode());
|
||||
assertFalse(classUnderTest.isBufferingDisabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bufferingDisabled()
|
||||
{
|
||||
LookAheadBufferedReader classUnderTest = new LookAheadBufferedReader(reader, data.length(), false, false);
|
||||
assertTrue(classUnderTest.isBufferingDisabled());
|
||||
assertFalse(classUnderTest.isInCollectEverythingMode());
|
||||
assertFalse(classUnderTest.isInWindowingMode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectEverythingWinsOverWindowing()
|
||||
{
|
||||
LookAheadBufferedReader classUnderTest = new LookAheadBufferedReader(reader, data.length(), true, true);
|
||||
assertTrue(classUnderTest.isInCollectEverythingMode());
|
||||
assertFalse(classUnderTest.isInWindowingMode());
|
||||
assertFalse(classUnderTest.isBufferingDisabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void windowingModeShouldCollectPartialWindowsOfData()
|
||||
{
|
||||
int windowSize = 10;
|
||||
Reader reader = new StringReader(data);
|
||||
LookAheadBufferedReader classUnderTest = new LookAheadBufferedReader(reader, windowSize, true, false);
|
||||
|
||||
// Read only 12 chars from the underlying stream
|
||||
range(0, 12).forEach(index -> consume(classUnderTest));
|
||||
|
||||
String collectedWindow = classUnderTest.lookAheadAndGetBufferedContent();
|
||||
|
||||
assertEquals(windowSize * 2, collectedWindow.length());
|
||||
assertEquals("4567890ABCDEFGHILMNO", collectedWindow);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notEnoughCharsForTheWindow()
|
||||
{
|
||||
int windowSize = 10;
|
||||
Reader reader = new StringReader(data);
|
||||
LookAheadBufferedReader classUnderTest = new LookAheadBufferedReader(reader, windowSize, true, false);
|
||||
|
||||
range(0, data.length() - 3).forEach(index -> consume(classUnderTest));
|
||||
|
||||
String collectedWindow = classUnderTest.lookAheadAndGetBufferedContent();
|
||||
|
||||
assertEquals(windowSize + 2, collectedWindow.length());
|
||||
assertEquals("NOPQRSTUVYXZ", collectedWindow);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyDataShouldCollectEmptyWindow()
|
||||
{
|
||||
Reader reader = new StringReader("");
|
||||
LookAheadBufferedReader classUnderTest = new LookAheadBufferedReader(reader, 10, true, false);
|
||||
|
||||
range(0, data.length() - 3).forEach(index -> consume(classUnderTest));
|
||||
|
||||
String collectedWindow = classUnderTest.lookAheadAndGetBufferedContent();
|
||||
|
||||
assertEquals(0, collectedWindow.length());
|
||||
assertEquals("", collectedWindow);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectEverythingModeShouldCollectTheWholeStream()
|
||||
{
|
||||
Reader reader = new StringReader(data);
|
||||
LookAheadBufferedReader classUnderTest =
|
||||
new LookAheadBufferedReader(
|
||||
reader,
|
||||
10, // this has no effect
|
||||
false,
|
||||
true);
|
||||
|
||||
// Read only 12 chars from the underlying stream
|
||||
range(0, 12).forEach(index -> consume(classUnderTest));
|
||||
|
||||
String collectedData = classUnderTest.lookAheadAndGetBufferedContent();
|
||||
|
||||
assertEquals(data.length(), collectedData.length());
|
||||
assertEquals(data, collectedData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyDataShouldCollectEmptyStringInCollectEverythingMode()
|
||||
{
|
||||
Reader reader = new StringReader("");
|
||||
LookAheadBufferedReader classUnderTest =
|
||||
new LookAheadBufferedReader(
|
||||
reader,
|
||||
10, // this has no effect
|
||||
false,
|
||||
true);
|
||||
|
||||
range(0, data.length() - 3).forEach(index -> consume(classUnderTest));
|
||||
|
||||
String collectedData = classUnderTest.lookAheadAndGetBufferedContent();
|
||||
|
||||
assertEquals(0, collectedData.length());
|
||||
assertEquals("", collectedData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bufferingModeDisableShouldCollectNoData()
|
||||
{
|
||||
int windowSize = 10;
|
||||
Reader reader = new StringReader(data);
|
||||
LookAheadBufferedReader classUnderTest = new LookAheadBufferedReader(reader, windowSize, false, false);
|
||||
|
||||
// Read only 12 chars from the underlying stream
|
||||
range(0, 12).forEach(index -> consume(classUnderTest));
|
||||
assertEquals(LookAheadBufferedReader.BUFFERING_DISABLED_INFO_MESSAGE, classUnderTest.lookAheadAndGetBufferedContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyDataShouldCollectEmptyDataWhenBufferingIsDisabled()
|
||||
{
|
||||
Reader reader = new StringReader("");
|
||||
LookAheadBufferedReader classUnderTest =
|
||||
new LookAheadBufferedReader(
|
||||
reader,
|
||||
10, // this has no effect
|
||||
false,
|
||||
false);
|
||||
|
||||
range(0, data.length() - 3).forEach(index -> consume(classUnderTest));
|
||||
|
||||
String collectedData = classUnderTest.lookAheadAndGetBufferedContent();
|
||||
|
||||
assertEquals(LookAheadBufferedReader.BUFFERING_DISABLED_INFO_MESSAGE, collectedData);
|
||||
}
|
||||
|
||||
private void consume(Reader reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
reader.read();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
+116
-108
@@ -1,93 +1,93 @@
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
/*
|
||||
* #%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.client;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.alfresco.encryption.DefaultEncryptionUtils;
|
||||
import org.alfresco.encryption.KeyProvider;
|
||||
import org.alfresco.encryption.KeyResourceLoader;
|
||||
import org.alfresco.encryption.KeyStoreParameters;
|
||||
import org.alfresco.encryption.MACUtils.MACInput;
|
||||
import org.alfresco.encryption.ssl.SSLEncryptionParameters;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.httpclient.AlfrescoHttpClient;
|
||||
import org.alfresco.httpclient.AuthenticationException;
|
||||
import org.alfresco.httpclient.HttpClientFactory;
|
||||
import org.alfresco.httpclient.HttpClientFactory.SecureCommsType;
|
||||
import org.alfresco.opencmis.dictionary.CMISDictionaryRegistry;
|
||||
import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService;
|
||||
import org.alfresco.opencmis.mapping.CMISMapping;
|
||||
import org.alfresco.opencmis.mapping.RuntimePropertyLuceneBuilderMapping;
|
||||
import org.alfresco.repo.cache.MemoryCache;
|
||||
import org.alfresco.repo.dictionary.CompiledModelsCache;
|
||||
import org.alfresco.repo.dictionary.DictionaryComponent;
|
||||
import org.alfresco.repo.dictionary.DictionaryDAOImpl;
|
||||
import org.alfresco.repo.dictionary.DictionaryNamespaceComponent;
|
||||
import org.alfresco.repo.dictionary.M2Model;
|
||||
import org.alfresco.repo.dictionary.M2Namespace;
|
||||
import org.alfresco.repo.dictionary.NamespaceDAO;
|
||||
import org.alfresco.repo.i18n.StaticMessageLookup;
|
||||
import org.alfresco.repo.tenant.SingleTServiceImpl;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.DynamicallySizedThreadPoolExecutor;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TraceableThreadFactory;
|
||||
import org.alfresco.util.cache.DefaultAsynchronouslyRefreshedCacheRegistry;
|
||||
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
|
||||
import org.apache.commons.httpclient.HttpMethod;
|
||||
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.alfresco.encryption.DefaultEncryptionUtils;
|
||||
import org.alfresco.encryption.KeyProvider;
|
||||
import org.alfresco.encryption.KeyResourceLoader;
|
||||
import org.alfresco.encryption.KeyStoreParameters;
|
||||
import org.alfresco.encryption.MACUtils.MACInput;
|
||||
import org.alfresco.encryption.ssl.SSLEncryptionParameters;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.httpclient.AlfrescoHttpClient;
|
||||
import org.alfresco.httpclient.AuthenticationException;
|
||||
import org.alfresco.httpclient.HttpClientFactory;
|
||||
import org.alfresco.httpclient.HttpClientFactory.SecureCommsType;
|
||||
import org.alfresco.opencmis.dictionary.CMISDictionaryRegistry;
|
||||
import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService;
|
||||
import org.alfresco.opencmis.mapping.CMISMapping;
|
||||
import org.alfresco.opencmis.mapping.RuntimePropertyLuceneBuilderMapping;
|
||||
import org.alfresco.repo.cache.MemoryCache;
|
||||
import org.alfresco.repo.dictionary.CompiledModelsCache;
|
||||
import org.alfresco.repo.dictionary.DictionaryComponent;
|
||||
import org.alfresco.repo.dictionary.DictionaryDAOImpl;
|
||||
import org.alfresco.repo.dictionary.DictionaryNamespaceComponent;
|
||||
import org.alfresco.repo.dictionary.M2Model;
|
||||
import org.alfresco.repo.dictionary.M2Namespace;
|
||||
import org.alfresco.repo.dictionary.NamespaceDAO;
|
||||
import org.alfresco.repo.i18n.StaticMessageLookup;
|
||||
import org.alfresco.repo.tenant.SingleTServiceImpl;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.DynamicallySizedThreadPoolExecutor;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TraceableThreadFactory;
|
||||
import org.alfresco.util.cache.DefaultAsynchronouslyRefreshedCacheRegistry;
|
||||
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
|
||||
import org.apache.commons.httpclient.HttpMethod;
|
||||
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests {@link SOLRAPIClient} Note: need to make sure that source/solr/instance is on the run classpath. Note: doesn't
|
||||
* currently work, need to change to use SSL.
|
||||
@@ -109,7 +109,7 @@ public class SOLRAPIClientTest extends TestCase
|
||||
private DictionaryDAOImpl dictionaryDAO;
|
||||
|
||||
private CMISStrictDictionaryService cmisDictionaryService;
|
||||
|
||||
|
||||
private static final String CORENAME = "collection1";
|
||||
|
||||
// private M2Model testModel;
|
||||
@@ -140,10 +140,10 @@ public class SOLRAPIClientTest extends TestCase
|
||||
{
|
||||
if(client == null)
|
||||
{
|
||||
TenantService tenantService = new SingleTServiceImpl();
|
||||
TenantService tenantService = new SingleTServiceImpl();
|
||||
|
||||
dictionaryDAO = new DictionaryDAOImpl();
|
||||
NamespaceDAO namespaceDAO = dictionaryDAO;
|
||||
NamespaceDAO namespaceDAO = dictionaryDAO;
|
||||
dictionaryDAO.setTenantService(tenantService);
|
||||
|
||||
CompiledModelsCache compiledModelsCache = new CompiledModelsCache();
|
||||
@@ -163,7 +163,7 @@ public class SOLRAPIClientTest extends TestCase
|
||||
dictionaryDAO.setResourceClassLoader(getResourceClassLoader());
|
||||
dictionaryDAO.init();
|
||||
|
||||
DictionaryComponent dictionaryComponent = new DictionaryComponent();
|
||||
DictionaryComponent dictionaryComponent = new DictionaryComponent();
|
||||
dictionaryComponent.setDictionaryDAO(dictionaryDAO);
|
||||
dictionaryComponent.setMessageLookup(new StaticMessageLookup());
|
||||
|
||||
@@ -283,7 +283,7 @@ public class SOLRAPIClientTest extends TestCase
|
||||
8443, 40, 40, 0);
|
||||
// TODO need to make port configurable depending on secure comms, or just make redirects
|
||||
// work
|
||||
return httpClientFactory.getRepoClient("localhost", 8443);
|
||||
return httpClientFactory.getRepoClient("localhost", 8443);
|
||||
}
|
||||
|
||||
public ClassLoader getResourceClassLoader()
|
||||
@@ -452,7 +452,8 @@ public class SOLRAPIClientTest extends TestCase
|
||||
|
||||
NodeMetaDataParameters metaParams = new NodeMetaDataParameters();
|
||||
metaParams.setNodeIds(nodeIds);
|
||||
List<NodeMetaData> metadata = client.getNodesMetaData(metaParams, 3);
|
||||
metaParams.setMaxResults(3);
|
||||
List<NodeMetaData> metadata = client.getNodesMetaData(metaParams);
|
||||
for (NodeMetaData info : metadata)
|
||||
{
|
||||
logger.debug(info);
|
||||
@@ -463,9 +464,10 @@ public class SOLRAPIClientTest extends TestCase
|
||||
{
|
||||
NodeMetaDataParameters metaParams = new NodeMetaDataParameters();
|
||||
List<Long> nodeIds = new ArrayList<Long>(1);
|
||||
nodeIds.add(1l);
|
||||
nodeIds.add(1L);
|
||||
metaParams.setMaxResults(3);
|
||||
metaParams.setNodeIds(nodeIds);
|
||||
List<NodeMetaData> metadata = client.getNodesMetaData(metaParams, 3);
|
||||
List<NodeMetaData> metadata = client.getNodesMetaData(metaParams);
|
||||
for (NodeMetaData info : metadata)
|
||||
{
|
||||
logger.debug(info);
|
||||
@@ -473,9 +475,10 @@ public class SOLRAPIClientTest extends TestCase
|
||||
|
||||
metaParams = new NodeMetaDataParameters();
|
||||
nodeIds = new ArrayList<Long>(1);
|
||||
nodeIds.add(9l);
|
||||
nodeIds.add(9L);
|
||||
metaParams.setNodeIds(nodeIds);
|
||||
metadata = client.getNodesMetaData(metaParams, 3);
|
||||
metaParams.setMaxResults(3);
|
||||
metadata = client.getNodesMetaData(metaParams);
|
||||
for (NodeMetaData info : metadata)
|
||||
{
|
||||
logger.debug(info);
|
||||
@@ -483,9 +486,10 @@ public class SOLRAPIClientTest extends TestCase
|
||||
|
||||
metaParams = new NodeMetaDataParameters();
|
||||
nodeIds = new ArrayList<Long>(1);
|
||||
nodeIds.add(19l);
|
||||
nodeIds.add(19L);
|
||||
metaParams.setNodeIds(nodeIds);
|
||||
metadata = client.getNodesMetaData(metaParams, 3);
|
||||
metaParams.setMaxResults(3);
|
||||
metadata = client.getNodesMetaData(metaParams);
|
||||
for (NodeMetaData info : metadata)
|
||||
{
|
||||
logger.debug(info);
|
||||
@@ -495,9 +499,10 @@ public class SOLRAPIClientTest extends TestCase
|
||||
// TODO check why the category path has a null QName
|
||||
metaParams = new NodeMetaDataParameters();
|
||||
nodeIds = new ArrayList<Long>(1);
|
||||
nodeIds.add(49437l);
|
||||
nodeIds.add(49437L);
|
||||
metaParams.setNodeIds(nodeIds);
|
||||
metadata = client.getNodesMetaData(metaParams, 3);
|
||||
metaParams.setMaxResults(3);
|
||||
metadata = client.getNodesMetaData(metaParams);
|
||||
for (NodeMetaData info : metadata)
|
||||
{
|
||||
logger.debug(info);
|
||||
@@ -506,9 +511,10 @@ public class SOLRAPIClientTest extends TestCase
|
||||
// content with tags
|
||||
metaParams = new NodeMetaDataParameters();
|
||||
nodeIds = new ArrayList<Long>(1);
|
||||
nodeIds.add(49431l);
|
||||
nodeIds.add(49431L);
|
||||
metaParams.setNodeIds(nodeIds);
|
||||
metadata = client.getNodesMetaData(metaParams, 3);
|
||||
metaParams.setMaxResults(3);
|
||||
metadata = client.getNodesMetaData(metaParams);
|
||||
for (NodeMetaData info : metadata)
|
||||
{
|
||||
logger.debug(info);
|
||||
@@ -525,9 +531,10 @@ public class SOLRAPIClientTest extends TestCase
|
||||
// content with null property values for author
|
||||
metaParams = new NodeMetaDataParameters();
|
||||
nodeIds = new ArrayList<Long>(1);
|
||||
nodeIds.add(117630l);
|
||||
nodeIds.add(117630L);
|
||||
metaParams.setNodeIds(nodeIds);
|
||||
metadata = client.getNodesMetaData(metaParams, 3);
|
||||
metaParams.setMaxResults(3);
|
||||
metadata = client.getNodesMetaData(metaParams);
|
||||
for (NodeMetaData info : metadata)
|
||||
{
|
||||
logger.debug(info);
|
||||
@@ -536,9 +543,10 @@ public class SOLRAPIClientTest extends TestCase
|
||||
// content with accented characters in title properties
|
||||
metaParams = new NodeMetaDataParameters();
|
||||
nodeIds = new ArrayList<Long>(1);
|
||||
nodeIds.add(117678l);
|
||||
nodeIds.add(117678L);
|
||||
metaParams.setNodeIds(nodeIds);
|
||||
metadata = client.getNodesMetaData(metaParams, 3);
|
||||
metaParams.setMaxResults(3);
|
||||
metadata = client.getNodesMetaData(metaParams);
|
||||
for (NodeMetaData info : metadata)
|
||||
{
|
||||
logger.debug(info);
|
||||
|
||||
Reference in New Issue
Block a user