substantial refactoring
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.inteligr8.alfresco</groupId>
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
<artifactId>asie-platform-module-parent</artifactId>
|
<artifactId>asie-platform-module-parent</artifactId>
|
||||||
<version>1.1-SNAPSHOT</version>
|
<version>1.2-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.inteligr8.alfresco</groupId>
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
<artifactId>asie-platform-module-parent</artifactId>
|
<artifactId>asie-platform-module-parent</artifactId>
|
||||||
<version>1.1-SNAPSHOT</version>
|
<version>1.2-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.repo.index.shard.Shard;
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
import org.alfresco.repo.index.shard.ShardState;
|
||||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||||
import org.alfresco.service.cmr.attributes.AttributeService.AttributeQueryCallback;
|
import org.alfresco.service.cmr.attributes.AttributeService.AttributeQueryCallback;
|
||||||
@@ -23,10 +24,11 @@ import org.springframework.http.HttpStatus;
|
|||||||
|
|
||||||
import com.inteligr8.alfresco.asie.Constants;
|
import com.inteligr8.alfresco.asie.Constants;
|
||||||
import com.inteligr8.alfresco.asie.api.CoreAdminApi;
|
import com.inteligr8.alfresco.asie.api.CoreAdminApi;
|
||||||
import com.inteligr8.alfresco.asie.model.NodeParameterSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
import com.inteligr8.alfresco.asie.rest.AbstractAsieNodeWebScript;
|
import com.inteligr8.alfresco.asie.rest.AbstractAsieNodeWebScript;
|
||||||
import com.inteligr8.alfresco.asie.service.ShardBackupService;
|
import com.inteligr8.alfresco.asie.rest.model.NodeParameterSet;
|
||||||
import com.inteligr8.alfresco.asie.spi.ShardStateService;
|
import com.inteligr8.alfresco.asie.spi.ShardBackupService;
|
||||||
|
import com.inteligr8.alfresco.asie.enterprise.service.ShardStateService;
|
||||||
import com.inteligr8.solr.model.CoreMetadata;
|
import com.inteligr8.solr.model.CoreMetadata;
|
||||||
import com.inteligr8.solr.model.core.StatusRequest;
|
import com.inteligr8.solr.model.core.StatusRequest;
|
||||||
import com.inteligr8.solr.model.core.StatusResponse;
|
import com.inteligr8.solr.model.core.StatusResponse;
|
||||||
@@ -99,7 +101,9 @@ public abstract class AbstractUnregisterNodeWebScript<T extends NodeParameterSet
|
|||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
this.sss.remove(matchingCore.getKey());
|
this.sss.remove(matchingCore.getKey());
|
||||||
this.sbs.forget(shardNode);
|
|
||||||
|
Shard shard = shardNode.getShardInstance().getShard();
|
||||||
|
this.sbs.forget(ShardSet.from(shard.getFloc(), shardNode), shard.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@@ -4,8 +4,8 @@ import org.alfresco.repo.index.shard.ShardState;
|
|||||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.model.NodeShardParameterSet;
|
|
||||||
import com.inteligr8.alfresco.asie.model.ShardSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.rest.model.NodeShardParameterSet;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.nodeShard.delete")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.nodeShard.delete")
|
||||||
public class UnloadNodeShardWebScript extends AbstractUnregisterNodeWebScript<NodeShardParameterSet> {
|
public class UnloadNodeShardWebScript extends AbstractUnregisterNodeWebScript<NodeShardParameterSet> {
|
||||||
@@ -20,7 +20,7 @@ public class UnloadNodeShardWebScript extends AbstractUnregisterNodeWebScript<No
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean matches(NodeShardParameterSet params, ShardState shardState) {
|
protected boolean matches(NodeShardParameterSet params, ShardState shardState) {
|
||||||
if (!params.getShardSet().isFor(shardState))
|
if (!params.getShardSet().contains(shardState))
|
||||||
return false;
|
return false;
|
||||||
if (params.getShardId() != shardState.getShardInstance().getShard().getInstance())
|
if (params.getShardId() != shardState.getShardInstance().getShard().getInstance())
|
||||||
return false;
|
return false;
|
||||||
|
@@ -3,7 +3,7 @@ package com.inteligr8.alfresco.asie.enterprise.rest;
|
|||||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.model.NodeParameterSet;
|
import com.inteligr8.alfresco.asie.rest.model.NodeParameterSet;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.node.delete")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.node.delete")
|
||||||
public class UnloadNodeWebScript extends AbstractUnregisterNodeWebScript<NodeParameterSet> {
|
public class UnloadNodeWebScript extends AbstractUnregisterNodeWebScript<NodeParameterSet> {
|
||||||
|
@@ -0,0 +1,404 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.enterprise.service;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.repo.index.shard.Floc;
|
||||||
|
import org.alfresco.repo.index.shard.Shard;
|
||||||
|
import org.alfresco.repo.index.shard.ShardInstance;
|
||||||
|
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||||
|
import org.alfresco.repo.index.shard.ShardRegistry;
|
||||||
|
import org.alfresco.repo.index.shard.ShardState;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.alfresco.util.collections.CollectionUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.asie.Constants;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ShardDiscoveryService implements com.inteligr8.alfresco.asie.spi.ShardDiscoveryService {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||||
|
private ShardRegistry shardRegistry;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShardSet findSetByCore(String core) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return null;
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
|
for (Entry<Shard, Set<ShardState>> flocShard : floc.getValue().entrySet()) {
|
||||||
|
for (ShardState shardState : flocShard.getValue()) {
|
||||||
|
ShardSet shardSet = ShardSet.from(floc.getKey(), shardState);
|
||||||
|
if (shardSet.getCore().equals(core))
|
||||||
|
return shardSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SolrHost findNode(String nodeHostname, int nodePort) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return null;
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
Map<String, InetAddress> resolvedAddresses = new HashMap<>();
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
|
for (Entry<Shard, Set<ShardState>> flocShard : floc.getValue().entrySet()) {
|
||||||
|
for (ShardState shardState : flocShard.getValue()) {
|
||||||
|
ShardInstance shardInstance = shardState.getShardInstance();
|
||||||
|
if (!nodeHostname.equalsIgnoreCase(shardInstance.getHostName())) {
|
||||||
|
if (!resolvedAddresses.containsKey(nodeHostname))
|
||||||
|
resolvedAddresses.put(nodeHostname, this.resolve(nodeHostname));
|
||||||
|
InetAddress nodeAddress = resolvedAddresses.get(nodeHostname);
|
||||||
|
this.logger.trace("Resolved: {} => {}", nodeHostname, nodeAddress);
|
||||||
|
if (nodeAddress == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!resolvedAddresses.containsKey(shardInstance.getHostName()))
|
||||||
|
resolvedAddresses.put(shardInstance.getHostName(), this.resolve(shardInstance.getHostName()));
|
||||||
|
InetAddress shardInstanceAddress = resolvedAddresses.get(shardInstance.getHostName());
|
||||||
|
this.logger.trace("Resolved: {} => {}", shardInstance.getHostName(), shardInstanceAddress);
|
||||||
|
if (!nodeAddress.equals(shardInstanceAddress))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodePort == shardInstance.getPort()) {
|
||||||
|
SolrHost node = SolrHost.from(shardInstance);
|
||||||
|
this.logger.debug("Found node: {}", node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<ShardSet, Map<Integer, ShardInstanceState>> findByNode(SolrHost node) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return Collections.emptyMap();
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
Map<ShardSet, Map<Integer, ShardInstanceState>> setShardStates = new HashMap<>();
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet())
|
||||||
|
setShardStates.putAll(this.findByNode(node, floc.getKey(), floc.getValue()));
|
||||||
|
|
||||||
|
return setShardStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<ShardSet, Map<Integer, ShardInstanceState>> findByNode(SolrHost node, Floc floc, Map<Shard, Set<ShardState>> shards) {
|
||||||
|
ShardSet shardSet = null;
|
||||||
|
Map<ShardSet, Map<Integer, ShardInstanceState>> setShardStates = new HashMap<>();
|
||||||
|
int shardStateCount = 0;
|
||||||
|
|
||||||
|
for (Entry<Shard, Set<ShardState>> flocShard : shards.entrySet()) {
|
||||||
|
for (ShardState shardState : flocShard.getValue()) {
|
||||||
|
if (shardSet == null)
|
||||||
|
shardSet = ShardSet.from(floc, shardState);
|
||||||
|
|
||||||
|
ShardInstance shardInstance = shardState.getShardInstance();
|
||||||
|
if (node.equals(SolrHost.from(shardInstance))) {
|
||||||
|
Map<Integer, ShardInstanceState> shardStates = setShardStates.get(shardSet);
|
||||||
|
if (shardStates == null)
|
||||||
|
setShardStates.put(shardSet, shardStates = new HashMap<>());
|
||||||
|
shardStates.put(flocShard.getKey().getInstance(), ShardInstanceState.from(shardState));
|
||||||
|
shardStateCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug("Found {} shard states for node: {}", shardStateCount, node);
|
||||||
|
return setShardStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ShardSet> findSetsByShardMethod(ShardMethodEnum... shardMethods) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return Collections.emptySet();
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
Set<ShardMethodEnum> shardMethodSet = CollectionUtils.asSet(shardMethods);
|
||||||
|
Set<ShardSet> shardSets = new HashSet<>();
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
|
if (shardMethodSet.contains(floc.getKey().getShardMethod())) {
|
||||||
|
ShardState shardState = this.extractAnyShardState(floc.getValue());
|
||||||
|
shardSets.add(ShardSet.from(floc.getKey(), shardState));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug("Found {} shard sets of methods: {}", flocs.size(), shardMethods);
|
||||||
|
return shardSets;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<SolrHost> findNodes(ShardSet shardSet) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return Collections.emptySet();
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
|
Set<SolrHost> nodes = this.findNodes(shardSet, null, floc.getKey(), floc.getValue());
|
||||||
|
if (nodes != null) {
|
||||||
|
this.logger.debug("Found {} nodes for set: {}", nodes.size(), shardSet);
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug("Found {} nodes for set: {}", 0, shardSet);
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<SolrHost> findNodesByShard(ShardSet shardSet, int shardId) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return Collections.emptySet();
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
|
Set<SolrHost> nodes = this.findNodes(shardSet, shardId, floc.getKey(), floc.getValue());
|
||||||
|
if (nodes != null) {
|
||||||
|
this.logger.debug("Found {} nodes for shard #{} in set: {}", nodes.size(), shardId, shardSet);
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug("Found {} nodes for shard #{} in set: {}", 0, shardId, shardSet);
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<SolrHost> findNodes(ShardSet shardSet, Integer shardId, Floc floc, Map<Shard, Set<ShardState>> shards) {
|
||||||
|
Set<SolrHost> nodes = new HashSet<>();
|
||||||
|
boolean checked = false;
|
||||||
|
|
||||||
|
for (Entry<Shard, Set<ShardState>> shard : shards.entrySet()) {
|
||||||
|
if (shardId == null || shardId.intValue() == shard.getKey().getInstance()) {
|
||||||
|
for (ShardState shardState : shard.getValue()) {
|
||||||
|
if (!checked && !shardSet.equals(ShardSet.from(floc, shardState)))
|
||||||
|
return null;
|
||||||
|
checked = true;
|
||||||
|
|
||||||
|
ShardInstance shardInstance = shardState.getShardInstance();
|
||||||
|
SolrHost node = SolrHost.from(shardInstance);
|
||||||
|
nodes.add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Integer, Pair<SolrHost, ShardInstanceState>> findLatestNodeStates(ShardSet shardSet) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return Collections.emptyMap();
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
|
Map<Integer, Pair<SolrHost, ShardInstanceState>> shardNodeStates = this.findLatestNodeStates(shardSet, floc.getKey(), floc.getValue());
|
||||||
|
if (shardNodeStates != null) {
|
||||||
|
this.logger.debug("Found {} shard node states for set: {}", shardNodeStates.size(), shardSet);
|
||||||
|
return shardNodeStates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug("Found {} shard node states for set: {}", 0, shardSet);
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Integer, Pair<SolrHost, ShardInstanceState>> findLatestNodeStates(ShardSet shardSet, Floc floc, Map<Shard, Set<ShardState>> shards) {
|
||||||
|
Map<Integer, Pair<SolrHost, ShardInstanceState>> shardNodeStates = new HashMap<>();
|
||||||
|
boolean checked = false;
|
||||||
|
|
||||||
|
com.inteligr8.alfresco.asie.spi.ShardDiscoveryService.ShardedNodeShardStateComparator comparator = new com.inteligr8.alfresco.asie.spi.ShardDiscoveryService.ShardedNodeShardStateComparator();
|
||||||
|
|
||||||
|
for (Entry<Shard, Set<ShardState>> shard : shards.entrySet()) {
|
||||||
|
int shardId = shard.getKey().getInstance();
|
||||||
|
for (ShardState shardState : shard.getValue()) {
|
||||||
|
if (!checked && !shardSet.equals(ShardSet.from(floc, shardState)))
|
||||||
|
return null;
|
||||||
|
checked = true;
|
||||||
|
|
||||||
|
ShardInstance shardInstance = shardState.getShardInstance();
|
||||||
|
SolrHost node = SolrHost.from(shardInstance);
|
||||||
|
ShardInstanceState nodeShardState = ShardInstanceState.from(shardState);
|
||||||
|
|
||||||
|
Pair<SolrHost, ShardInstanceState> pair = new Pair<>(node, nodeShardState);
|
||||||
|
if (comparator.compare(pair, shardNodeStates.get(shardId)) < 0)
|
||||||
|
shardNodeStates.put(shardId, pair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shardNodeStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Pair<SolrHost, ShardInstanceState>> findNodeStatesByShard(ShardSet shardSet, int shardId) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return Collections.emptyList();
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
|
List<Pair<SolrHost, ShardInstanceState>> nodeStates = this.findNodeStates(shardSet, shardId, floc.getKey(), floc.getValue());
|
||||||
|
if (nodeStates != null) {
|
||||||
|
this.logger.debug("Found {} node states for shard #{} in set: {}", nodeStates.size(), shardId, shardSet);
|
||||||
|
return nodeStates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug("Found {} node states for shard #{} in set: {}", 0, shardId, shardSet);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Pair<SolrHost, ShardInstanceState>> findNodeStates(ShardSet shardSet, Integer shardId, Floc floc, Map<Shard, Set<ShardState>> shards) {
|
||||||
|
List<Pair<SolrHost, ShardInstanceState>> nodeStates = new LinkedList<>();
|
||||||
|
boolean checked = false;
|
||||||
|
|
||||||
|
for (Entry<Shard, Set<ShardState>> shard : shards.entrySet()) {
|
||||||
|
if (shardId == null || shardId.intValue() == shard.getKey().getInstance()) {
|
||||||
|
for (ShardState shardState : shard.getValue()) {
|
||||||
|
if (!checked && !shardSet.equals(ShardSet.from(floc, shardState)))
|
||||||
|
return null;
|
||||||
|
checked = true;
|
||||||
|
|
||||||
|
ShardInstance shardInstance = shardState.getShardInstance();
|
||||||
|
SolrHost node = SolrHost.from(shardInstance);
|
||||||
|
ShardInstanceState nodeShardState = ShardInstanceState.from(shardState);
|
||||||
|
nodeStates.add(new Pair<>(node, nodeShardState));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Integer> findIdsByNode(ShardSet shardSet, SolrHost node) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return Collections.emptySet();
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
|
Set<Integer> shardIds = this.findIdsByNode(shardSet, node, floc.getKey(), floc.getValue());
|
||||||
|
if (shardIds != null) {
|
||||||
|
this.logger.debug("Found {} shards for node '{}' in set: {}", shardIds.size(), node, shardSet);
|
||||||
|
return shardIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug("Found {} node states for node '{}' in set: {}", 0, node, shardSet);
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<Integer> findIdsByNode(ShardSet shardSet, SolrHost node, Floc floc, Map<Shard, Set<ShardState>> shards) {
|
||||||
|
Set<Integer> shardIds = new HashSet<>();
|
||||||
|
boolean checked = false;
|
||||||
|
|
||||||
|
for (Entry<Shard, Set<ShardState>> shard : shards.entrySet()) {
|
||||||
|
for (ShardState shardState : shard.getValue()) {
|
||||||
|
if (!checked && !shardSet.equals(ShardSet.from(floc, shardState)))
|
||||||
|
return null;
|
||||||
|
checked = true;
|
||||||
|
|
||||||
|
ShardInstance shardInstance = shardState.getShardInstance();
|
||||||
|
if (node.equals(SolrHost.from(shardInstance)))
|
||||||
|
shardIds.add(shard.getKey().getInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shardIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Integer, ShardInstanceState> findStatesByNode(ShardSet shardSet, SolrHost node) {
|
||||||
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
|
if (flocs.isEmpty())
|
||||||
|
return Collections.emptyMap();
|
||||||
|
this.logger.trace("Found {} shard sets", flocs.size());
|
||||||
|
|
||||||
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
|
Map<Integer, ShardInstanceState> shardStates = this.findStatesByNode(shardSet, node, floc.getKey(), floc.getValue());
|
||||||
|
if (shardStates != null) {
|
||||||
|
this.logger.debug("Found {} shard states for node '{}' in set: {}", shardStates.size(), node, shardSet);
|
||||||
|
return shardStates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug("Found {} shard states for node '{}' in set: {}", 0, node, shardSet);
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Integer, ShardInstanceState> findStatesByNode(ShardSet shardSet, SolrHost node, Floc floc, Map<Shard, Set<ShardState>> shards) {
|
||||||
|
Map<Integer, ShardInstanceState> shardStates = new HashMap<>();
|
||||||
|
boolean checked = false;
|
||||||
|
|
||||||
|
for (Entry<Shard, Set<ShardState>> shard : shards.entrySet()) {
|
||||||
|
for (ShardState shardState : shard.getValue()) {
|
||||||
|
if (!checked && !shardSet.equals(ShardSet.from(floc, shardState)))
|
||||||
|
return null;
|
||||||
|
checked = true;
|
||||||
|
|
||||||
|
ShardInstance shardInstance = shardState.getShardInstance();
|
||||||
|
if (node.equals(SolrHost.from(shardInstance)))
|
||||||
|
shardStates.put(shard.getKey().getInstance(), ShardInstanceState.from(shardState));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shardStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShardState extractAnyShardState(Map<Shard, Set<ShardState>> shards) {
|
||||||
|
if (shards.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (Set<ShardState> shardStates : shards.values())
|
||||||
|
for (ShardState shardState : shardStates)
|
||||||
|
return shardState;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InetAddress resolve(String hostname) {
|
||||||
|
try {
|
||||||
|
return InetAddress.getByName(hostname);
|
||||||
|
} catch (UnknownHostException uhe) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -35,6 +35,7 @@ public class ShardStateService implements com.inteligr8.alfresco.asie.spi.ShardS
|
|||||||
@Qualifier(Constants.BEAN_SHARD_GUID_CACHE)
|
@Qualifier(Constants.BEAN_SHARD_GUID_CACHE)
|
||||||
private SimpleCache<ShardInstance, String> shardToGuidCache;
|
private SimpleCache<ShardInstance, String> shardToGuidCache;
|
||||||
|
|
||||||
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
this.logger.info("Removing all nodes/shards from the shard registry");
|
this.logger.info("Removing all nodes/shards from the shard registry");
|
||||||
|
|
||||||
|
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<groupId>com.inteligr8.alfresco</groupId>
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
<artifactId>asie-platform-module-parent</artifactId>
|
<artifactId>asie-platform-module-parent</artifactId>
|
||||||
<version>1.1-SNAPSHOT</version>
|
<version>1.2-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<name>ASIE Platform Module Parent</name>
|
<name>ASIE Platform Module Parent</name>
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.inteligr8.alfresco</groupId>
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
<artifactId>asie-platform-module-parent</artifactId>
|
<artifactId>asie-platform-module-parent</artifactId>
|
||||||
<version>1.1-SNAPSHOT</version>
|
<version>1.2-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@@ -6,20 +6,15 @@ public interface Constants {
|
|||||||
|
|
||||||
static final String QUALIFIER_ASIE = "asie";
|
static final String QUALIFIER_ASIE = "asie";
|
||||||
|
|
||||||
// OOTB
|
// defined OOTB
|
||||||
static final String BEAN_SHARD_STATE_CACHE = "shardStateCache";
|
static final String BEAN_SHARD_STATE_CACHE = "shardStateCache";
|
||||||
static final String BEAN_SHARD_GUID_CACHE = "shardToGuidCache";
|
static final String BEAN_SHARD_GUID_CACHE = "shardToGuidCache";
|
||||||
|
|
||||||
static final String BEAN_OFFILINE_SHARD_STATE_CACHE = "offlineShardStateCache";
|
static final String BEAN_SHARD_REGISTRY = "asie.ShardRegistry";
|
||||||
static final String BEAN_CORE_EXPLICIT_CACHE = "coreExplicitIdCache";
|
|
||||||
static final String BEAN_OBJECT_MAPPER = "asie.ObjectMapper";
|
static final String BEAN_OBJECT_MAPPER = "asie.ObjectMapper";
|
||||||
static final String BEAN_ATTRIBUTE_SERVICE = "asie.AttributeService";
|
static final String BEAN_ATTRIBUTE_SERVICE = "asie.AttributeService";
|
||||||
static final String BEAN_SHARD_REGISTRY = "asie.ShardRegistry";
|
|
||||||
|
|
||||||
static final String ATTR_ASIE = "inteligr8.asie";
|
static final String ATTR_ASIE = "inteligr8.asie";
|
||||||
static final String ATTR_ASIE_NODE_SHARD = "inteligr8.asie.nodeShard";
|
|
||||||
static final String ATTR_STATE = "state";
|
|
||||||
static final String ATTR_ONLINE = "online";
|
|
||||||
static final String ATTR_UNLOADED = "unloadedNode.cores";
|
static final String ATTR_UNLOADED = "unloadedNode.cores";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,48 @@
|
|||||||
|
package com.inteligr8.alfresco.asie;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class SimpleCaster {
|
||||||
|
|
||||||
|
public static <T> T transform(String str, Class<T> returnType) {
|
||||||
|
if (str == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (returnType.isAssignableFrom(String.class)) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T t = (T) str;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Constructor<T> constructor = returnType.getConstructor(String.class);
|
||||||
|
return constructor.newInstance(str);
|
||||||
|
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
||||||
|
// suppress
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String staticMethod : Arrays.asList("from", "valueOf")) {
|
||||||
|
try {
|
||||||
|
return invoke(returnType, staticMethod, str);
|
||||||
|
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
// suppress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T invoke(Class<T> returnType, String staticMethodName, Object... arguments) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||||
|
Method method = returnType.getDeclaredMethod(staticMethodName, String.class);
|
||||||
|
if (!returnType.isAssignableFrom(method.getReturnType()))
|
||||||
|
throw new NoSuchMethodException();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T t = (T) method.invoke(null, arguments);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,56 +0,0 @@
|
|||||||
package com.inteligr8.alfresco.asie.model;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
|
||||||
|
|
||||||
public class Node implements Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -8834744746109388928L;
|
|
||||||
|
|
||||||
private final String id;
|
|
||||||
private final ShardInstance shardNode;
|
|
||||||
|
|
||||||
public Node(ShardInstance shardNode) {
|
|
||||||
this.shardNode = shardNode;
|
|
||||||
this.id = this.getHostname() + ":" + this.getPort() + this.getPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHostname() {
|
|
||||||
return this.shardNode.getHostName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPort() {
|
|
||||||
return this.shardNode.getPort();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPath() {
|
|
||||||
// baseUrl is to the shard; we want to the node, so exclude the core
|
|
||||||
int lastSlash = this.shardNode.getBaseUrl().lastIndexOf('/');
|
|
||||||
return this.shardNode.getBaseUrl().substring(0, lastSlash);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (!(obj instanceof Node))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Node node = (Node) obj;
|
|
||||||
return this.id.equals(node.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.id.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,5 +0,0 @@
|
|||||||
package com.inteligr8.alfresco.asie.model;
|
|
||||||
|
|
||||||
public interface RequestParameterSet {
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,68 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.alfresco.repo.index.shard.Floc;
|
||||||
|
|
||||||
|
public class Shard implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 5683743181748541736L;
|
||||||
|
|
||||||
|
public static Shard from(ShardSet shardSet, int shardId) {
|
||||||
|
return new Shard(shardSet, shardId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Shard from(String spec) {
|
||||||
|
return new Shard(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String spec;
|
||||||
|
|
||||||
|
protected Shard(ShardSet shardSet, int shardId) {
|
||||||
|
this.spec = shardSet.getCore() + "~" + shardId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Shard(String spec) {
|
||||||
|
this.spec = spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public org.alfresco.repo.index.shard.Shard toAlfrescoModel(Floc floc) {
|
||||||
|
org.alfresco.repo.index.shard.Shard shard = new org.alfresco.repo.index.shard.Shard();
|
||||||
|
shard.setFloc(floc);
|
||||||
|
shard.setInstance(this.extractShardId());
|
||||||
|
return shard;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpec() {
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String extractShardSetCore() {
|
||||||
|
int pos = this.spec.indexOf('~');
|
||||||
|
return this.spec.substring(0, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int extractShardId() {
|
||||||
|
int pos = this.spec.indexOf('~');
|
||||||
|
return Integer.parseInt(this.spec.substring(pos+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof Shard))
|
||||||
|
return false;
|
||||||
|
Shard shard = (Shard) obj;
|
||||||
|
return this.spec.equals(shard.spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.spec.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,64 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class ShardInstance implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 7455521296197234581L;
|
||||||
|
|
||||||
|
public static ShardInstance from(Shard shard, SolrHost node) {
|
||||||
|
return new ShardInstance(shard, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String spec;
|
||||||
|
|
||||||
|
protected ShardInstance(Shard shard, SolrHost node) {
|
||||||
|
this.spec = shard.getSpec() + "~" + node.getSpec();
|
||||||
|
}
|
||||||
|
|
||||||
|
public org.alfresco.repo.index.shard.ShardInstance toAlfrescoModel(org.alfresco.repo.index.shard.Shard shard) {
|
||||||
|
SolrHost node = this.extractNode();
|
||||||
|
|
||||||
|
String core = shard.getFloc().getPropertyBag().get("coreName");
|
||||||
|
|
||||||
|
org.alfresco.repo.index.shard.ShardInstance shardInstance = new org.alfresco.repo.index.shard.ShardInstance();
|
||||||
|
shardInstance.setHostName(node.getHostname());
|
||||||
|
shardInstance.setPort(node.getPort());
|
||||||
|
shardInstance.setBaseUrl(node.getPath() + "/" + core + "-" + shard.getInstance());
|
||||||
|
shardInstance.setShard(shard);
|
||||||
|
return shardInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpec() {
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shard extractShard() {
|
||||||
|
int pos = this.spec.indexOf('~');
|
||||||
|
return Shard.from(this.spec.substring(0, pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SolrHost extractNode() {
|
||||||
|
int pos = this.spec.indexOf('~');
|
||||||
|
return SolrHost.from(this.spec.substring(pos+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof ShardInstance))
|
||||||
|
return false;
|
||||||
|
ShardInstance shard = (ShardInstance) obj;
|
||||||
|
return this.spec.equals(shard.spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.spec.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,102 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.alfresco.repo.index.shard.ShardInstance;
|
||||||
|
import org.alfresco.repo.index.shard.ShardState;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
|
|
||||||
|
public class ShardInstanceState implements Serializable, Comparable<ShardInstanceState> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 2893797002689889478L;
|
||||||
|
|
||||||
|
public static ShardInstanceState from(ShardState shardState) {
|
||||||
|
return new ShardInstanceState(shardState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final OffsetDateTime lastUpdated;
|
||||||
|
private final long lastIndexedChangeSetId;
|
||||||
|
private final OffsetDateTime lastIndexedChangeSetTime;
|
||||||
|
private final long lastIndexedTxId;
|
||||||
|
private final OffsetDateTime lastIndexedTxTime;
|
||||||
|
private transient Integer hash = null;
|
||||||
|
|
||||||
|
private ShardInstanceState(ShardState shardState) {
|
||||||
|
this.lastUpdated = Instant.ofEpochMilli(shardState.getLastUpdated()).atOffset(ZoneOffset.UTC);
|
||||||
|
this.lastIndexedChangeSetId = shardState.getLastIndexedChangeSetId();
|
||||||
|
this.lastIndexedChangeSetTime = Instant.ofEpochMilli(shardState.getLastIndexedChangeSetCommitTime()).atOffset(ZoneOffset.UTC);
|
||||||
|
this.lastIndexedTxId = shardState.getLastIndexedTxId();
|
||||||
|
this.lastIndexedTxTime = Instant.ofEpochMilli(shardState.getLastIndexedTxCommitTime()).atOffset(ZoneOffset.UTC);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShardState toAlfrescoModel(ShardInstance shardInstance) {
|
||||||
|
ShardState state = new ShardState();
|
||||||
|
state.setLastIndexedChangeSetCommitTime(this.lastIndexedChangeSetTime.toInstant().toEpochMilli());
|
||||||
|
state.setLastIndexedChangeSetId(this.lastIndexedChangeSetId);
|
||||||
|
state.setLastIndexedTxCommitTime(this.lastIndexedTxTime.toInstant().toEpochMilli());
|
||||||
|
state.setLastIndexedTxId(this.lastIndexedTxId);
|
||||||
|
state.setLastUpdated(this.lastUpdated.toInstant().toEpochMilli());
|
||||||
|
state.setShardInstance(shardInstance);
|
||||||
|
|
||||||
|
for (Entry<String, String> prop : shardInstance.getShard().getFloc().getPropertyBag().entrySet())
|
||||||
|
if (prop.getKey().startsWith("shard."))
|
||||||
|
state.getPropertyBag().put(prop.getKey(), prop.getValue());
|
||||||
|
String core = shardInstance.getShard().getFloc().getPropertyBag().get("coreName");
|
||||||
|
if (core != null)
|
||||||
|
state.getPropertyBag().put("coreName", core + "-" + shardInstance.getShard().getInstance());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getLastUpdated() {
|
||||||
|
return lastUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastIndexedChangeSetId() {
|
||||||
|
return lastIndexedChangeSetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getLastIndexedChangeSetTime() {
|
||||||
|
return lastIndexedChangeSetTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastIndexedTxId() {
|
||||||
|
return lastIndexedTxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getLastIndexedTxTime() {
|
||||||
|
return lastIndexedTxTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(ShardInstanceState o) {
|
||||||
|
return -this.lastUpdated.compareTo(o.lastUpdated);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof ShardInstanceState))
|
||||||
|
return false;
|
||||||
|
ShardInstanceState snss = (ShardInstanceState) obj;
|
||||||
|
|
||||||
|
return this.lastIndexedChangeSetId == snss.lastIndexedChangeSetId &&
|
||||||
|
this.lastIndexedTxId == snss.lastIndexedTxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
if (this.hash == null) {
|
||||||
|
this.hash = new HashCodeBuilder()
|
||||||
|
.append(this.lastIndexedTxId)
|
||||||
|
.append(this.lastIndexedChangeSetId)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.hash.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,56 +1,194 @@
|
|||||||
package com.inteligr8.alfresco.asie.model;
|
package com.inteligr8.alfresco.asie.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Set;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.Floc;
|
import org.alfresco.repo.index.shard.Floc;
|
||||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
import org.alfresco.repo.index.shard.ShardState;
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.util.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.collections4.map.CompositeMap;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.asie.SimpleCaster;
|
||||||
|
|
||||||
public class ShardSet implements Serializable {
|
public class ShardSet implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = -8891094367429601316L;
|
private static final long serialVersionUID = -8891094367429601316L;
|
||||||
|
private static final String DEFAULT_SOLR_TEMPLATE = "rerank";
|
||||||
|
|
||||||
/**
|
public static ShardSet from(Floc floc, ShardState anyShardState) {
|
||||||
* Examples:
|
return new ShardSet(floc, anyShardState);
|
||||||
*
|
|
||||||
* MOD_ACL_ID
|
|
||||||
* ACL_ID
|
|
||||||
* DB_ID
|
|
||||||
* DB_ID_RANGE;range:0-20000
|
|
||||||
* DATE;key:cm:created
|
|
||||||
* DATE;key:cm:created;date.grouping:3
|
|
||||||
* PROPERTY;key:cm:created;regex:^d{4}
|
|
||||||
*/
|
|
||||||
private static final Pattern shardSetPattern = Pattern.compile("([A-Z]+)(;fulltext)?(;([a-z]+):([^;]+))?(;([a-z]+):([^;]+))?");
|
|
||||||
|
|
||||||
private final ShardMethodEnum method;
|
|
||||||
private final boolean hasContent;
|
|
||||||
private final Map<String, String> config;
|
|
||||||
private transient Integer hash;
|
|
||||||
|
|
||||||
public ShardSet(Floc floc, ShardState anyShardNode) {
|
|
||||||
this.method = floc.getShardMethod();
|
|
||||||
this.hasContent = floc.hasContent();
|
|
||||||
this.config = (floc.getPropertyBag().isEmpty() && anyShardNode != null) ? anyShardNode.getPropertyBag() : floc.getPropertyBag();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShardSet(String shardSetSpec) {
|
public static ShardSet from(String coreName, String spec) {
|
||||||
Matcher matcher = shardSetPattern.matcher(shardSetSpec);
|
return new ShardSet(coreName, spec);
|
||||||
if (!matcher.find())
|
}
|
||||||
throw new IllegalArgumentException("The shard set '" + shardSetSpec + "' is not properly formatted");
|
|
||||||
|
|
||||||
this.method = ShardMethodEnum.valueOf(matcher.group(1));
|
private final String core;
|
||||||
this.hasContent = ";fulltext".equals(matcher.group(2));
|
private final ShardMethodEnum method;
|
||||||
this.config = new HashMap<>();
|
private final boolean hasContent;
|
||||||
for (int g = 3; g < matcher.groupCount(); g += 3)
|
private final String template;
|
||||||
if (matcher.group(g) != null)
|
private final Set<StoreRef> storeRefs;
|
||||||
this.config.put("shard." + matcher.group(g+1), matcher.group(g+2));
|
private final Short shards;
|
||||||
|
private final Pair<Long, Long> range;
|
||||||
|
private final Byte dateGrouping;
|
||||||
|
private final String prefixedProperty;
|
||||||
|
private final Pattern regex;
|
||||||
|
private transient String spec;
|
||||||
|
|
||||||
|
private ShardSet(Floc floc, ShardState anyShardNode) {
|
||||||
|
String shardCoreName = anyShardNode.getPropertyBag().get("coreName");
|
||||||
|
int lastDash = shardCoreName.lastIndexOf('-');
|
||||||
|
this.core = shardCoreName.substring(0, lastDash);
|
||||||
|
|
||||||
|
this.method = floc.getShardMethod();
|
||||||
|
this.hasContent = floc.hasContent();
|
||||||
|
this.template = floc.getTemplate();
|
||||||
|
this.storeRefs = floc.getStoreRefs();
|
||||||
|
CompositeMap<String, String> propbag = new CompositeMap<>(floc.getPropertyBag(), anyShardNode.getPropertyBag());
|
||||||
|
|
||||||
|
Short shards = null;
|
||||||
|
Pair<Long, Long> range = null;
|
||||||
|
Byte dateGrouping = null;
|
||||||
|
String prefixedProperty = null;
|
||||||
|
String regex = null;
|
||||||
|
|
||||||
|
switch (this.method) {
|
||||||
|
case DB_ID_RANGE:
|
||||||
|
range = this.strToRange(propbag.get("shard.range"));
|
||||||
|
break;
|
||||||
|
case DATE:
|
||||||
|
dateGrouping = SimpleCaster.transform(propbag.get("shard.date.grouping"), Byte.class);
|
||||||
|
case PROPERTY:
|
||||||
|
case EXPLICIT_ID:
|
||||||
|
prefixedProperty = StringUtils.trimToNull(propbag.get("shard.key"));
|
||||||
|
regex = StringUtils.trimToNull(propbag.get("shard.regex"));
|
||||||
|
default:
|
||||||
|
shards = (short) floc.getNumberOfShards();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.range = range;
|
||||||
|
this.shards = shards;
|
||||||
|
this.dateGrouping = dateGrouping;
|
||||||
|
this.prefixedProperty = prefixedProperty;
|
||||||
|
this.regex = regex == null ? null : Pattern.compile(regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Floc toAlfrescoModel() {
|
||||||
|
Floc floc = new Floc();
|
||||||
|
floc.setShardMethod(this.method);
|
||||||
|
floc.setHasContent(this.hasContent);
|
||||||
|
floc.setTemplate(this.template);
|
||||||
|
floc.setStoreRefs(new HashSet<>(this.storeRefs));
|
||||||
|
floc.getPropertyBag().put("coreName", this.core);
|
||||||
|
|
||||||
|
switch (this.method) {
|
||||||
|
case DB_ID_RANGE:
|
||||||
|
floc.getPropertyBag().put("shard.range", this.range.getLeft() + "-" + this.range.getRight());
|
||||||
|
break;
|
||||||
|
case DATE:
|
||||||
|
if (this.dateGrouping != null)
|
||||||
|
floc.getPropertyBag().put("shard.date.grouping", this.dateGrouping.toString());
|
||||||
|
case PROPERTY:
|
||||||
|
case EXPLICIT_ID:
|
||||||
|
floc.getPropertyBag().put("shard.key", this.prefixedProperty);
|
||||||
|
if (this.regex != null)
|
||||||
|
floc.getPropertyBag().put("shard.regex", this.regex.pattern());
|
||||||
|
default:
|
||||||
|
if (this.shards != null)
|
||||||
|
floc.setNumberOfShards(this.shards.intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return floc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShardSet(String coreName, String shardSetSpec) {
|
||||||
|
String[] parts = shardSetSpec.split("[;|_]");
|
||||||
|
if (parts.length == 0)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
this.core = coreName;
|
||||||
|
this.method = ShardMethodEnum.valueOf(parts[0].toUpperCase());
|
||||||
|
|
||||||
|
boolean hasContent = false;
|
||||||
|
String template = DEFAULT_SOLR_TEMPLATE;
|
||||||
|
StoreRef storeRef = StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||||
|
Pair<Long, Long> range = null;
|
||||||
|
Short shards = null;
|
||||||
|
Byte dateGrouping = null;
|
||||||
|
String prefixedProperty = null;
|
||||||
|
String regex = null;
|
||||||
|
|
||||||
|
for (int i = 1; i < parts.length; i++) {
|
||||||
|
int colon = parts[i].indexOf(":");
|
||||||
|
String fieldName = colon < 0 ? parts[i] : parts[i].substring(0, colon);
|
||||||
|
String fieldValue = colon < 0 ? null : parts[i].substring(colon+1);
|
||||||
|
|
||||||
|
switch (fieldName) {
|
||||||
|
case "txt":
|
||||||
|
case "text":
|
||||||
|
case "fulltext":
|
||||||
|
case "content":
|
||||||
|
case "hasContent":
|
||||||
|
case "hasText":
|
||||||
|
hasContent = true;
|
||||||
|
break;
|
||||||
|
case "t":
|
||||||
|
case "template":
|
||||||
|
template = fieldValue;
|
||||||
|
break;
|
||||||
|
case "sref":
|
||||||
|
case "storeRef":
|
||||||
|
storeRef = new StoreRef(fieldValue);
|
||||||
|
break;
|
||||||
|
case "s":
|
||||||
|
case "shards":
|
||||||
|
shards = SimpleCaster.transform(fieldValue, Short.class);
|
||||||
|
break;
|
||||||
|
case "range":
|
||||||
|
range = this.strToRange(fieldValue);
|
||||||
|
break;
|
||||||
|
case "date.grouping":
|
||||||
|
dateGrouping = SimpleCaster.transform(fieldValue, Byte.class);
|
||||||
|
break;
|
||||||
|
case "k":
|
||||||
|
case "key":
|
||||||
|
prefixedProperty = fieldValue;
|
||||||
|
break;
|
||||||
|
case "regex":
|
||||||
|
regex = fieldValue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasContent = hasContent;
|
||||||
|
this.template = template;
|
||||||
|
this.storeRefs = CollectionUtils.asSet(storeRef);
|
||||||
|
this.shards = shards;
|
||||||
|
this.range = range;
|
||||||
|
this.dateGrouping = dateGrouping;
|
||||||
|
this.prefixedProperty = prefixedProperty;
|
||||||
|
this.regex = regex == null ? null : Pattern.compile(regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Pair<Long, Long> strToRange(String str) {
|
||||||
|
str = StringUtils.trimToNull(str);
|
||||||
|
if (str == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
String[] rangeValues = str.split("-");
|
||||||
|
return Pair.of(Long.valueOf(rangeValues[0]), Long.valueOf(rangeValues[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCore() {
|
||||||
|
return core;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShardMethodEnum getMethod() {
|
public ShardMethodEnum getMethod() {
|
||||||
@@ -61,35 +199,70 @@ public class ShardSet implements Serializable {
|
|||||||
return hasContent;
|
return hasContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTemplate() {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<StoreRef> getStoreRefs() {
|
||||||
|
return storeRefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Short getShards() {
|
||||||
|
return shards;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<Long, Long> getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Byte getDateGrouping() {
|
||||||
|
return dateGrouping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefixedProperty() {
|
||||||
|
return prefixedProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pattern getRegex() {
|
||||||
|
return regex;
|
||||||
|
}
|
||||||
|
|
||||||
public String toSpec() {
|
public String toSpec() {
|
||||||
|
if (this.spec == null) {
|
||||||
StringBuilder spec = new StringBuilder(this.method.toString());
|
StringBuilder spec = new StringBuilder(this.method.toString());
|
||||||
if (this.hasContent)
|
if (this.hasContent)
|
||||||
spec.append(";fulltext");
|
spec.append(";txt");
|
||||||
for (Entry<String, String> c : this.config.entrySet()) {
|
spec.append(";t:").append(this.template);
|
||||||
if (!c.getKey().startsWith("shard."))
|
spec.append(";sref:").append(StringUtils.join(this.storeRefs, ','));
|
||||||
continue;
|
if (this.shards != null)
|
||||||
spec.append(';').append(c.getKey().substring(6)).append(':').append(c.getValue());
|
spec.append(";s:").append(this.shards);
|
||||||
}
|
if (this.range != null)
|
||||||
return spec.toString();
|
spec.append(";range:").append(this.range.getLeft()).append('-').append(this.range.getRight());
|
||||||
|
if (this.dateGrouping != null)
|
||||||
|
spec.append(";date.grouping:").append(this.dateGrouping);
|
||||||
|
if (this.prefixedProperty != null)
|
||||||
|
spec.append(";k:").append(this.prefixedProperty);
|
||||||
|
if (this.regex != null)
|
||||||
|
spec.append(";regex:").append(this.regex);
|
||||||
|
this.spec = spec.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getConfig() {
|
return spec;
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFor(ShardState shardState) {
|
public boolean contains(ShardState shardState) {
|
||||||
return this.method.equals(shardState.getShardInstance().getShard().getFloc().getShardMethod()) &&
|
Floc floc = shardState.getShardInstance().getShard().getFloc();
|
||||||
this.hasContent == shardState.getShardInstance().getShard().getFloc().hasContent() &&
|
CompositeMap<String, String> propbag = new CompositeMap<>(shardState.getPropertyBag(), floc.getPropertyBag());
|
||||||
this.isConfigurationFor(shardState.getPropertyBag());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConfigurationFor(Map<String, String> propertyBag) {
|
return this.method.equals(floc.getShardMethod()) &&
|
||||||
for (Entry<String, String> config : this.config.entrySet()) {
|
this.hasContent == floc.hasContent() &&
|
||||||
if (config.getValue() == null || !config.getValue().equals(propertyBag.get(config.getKey())))
|
StringUtils.equals(this.template, floc.getTemplate()) &&
|
||||||
return false;
|
this.storeRefs.equals(floc.getStoreRefs()) &&
|
||||||
}
|
this.equals(this.shards, floc.getNumberOfShards()) &&
|
||||||
|
this.equals(this.range, this.strToRange(propbag.get("shard.range"))) &&
|
||||||
return true;
|
this.equals(this.dateGrouping, propbag.get("shard.date.grouping")) &&
|
||||||
|
StringUtils.equals(this.prefixedProperty, propbag.get("shard.key")) &&
|
||||||
|
this.equals(this.regex, propbag.get("shard.regex"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -98,21 +271,34 @@ public class ShardSet implements Serializable {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
ShardSet shardSet = (ShardSet) obj;
|
ShardSet shardSet = (ShardSet) obj;
|
||||||
return this.method.equals(shardSet.method) && this.config.equals(shardSet.config);
|
return this.core.equals(shardSet.core);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> boolean equals(Pattern p1, String s2) {
|
||||||
|
s2 = StringUtils.trimToNull(s2);
|
||||||
|
if (p1 == null) {
|
||||||
|
return s2 == null;
|
||||||
|
} else {
|
||||||
|
return p1.pattern().equals(s2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> boolean equals(T t1, T t2) {
|
||||||
|
if (t1 == null) {
|
||||||
|
return t2 == null;
|
||||||
|
} else {
|
||||||
|
return t1.equals(t2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
if (this.hash == null) {
|
return this.core.hashCode();
|
||||||
this.hash = new HashCodeBuilder().append(this.method).append(this.hasContent).append(this.config).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.toSpec();
|
return this.core;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,92 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.alfresco.repo.index.shard.ShardInstance;
|
||||||
|
|
||||||
|
public class SolrHost implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -8834744746109388928L;
|
||||||
|
private static final Pattern PATTERN = Pattern.compile("([^:]+):([0-9]+)([^0-9]?.*)");
|
||||||
|
|
||||||
|
public static SolrHost from(ShardInstance shardNode) {
|
||||||
|
return new SolrHost(shardNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SolrHost from(String spec) {
|
||||||
|
return new SolrHost(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String spec;
|
||||||
|
private final String hostname;
|
||||||
|
private final int port;
|
||||||
|
private final String path;
|
||||||
|
|
||||||
|
protected SolrHost(ShardInstance shardNode) {
|
||||||
|
this.hostname = shardNode.getHostName();
|
||||||
|
this.port = shardNode.getPort();
|
||||||
|
|
||||||
|
// baseUrl is to the shard; we want to the node, so exclude the core
|
||||||
|
int lastSlash = shardNode.getBaseUrl().lastIndexOf('/');
|
||||||
|
this.path = shardNode.getBaseUrl().substring(0, lastSlash);
|
||||||
|
|
||||||
|
this.spec = this.hostname + ":" + this.port + this.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SolrHost(String spec) {
|
||||||
|
this.spec = spec;
|
||||||
|
|
||||||
|
Matcher matcher = PATTERN.matcher(spec);
|
||||||
|
this.hostname = matcher.group(1);
|
||||||
|
this.port = Integer.parseInt(matcher.group(2));
|
||||||
|
this.path = matcher.group(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpec() {
|
||||||
|
return this.spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostname() {
|
||||||
|
return this.hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return this.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return this.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL toUrl(String protocol) {
|
||||||
|
try {
|
||||||
|
return new URL(protocol + "://" + this.hostname + ':' + this.port + this.path);
|
||||||
|
} catch (MalformedURLException mue) {
|
||||||
|
throw new IllegalArgumentException(mue.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof SolrHost))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SolrHost shardNode = (SolrHost) obj;
|
||||||
|
return this.spec.equals(shardNode.spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.spec.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,9 +1,8 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -12,7 +11,10 @@ import org.springframework.extensions.webscripts.WebScriptRequest;
|
|||||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.service.ShardDiscoveryService;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
|
import com.inteligr8.alfresco.asie.spi.ShardDiscoveryService;
|
||||||
|
|
||||||
public abstract class AbstractAsieNodeWebScript extends AbstractAsieShardableWebScript {
|
public abstract class AbstractAsieNodeWebScript extends AbstractAsieShardableWebScript {
|
||||||
|
|
||||||
@@ -37,15 +39,16 @@ public abstract class AbstractAsieNodeWebScript extends AbstractAsieShardableWeb
|
|||||||
protected void execute(WebScriptRequest req, WebScriptResponse res, String nodeHostname, int nodePort) throws IOException {
|
protected void execute(WebScriptRequest req, WebScriptResponse res, String nodeHostname, int nodePort) throws IOException {
|
||||||
this.logger.trace("execute({}, {})", nodeHostname, nodePort);
|
this.logger.trace("execute({}, {})", nodeHostname, nodePort);
|
||||||
|
|
||||||
Set<ShardState> shardsOnNode = this.sds.findByNode(nodeHostname, nodePort);
|
SolrHost node = this.sds.findNode(nodeHostname, nodePort);
|
||||||
|
Map<ShardSet, Map<Integer, ShardInstanceState>> shardsOnNode = this.sds.findByNode(node);
|
||||||
if (shardsOnNode == null || shardsOnNode.isEmpty())
|
if (shardsOnNode == null || shardsOnNode.isEmpty())
|
||||||
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE node could not be found");
|
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE node could not be found");
|
||||||
|
|
||||||
this.execute(req, res, shardsOnNode);
|
this.execute(req, res, node, shardsOnNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void execute(WebScriptRequest req, WebScriptResponse res, Set<ShardState> registeredNodeShards) throws IOException {
|
protected void execute(WebScriptRequest req, WebScriptResponse res, SolrHost node, Map<ShardSet, Map<Integer, ShardInstanceState>> shardSetShardStates) throws IOException {
|
||||||
this.logger.trace("execute({})", registeredNodeShards.size());
|
this.logger.trace("execute({})", shardSetShardStates.size());
|
||||||
// made to be optionally overridden
|
// made to be optionally overridden
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
import org.alfresco.util.Pair;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -13,7 +13,9 @@ import org.springframework.extensions.webscripts.WebScriptResponse;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.model.ShardSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
import com.inteligr8.alfresco.asie.service.ShardDiscoveryService;
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
|
import com.inteligr8.alfresco.asie.spi.ShardDiscoveryService;
|
||||||
|
|
||||||
public abstract class AbstractAsieShardWebScript extends AbstractAsieShardableWebScript {
|
public abstract class AbstractAsieShardWebScript extends AbstractAsieShardableWebScript {
|
||||||
|
|
||||||
@@ -26,21 +28,24 @@ public abstract class AbstractAsieShardWebScript extends AbstractAsieShardableWe
|
|||||||
public void executeAuthorized(WebScriptRequest req, WebScriptResponse res) throws IOException {
|
public void executeAuthorized(WebScriptRequest req, WebScriptResponse res) throws IOException {
|
||||||
this.logger.trace("execute()");
|
this.logger.trace("execute()");
|
||||||
|
|
||||||
ShardSet shardSet = this.getRequiredPathParameter(req, "shardSet", ShardSet.class);
|
String coreName = this.getRequiredPathParameter(req, "shardCore");
|
||||||
this.logger.debug("Parsed shard set: {}", shardSet);
|
|
||||||
int shardId = this.getRequiredPathParameter(req, "shardId", Integer.class);
|
int shardId = this.getRequiredPathParameter(req, "shardId", Integer.class);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Set<ShardState> registeredShardNodes = this.sds.findByShard(shardSet, shardId);
|
ShardSet shardSet = this.sds.findSetByCore(coreName);
|
||||||
if (registeredShardNodes == null || registeredShardNodes.isEmpty())
|
if (shardSet == null)
|
||||||
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard set or shard could not be found");
|
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard set could not be found");
|
||||||
|
|
||||||
this.execute(req, res, registeredShardNodes);
|
List<Pair<SolrHost, ShardInstanceState>> nodeShardStates = this.sds.findNodeStatesByShard(shardSet, shardId);
|
||||||
|
if (nodeShardStates == null || nodeShardStates.isEmpty())
|
||||||
|
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard could not be found");
|
||||||
|
|
||||||
|
this.execute(req, res, shardId, shardSet, nodeShardStates);
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), iae.getMessage());
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), iae.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void execute(WebScriptRequest req, WebScriptResponse res, Set<ShardState> registeredShardNodes) throws IOException;
|
protected abstract void execute(WebScriptRequest req, WebScriptResponse res, int shardId, ShardSet shardSet, List<Pair<SolrHost, ShardInstanceState>> nodeShardStates) throws IOException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -57,7 +57,7 @@ public abstract class AbstractAsieShardableWebScript extends AbstractAsieWebScri
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
SolrShardHashSampleType type = SolrShardHashSampleType.valueOf(matcher.group(1));
|
SolrShardHashSampleType type = SolrShardHashSampleType.valueOf(matcher.group(1));
|
||||||
int shards = Integer.parseInt(matcher.group(2));
|
short shards = Short.parseShort(matcher.group(2));
|
||||||
return this.createSampleHashTable(type, shards);
|
return this.createSampleHashTable(type, shards);
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
// this should never happen, because of the regex
|
// this should never happen, because of the regex
|
||||||
@@ -67,7 +67,7 @@ public abstract class AbstractAsieShardableWebScript extends AbstractAsieWebScri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SolrShardHashTable<?> createSampleHashTable(SolrShardHashSampleType sampleType, int shards) {
|
protected SolrShardHashTable<?> createSampleHashTable(SolrShardHashSampleType sampleType, short shards) {
|
||||||
int thisYear = Year.now().getValue();
|
int thisYear = Year.now().getValue();
|
||||||
|
|
||||||
switch (sampleType) {
|
switch (sampleType) {
|
||||||
|
@@ -1,19 +1,21 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
import org.alfresco.util.Pair;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.extensions.webscripts.WebScriptException;
|
|
||||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.model.Node;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
import com.inteligr8.alfresco.asie.service.ShardBackupService;
|
import com.inteligr8.alfresco.asie.service.ShardBackupService;
|
||||||
|
import com.inteligr8.alfresco.asie.spi.ShardDiscoveryService;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.backupNode.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.backupNode.get")
|
||||||
public class GetBackupNodeWebScript extends AbstractAsieShardWebScript {
|
public class GetBackupNodeWebScript extends AbstractAsieShardWebScript {
|
||||||
@@ -22,15 +24,15 @@ public class GetBackupNodeWebScript extends AbstractAsieShardWebScript {
|
|||||||
private ShardBackupService sbs;
|
private ShardBackupService sbs;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(WebScriptRequest req, WebScriptResponse res, Set<ShardState> shardNodes) throws IOException {
|
public void execute(WebScriptRequest req, WebScriptResponse res, int shardId, ShardSet shardSet, List<Pair<SolrHost, ShardInstanceState>> nodeShardStates) throws IOException {
|
||||||
if (shardNodes.isEmpty())
|
Collections.sort(nodeShardStates, new ShardDiscoveryService.ShardedNodeShardStateComparator());
|
||||||
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard state could not be found");
|
SolrHost mostRecentNode = nodeShardStates.iterator().next().getFirst();
|
||||||
|
|
||||||
Node node = this.sbs.fetchNode(shardNodes);
|
SolrHost backupNode = this.sbs.selectNode(shardSet, shardId, mostRecentNode);
|
||||||
|
|
||||||
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
res.setContentEncoding("utf-8");
|
res.setContentEncoding("utf-8");
|
||||||
this.getObjectMapper().writeValue(res.getWriter(), node.getId());
|
this.getObjectMapper().writeValue(res.getWriter(), backupNode.getSpec());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.extensions.webscripts.WebScriptException;
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
@@ -13,7 +12,9 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.model.Node;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
import com.inteligr8.alfresco.asie.spi.ShardDiscoveryService;
|
import com.inteligr8.alfresco.asie.spi.ShardDiscoveryService;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.leadNode.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.leadNode.get")
|
||||||
@@ -23,17 +24,14 @@ public class GetLeadNodeWebScript extends AbstractAsieShardWebScript {
|
|||||||
private ShardDiscoveryService sds;
|
private ShardDiscoveryService sds;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(WebScriptRequest req, WebScriptResponse res, Set<ShardState> shardNodesCache) throws IOException {
|
public void execute(WebScriptRequest req, WebScriptResponse res, int shardId, ShardSet shardSet, List<Pair<SolrHost, ShardInstanceState>> nodeShardStates) throws IOException {
|
||||||
if (shardNodesCache.isEmpty())
|
SolrHost latestNode = this.sds.computeLeadNode(nodeShardStates);
|
||||||
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard state could not be found");
|
|
||||||
|
|
||||||
ShardInstance latestNode = this.sds.computeLeadShard(shardNodesCache);
|
|
||||||
if (latestNode == null)
|
if (latestNode == null)
|
||||||
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard state could not be found");
|
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE node could not be found");
|
||||||
|
|
||||||
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
res.setContentEncoding("utf-8");
|
res.setContentEncoding("utf-8");
|
||||||
this.getObjectMapper().writeValue(res.getWriter(), new Node(latestNode).getId());
|
this.getObjectMapper().writeValue(res.getWriter(), latestNode.getSpec());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +1,17 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Instant;
|
import java.util.Map;
|
||||||
import java.time.OffsetDateTime;
|
import java.util.Map.Entry;
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.NodeShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
@@ -22,32 +21,32 @@ import com.inteligr8.alfresco.asie.rest.model.ShardSetInfo;
|
|||||||
public class GetNodeWebScript extends AbstractAsieNodeWebScript {
|
public class GetNodeWebScript extends AbstractAsieNodeWebScript {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void execute(WebScriptRequest req, WebScriptResponse res, Set<ShardState> registeredNodeShards) throws IOException {
|
protected void execute(WebScriptRequest req, WebScriptResponse res, SolrHost node, Map<ShardSet, Map<Integer, ShardInstanceState>> shardSetShardStates) throws IOException {
|
||||||
ShardState anyRegisteredNodeShard = registeredNodeShards.iterator().next();
|
|
||||||
ShardInstance registeredNode = anyRegisteredNodeShard.getShardInstance();
|
|
||||||
int maxShards = registeredNode.getShard().getFloc().getNumberOfShards();
|
|
||||||
|
|
||||||
SolrShardHashSampleType sampleHashType = this.getOptionalQueryParameter(req, "sampleHashType", SolrShardHashSampleType.class);
|
SolrShardHashSampleType sampleHashType = this.getOptionalQueryParameter(req, "sampleHashType", SolrShardHashSampleType.class);
|
||||||
SolrShardHashTable<?> sampleHashTable = sampleHashType == null ? null : this.createSampleHashTable(sampleHashType, maxShards);
|
|
||||||
|
|
||||||
NodeInfo node = new NodeShardInfo(registeredNode);
|
NodeInfo nodeResponse = NodeShardInfo.from(node);
|
||||||
|
|
||||||
for (ShardState registeredNodeShard : registeredNodeShards) {
|
for (Entry<ShardSet, Map<Integer, ShardInstanceState>> shardSet : shardSetShardStates.entrySet()) {
|
||||||
ShardInfo shard = new ShardInfo();
|
Short maxShards = shardSet.getKey().getShards();
|
||||||
shard.setId(registeredNodeShard.getShardInstance().getShard().getInstance());
|
SolrShardHashTable<?> sampleHashTable = null;
|
||||||
shard.setLatestTx(OffsetDateTime.ofInstant(Instant.ofEpochMilli(registeredNodeShard.getLastIndexedTxCommitTime()), ZoneOffset.UTC));
|
if (sampleHashType != null && maxShards != null)
|
||||||
shard.setTxsCompleted(registeredNodeShard.getLastIndexedTxId());
|
sampleHashTable = this.createSampleHashTable(sampleHashType, maxShards);
|
||||||
|
|
||||||
shard.setShardSet(new ShardSetInfo(registeredNodeShard.getShardInstance().getShard().getFloc(), registeredNodeShard));
|
ShardSetInfo shardSetResponse = ShardSetInfo.from(shardSet.getKey());
|
||||||
|
|
||||||
|
for (Entry<Integer, ShardInstanceState> shard : shardSet.getValue().entrySet()) {
|
||||||
|
ShardInfo shardResponse = ShardInfo.from(shard.getKey(), shard.getValue());
|
||||||
|
shardResponse.setShardSet(shardSetResponse);
|
||||||
if (sampleHashTable != null)
|
if (sampleHashTable != null)
|
||||||
this.addShardHashSamples(shard, sampleHashTable);
|
this.addShardHashSamples(shardResponse, sampleHashTable);
|
||||||
|
|
||||||
node.getShards().put(shard.getId(), shard);
|
nodeResponse.getShards().put(shardResponse.getId(), shardResponse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setContentType("application/json");
|
res.setContentType("application/json");
|
||||||
res.setContentEncoding("utf-8");
|
res.setContentEncoding("utf-8");
|
||||||
this.getObjectMapper().writeValue(res.getWriter(), node);
|
this.getObjectMapper().writeValue(res.getWriter(), nodeResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import java.util.TreeMap;
|
|||||||
|
|
||||||
import org.alfresco.repo.index.shard.Floc;
|
import org.alfresco.repo.index.shard.Floc;
|
||||||
import org.alfresco.repo.index.shard.Shard;
|
import org.alfresco.repo.index.shard.Shard;
|
||||||
|
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
import org.alfresco.repo.index.shard.ShardState;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -18,7 +19,9 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
||||||
import com.inteligr8.alfresco.asie.model.Node;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.NodeShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
@@ -39,34 +42,44 @@ public class GetNodesWebScript extends AbstractAsieShardableWebScript {
|
|||||||
|
|
||||||
SolrShardHashSampleType sampleHashType = this.getOptionalQueryParameter(req, "sampleHashType", SolrShardHashSampleType.class);
|
SolrShardHashSampleType sampleHashType = this.getOptionalQueryParameter(req, "sampleHashType", SolrShardHashSampleType.class);
|
||||||
|
|
||||||
Map<String, NodeInfo> nodes = new TreeMap<>();
|
Map<String, NodeInfo> nodesResponse = new TreeMap<>();
|
||||||
|
|
||||||
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
int maxShards = floc.getKey().getNumberOfShards();
|
Short maxShards = floc.getKey().getShardMethod().equals(ShardMethodEnum.DB_ID_RANGE) ? null : (short) floc.getKey().getNumberOfShards();
|
||||||
|
SolrShardHashTable<?> sampleHashTable = null;
|
||||||
|
if (sampleHashType != null && maxShards != null)
|
||||||
|
sampleHashTable = this.createSampleHashTable(sampleHashType, maxShards);
|
||||||
|
|
||||||
SolrShardHashTable<?> sampleHashTable = sampleHashType == null ? null : this.createSampleHashTable(sampleHashType, maxShards);
|
ShardSetInfo shardSetResponse = null;
|
||||||
|
|
||||||
for (Entry<Shard, Set<ShardState>> registeredShards : floc.getValue().entrySet()) {
|
for (Entry<Shard, Set<ShardState>> registeredShards : floc.getValue().entrySet()) {
|
||||||
for (ShardState registeredShardNode : registeredShards.getValue()) {
|
for (ShardState registeredShardNode : registeredShards.getValue()) {
|
||||||
String nodeId = new Node(registeredShardNode.getShardInstance()).getId();
|
if (shardSetResponse == null) {
|
||||||
NodeInfo node = nodes.get(nodeId);
|
ShardSet shardSet = ShardSet.from(floc.getKey(), registeredShardNode);
|
||||||
if (node == null) {
|
shardSetResponse = ShardSetInfo.from(shardSet);
|
||||||
node = new NodeShardInfo(registeredShardNode.getShardInstance());
|
|
||||||
nodes.put(node.getId(), node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ShardInfo shard = new ShardInfo(registeredShardNode);
|
SolrHost node = SolrHost.from(registeredShardNode.getShardInstance());
|
||||||
shard.setShardSet(new ShardSetInfo(floc.getKey(), registeredShardNode));
|
String nodeSpec = node.getSpec();
|
||||||
|
NodeInfo nodeResponse = nodesResponse.get(nodeSpec);
|
||||||
|
if (nodeResponse == null) {
|
||||||
|
nodeResponse = NodeShardInfo.from(node);
|
||||||
|
nodesResponse.put(nodeResponse.getId(), nodeResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShardInstanceState nodeShardState = ShardInstanceState.from(registeredShardNode);
|
||||||
|
ShardInfo shardResponse = ShardInfo.from(registeredShards.getKey().getInstance(), nodeShardState);
|
||||||
|
shardResponse.setShardSet(shardSetResponse);
|
||||||
if (sampleHashTable != null)
|
if (sampleHashTable != null)
|
||||||
this.addShardHashSamples(shard, sampleHashTable);
|
this.addShardHashSamples(shardResponse, sampleHashTable);
|
||||||
node.getShards().put(shard.getId(), shard);
|
nodeResponse.getShards().put(shardResponse.getId(), shardResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setContentType("application/json");
|
res.setContentType("application/json");
|
||||||
res.setContentEncoding("utf-8");
|
res.setContentEncoding("utf-8");
|
||||||
this.getObjectMapper().writeValue(res.getWriter(), nodes);
|
this.getObjectMapper().writeValue(res.getWriter(), nodesResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,7 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -14,10 +10,7 @@ import java.util.Map.Entry;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.Floc;
|
|
||||||
import org.alfresco.repo.index.shard.Shard;
|
|
||||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -30,11 +23,14 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.PropertyHashShardSetInfo;
|
import com.inteligr8.alfresco.asie.rest.model.PropertyHashShardSetInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.ShardNodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardNodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.service.ShardDiscoveryService;
|
import com.inteligr8.alfresco.asie.spi.ShardDiscoveryService;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.propertyHashShards.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.propertyHashShards.get")
|
||||||
public class GetPropertyHashShardsWebScript extends AbstractAsieShardableWebScript {
|
public class GetPropertyHashShardsWebScript extends AbstractAsieShardableWebScript {
|
||||||
@@ -55,19 +51,18 @@ public class GetPropertyHashShardsWebScript extends AbstractAsieShardableWebScri
|
|||||||
List<String> values = this.getOptionalQueryParameterAsList(req);
|
List<String> values = this.getOptionalQueryParameterAsList(req);
|
||||||
this.validateParameters(min, max, values);
|
this.validateParameters(min, max, values);
|
||||||
|
|
||||||
List<PropertyHashShardSetInfo> shardSets = new LinkedList<>();
|
List<PropertyHashShardSetInfo> shardSetsResponse = new LinkedList<>();
|
||||||
|
|
||||||
Collection<Pair<Floc, Map<Shard, Set<ShardState>>>> flocs = this.sds.findByShardMethod(ShardMethodEnum.PROPERTY);
|
Set<ShardSet> shardSets = this.sds.findSetsByShardMethod(ShardMethodEnum.PROPERTY);
|
||||||
if (flocs.isEmpty())
|
if (shardSets.isEmpty())
|
||||||
throw new WebScriptException(HttpStatus.NO_CONTENT.value(), "There are no property-based shards");
|
throw new WebScriptException(HttpStatus.NO_CONTENT.value(), "There are no property-based shards");
|
||||||
|
|
||||||
for (Pair<Floc, Map<Shard, Set<ShardState>>> floc : flocs) {
|
for (ShardSet shardSet : shardSets) {
|
||||||
ShardState anyShardNode = this.getAnyShardNode(floc.getSecond());
|
PropertyHashShardSetInfo shardSetResponse = PropertyHashShardSetInfo.from(shardSet);
|
||||||
PropertyHashShardSetInfo shardSet = new PropertyHashShardSetInfo(floc.getFirst(), anyShardNode);
|
shardSetResponse.setShards(new TreeMap<>());
|
||||||
shardSet.setShards(new TreeMap<>());
|
|
||||||
|
|
||||||
int maxShards = floc.getFirst().getNumberOfShards();
|
Short shardCount = shardSet.getShards();
|
||||||
SolrShardHashTable<?> sampleHashTable = this.createSampleHashTable(sampleHashType, maxShards);
|
SolrShardHashTable<?> sampleHashTable = this.createSampleHashTable(sampleHashType, shardCount);
|
||||||
|
|
||||||
Map<Integer, List<Object>> shardToHashMap = new HashMap<>();
|
Map<Integer, List<Object>> shardToHashMap = new HashMap<>();
|
||||||
|
|
||||||
@@ -83,39 +78,24 @@ public class GetPropertyHashShardsWebScript extends AbstractAsieShardableWebScri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Entry<Shard, Set<ShardState>> shardCache : floc.getSecond().entrySet()) {
|
for (Entry<Integer, Pair<SolrHost, ShardInstanceState>> shard : this.sds.findLatestNodeStates(shardSet).entrySet()) {
|
||||||
ShardInfo shard = new ShardInfo();
|
ShardInfo shardResponse = ShardInfo.from(shard.getKey(), shard.getValue().getSecond());
|
||||||
shard.setId(shardCache.getKey().getInstance());
|
shardResponse.setNodes(new HashMap<>());
|
||||||
shard.setNodes(new HashMap<>());
|
|
||||||
|
|
||||||
for (ShardState shardNodeCache : shardCache.getValue()) {
|
NodeInfo nodeResponse = ShardNodeInfo.from(shard.getValue().getFirst(), shard.getValue().getSecond());
|
||||||
if (shard.getTxsCompleted() == null || shard.getTxsCompleted().longValue() < shardNodeCache.getLastIndexedTxId()) {
|
shardResponse.getNodes().put(nodeResponse.getId(), nodeResponse);
|
||||||
shard.setLatestTx(OffsetDateTime.ofInstant(Instant.ofEpochMilli(shardNodeCache.getLastIndexedTxCommitTime()), ZoneOffset.UTC));
|
|
||||||
shard.setTxsCompleted(shardNodeCache.getLastIndexedTxId());
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeInfo node = new ShardNodeInfo(shardNodeCache);
|
List<Object> hashedValues = shardToHashMap.get(shardResponse.getId());
|
||||||
shard.getNodes().put(node.getId(), node);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Object> hashedValues = shardToHashMap.get(shard.getId());
|
|
||||||
if (hashedValues != null) for (Object hashedValue : hashedValues)
|
if (hashedValues != null) for (Object hashedValue : hashedValues)
|
||||||
shardSet.getShards().put(hashedValue, shard);
|
shardSetResponse.getShards().put(hashedValue, shardResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
shardSets.add(shardSet);
|
shardSetsResponse.add(shardSetResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
res.setContentEncoding("utf-8");
|
res.setContentEncoding("utf-8");
|
||||||
this.getObjectMapper().writeValue(res.getWriter(), shardSets);
|
this.getObjectMapper().writeValue(res.getWriter(), shardSetsResponse);
|
||||||
}
|
|
||||||
|
|
||||||
private ShardState getAnyShardNode(Map<Shard, Set<ShardState>> shards) {
|
|
||||||
for (Set<ShardState> shardNodes : shards.values())
|
|
||||||
for (ShardState shardNode : shardNodes)
|
|
||||||
return shardNode;
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getOptionalQueryParameterAsList(WebScriptRequest req) {
|
private List<String> getOptionalQueryParameterAsList(WebScriptRequest req) {
|
||||||
|
@@ -1,20 +1,19 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Instant;
|
import java.util.List;
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.Shard;
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.ShardNodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardNodeInfo;
|
||||||
@@ -24,34 +23,35 @@ import com.inteligr8.alfresco.asie.rest.model.ShardSetInfo;
|
|||||||
public class GetShardWebScript extends AbstractAsieShardWebScript {
|
public class GetShardWebScript extends AbstractAsieShardWebScript {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(WebScriptRequest req, WebScriptResponse res, Set<ShardState> registeredShardNodes) throws IOException {
|
public void execute(WebScriptRequest req, WebScriptResponse res, int shardId, ShardSet shardSet, List<Pair<SolrHost, ShardInstanceState>> nodeShardStates) throws IOException {
|
||||||
ShardState aRegisteredShardNode = registeredShardNodes.iterator().next();
|
|
||||||
Shard registeredShard = aRegisteredShardNode.getShardInstance().getShard();
|
|
||||||
int maxShards = registeredShard.getFloc().getNumberOfShards();
|
|
||||||
|
|
||||||
SolrShardHashSampleType sampleHashType = this.getOptionalQueryParameter(req, "sampleHashType", SolrShardHashSampleType.class);
|
SolrShardHashSampleType sampleHashType = this.getOptionalQueryParameter(req, "sampleHashType", SolrShardHashSampleType.class);
|
||||||
SolrShardHashTable<?> sampleHashTable = sampleHashType == null ? null : this.createSampleHashTable(sampleHashType, maxShards);
|
|
||||||
|
|
||||||
ShardInfo shard = new ShardInfo();
|
Short maxShards = shardSet.getShards();
|
||||||
shard.setId(registeredShard.getInstance());
|
SolrShardHashTable<?> sampleHashTable = null;
|
||||||
shard.setShardSet(new ShardSetInfo(registeredShard.getFloc(), aRegisteredShardNode));
|
if (sampleHashType != null && maxShards != null)
|
||||||
shard.setNodes(new TreeMap<>());
|
sampleHashTable = this.createSampleHashTable(sampleHashType, maxShards);
|
||||||
|
|
||||||
|
ShardSetInfo shardSetResponse = ShardSetInfo.from(shardSet);
|
||||||
|
|
||||||
|
ShardInfo shardResponse = ShardInfo.from(shardId);
|
||||||
|
shardResponse.setShardSet(shardSetResponse);
|
||||||
|
shardResponse.setNodes(new TreeMap<>());
|
||||||
if (sampleHashTable != null)
|
if (sampleHashTable != null)
|
||||||
this.addShardHashSamples(shard, sampleHashTable);
|
this.addShardHashSamples(shardResponse, sampleHashTable);
|
||||||
|
|
||||||
for (ShardState registeredShardNode : registeredShardNodes) {
|
for (Pair<SolrHost, ShardInstanceState> nodeShardState : nodeShardStates) {
|
||||||
if (shard.getTxsCompleted() == null || shard.getTxsCompleted().longValue() < registeredShardNode.getLastIndexedTxId()) {
|
if (shardResponse.getTxsCompleted() == null || shardResponse.getTxsCompleted().longValue() < nodeShardState.getSecond().getLastIndexedTxId()) {
|
||||||
shard.setLatestTx(OffsetDateTime.ofInstant(Instant.ofEpochMilli(registeredShardNode.getLastIndexedTxCommitTime()), ZoneOffset.UTC));
|
shardResponse.setLatestTx(nodeShardState.getSecond().getLastIndexedTxTime());
|
||||||
shard.setTxsCompleted(registeredShardNode.getLastIndexedTxId());
|
shardResponse.setTxsCompleted(nodeShardState.getSecond().getLastIndexedTxId());
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeInfo node = new ShardNodeInfo(registeredShardNode);
|
NodeInfo node = ShardNodeInfo.from(nodeShardState.getFirst(), nodeShardState.getSecond());
|
||||||
shard.getNodes().put(node.getId(), node);
|
shardResponse.getNodes().put(node.getId(), node);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
res.setContentEncoding("utf-8");
|
res.setContentEncoding("utf-8");
|
||||||
this.getObjectMapper().writeValue(res.getWriter(), shard);
|
this.getObjectMapper().writeValue(res.getWriter(), shardResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,9 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.model.ShardNodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardNodeInfo;
|
||||||
@@ -42,42 +45,46 @@ public class GetShardsWebScript extends AbstractAsieShardableWebScript {
|
|||||||
|
|
||||||
SolrShardHashSampleType sampleHashType = this.getOptionalQueryParameter(req, "sampleHashType", SolrShardHashSampleType.class);
|
SolrShardHashSampleType sampleHashType = this.getOptionalQueryParameter(req, "sampleHashType", SolrShardHashSampleType.class);
|
||||||
|
|
||||||
Map<String, ShardSetInfo> shardSets = new TreeMap<>();
|
Map<String, ShardSetInfo> shardSetsResponse = new TreeMap<>();
|
||||||
|
|
||||||
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
||||||
int maxShards = floc.getKey().getNumberOfShards();
|
|
||||||
ShardState anyShardNode = this.getAnyShardNode(floc.getValue());
|
ShardState anyShardNode = this.getAnyShardNode(floc.getValue());
|
||||||
ShardSetInfo shardSet = new ShardSetInfo(floc.getKey(), anyShardNode);
|
ShardSet shardSet = ShardSet.from(floc.getKey(), anyShardNode);
|
||||||
shardSet.setShards(new TreeMap<>());
|
ShardSetInfo shardSetResponse = ShardSetInfo.from(shardSet);
|
||||||
|
shardSetResponse.setShards(new TreeMap<>());
|
||||||
|
|
||||||
SolrShardHashTable<?> sampleHashTable = sampleHashType == null ? null : this.createSampleHashTable(sampleHashType, maxShards);
|
Short maxShards = shardSet.getShards();
|
||||||
|
SolrShardHashTable<?> sampleHashTable = null;
|
||||||
|
if (sampleHashType != null && maxShards != null)
|
||||||
|
sampleHashTable = this.createSampleHashTable(sampleHashType, maxShards);
|
||||||
|
|
||||||
for (Entry<Shard, Set<ShardState>> registeredShard : floc.getValue().entrySet()) {
|
for (Entry<Shard, Set<ShardState>> registeredShard : floc.getValue().entrySet()) {
|
||||||
ShardInfo shard = new ShardInfo();
|
ShardInfo shardResponse = ShardInfo.from(registeredShard.getKey().getInstance());
|
||||||
shard.setId(registeredShard.getKey().getInstance());
|
shardResponse.setNodes(new TreeMap<>());
|
||||||
shard.setNodes(new TreeMap<>());
|
|
||||||
|
|
||||||
for (ShardState registeredShardNode : registeredShard.getValue()) {
|
for (ShardState registeredShardNode : registeredShard.getValue()) {
|
||||||
if (shard.getTxsCompleted() == null || shard.getTxsCompleted().longValue() < registeredShardNode.getLastIndexedTxId()) {
|
if (shardResponse.getTxsCompleted() == null || shardResponse.getTxsCompleted().longValue() < registeredShardNode.getLastIndexedTxId()) {
|
||||||
shard.setLatestTx(OffsetDateTime.ofInstant(Instant.ofEpochMilli(registeredShardNode.getLastIndexedTxCommitTime()), ZoneOffset.UTC));
|
shardResponse.setLatestTx(OffsetDateTime.ofInstant(Instant.ofEpochMilli(registeredShardNode.getLastIndexedTxCommitTime()), ZoneOffset.UTC));
|
||||||
shard.setTxsCompleted(registeredShardNode.getLastIndexedTxId());
|
shardResponse.setTxsCompleted(registeredShardNode.getLastIndexedTxId());
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeInfo node = new ShardNodeInfo(registeredShardNode);
|
SolrHost node = SolrHost.from(registeredShardNode.getShardInstance());
|
||||||
shard.getNodes().put(node.getId(), node);
|
ShardInstanceState nodeShardState = ShardInstanceState.from(registeredShardNode);
|
||||||
|
NodeInfo nodeResponse = ShardNodeInfo.from(node, nodeShardState);
|
||||||
|
shardResponse.getNodes().put(nodeResponse.getId(), nodeResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sampleHashTable != null)
|
if (sampleHashTable != null)
|
||||||
this.addShardHashSamples(shardSet, shard, sampleHashTable);
|
this.addShardHashSamples(shardSetResponse, shardResponse, sampleHashTable);
|
||||||
shardSet.getShards().put(shard.getId(), shard);
|
shardSetResponse.getShards().put(shardResponse.getId(), shardResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
shardSets.put(shardSet.getMethodSpec(), shardSet);
|
shardSetsResponse.put(shardSetResponse.getSpec(), shardSetResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
res.setContentEncoding("utf-8");
|
res.setContentEncoding("utf-8");
|
||||||
this.getObjectMapper().writeValue(res.getWriter(), shardSets);
|
this.getObjectMapper().writeValue(res.getWriter(), shardSetsResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ShardState getAnyShardNode(Map<Shard, Set<ShardState>> shards) {
|
private ShardState getAnyShardNode(Map<Shard, Set<ShardState>> shards) {
|
||||||
|
@@ -3,12 +3,10 @@ package com.inteligr8.alfresco.asie.rest.model;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.inteligr8.alfresco.asie.model.Node;
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
|
||||||
public abstract class NodeInfo {
|
public abstract class NodeInfo implements ResponseInfo {
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private String id;
|
private String id;
|
||||||
@@ -19,8 +17,8 @@ public abstract class NodeInfo {
|
|||||||
public NodeInfo() {
|
public NodeInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeInfo(ShardInstance nodeCache) {
|
protected NodeInfo(SolrHost node) {
|
||||||
this.setId(new Node(nodeCache).getId());
|
this.id = node.getSpec();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
@@ -2,25 +2,28 @@ package com.inteligr8.alfresco.asie.rest.model;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
|
||||||
@JsonInclude(Include.NON_EMPTY)
|
@JsonInclude(Include.NON_EMPTY)
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class NodeShardInfo extends NodeInfo {
|
public class NodeShardInfo extends NodeInfo {
|
||||||
|
|
||||||
|
public static NodeShardInfo from(SolrHost node) {
|
||||||
|
return new NodeShardInfo(node);
|
||||||
|
}
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private Map<Integer, ShardInfo> shards;
|
private Map<Integer, ShardInfo> shards;
|
||||||
|
|
||||||
public NodeShardInfo() {
|
public NodeShardInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeShardInfo(ShardInstance nodeCache) {
|
protected NodeShardInfo(SolrHost node) {
|
||||||
super(nodeCache);
|
super(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
package com.inteligr8.alfresco.asie.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
|
||||||
public class NodeShardParameterSet extends NodeParameterSet {
|
public class NodeShardParameterSet extends NodeParameterSet {
|
||||||
|
|
@@ -2,24 +2,25 @@ package com.inteligr8.alfresco.asie.rest.model;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.Floc;
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
import com.inteligr8.alfresco.asie.model.ShardSet;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
|
||||||
@JsonInclude(Include.NON_EMPTY)
|
@JsonInclude(Include.NON_EMPTY)
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class PropertyHashShardSetInfo {
|
public class PropertyHashShardSetInfo implements ResponseInfo {
|
||||||
|
|
||||||
|
public static PropertyHashShardSetInfo from(ShardSet shardSet) {
|
||||||
|
return new PropertyHashShardSetInfo(shardSet);
|
||||||
|
}
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private String methodSpec;
|
private String core;
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private int shardCount;
|
private String spec;
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private Map<Object, ShardInfo> shards;
|
private Map<Object, ShardInfo> shards;
|
||||||
@@ -27,26 +28,25 @@ public class PropertyHashShardSetInfo {
|
|||||||
public PropertyHashShardSetInfo() {
|
public PropertyHashShardSetInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyHashShardSetInfo(Floc floc, ShardState anyShardNode) {
|
protected PropertyHashShardSetInfo(ShardSet shardSet) {
|
||||||
ShardSet shardSet = new ShardSet(floc, anyShardNode);
|
this.core = shardSet.getCore();
|
||||||
this.setMethodSpec(shardSet.toSpec());
|
this.spec = shardSet.toSpec();
|
||||||
this.setShardCount(floc.getNumberOfShards());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMethodSpec() {
|
public String getCore() {
|
||||||
return this.methodSpec;
|
return core;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMethodSpec(String methodSpec) {
|
public void setCore(String core) {
|
||||||
this.methodSpec = methodSpec;
|
this.core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getShardCount() {
|
public String getSpec() {
|
||||||
return shardCount;
|
return this.spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShardCount(int shardCount) {
|
public void setSpec(String spec) {
|
||||||
this.shardCount = shardCount;
|
this.spec = spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Object, ShardInfo> getShards() {
|
public Map<Object, ShardInfo> getShards() {
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
|
public interface RequestParameterSet {
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
|
public interface ResponseInfo {
|
||||||
|
|
||||||
|
}
|
@@ -1,22 +1,27 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
|
|
||||||
@JsonInclude(Include.NON_EMPTY)
|
@JsonInclude(Include.NON_EMPTY)
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class ShardInfo {
|
public class ShardInfo implements ResponseInfo {
|
||||||
|
|
||||||
|
public static ShardInfo from(int shardId) {
|
||||||
|
return new ShardInfo(shardId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShardInfo from(int shardId, ShardInstanceState nodeShardState) {
|
||||||
|
return new ShardInfo(shardId, nodeShardState);
|
||||||
|
}
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private int id;
|
private int id;
|
||||||
@@ -40,10 +45,10 @@ public class ShardInfo {
|
|||||||
public ShardInfo() {
|
public ShardInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShardInfo(ShardState shard) {
|
protected ShardInfo(int shardId, ShardInstanceState nodeShardState) {
|
||||||
this.setId(shard.getShardInstance().getShard().getInstance());
|
this.id = shardId;
|
||||||
this.setLatestTx(OffsetDateTime.ofInstant(Instant.ofEpochMilli(shard.getLastIndexedTxCommitTime()), ZoneOffset.UTC));
|
this.latestTx = nodeShardState == null ? null : nodeShardState.getLastIndexedTxTime();
|
||||||
this.setTxsCompleted(shard.getLastIndexedTxId());
|
this.txsCompleted = nodeShardState == null ? null : nodeShardState.getLastIndexedTxId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
|
@@ -1,10 +1,6 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
|
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
|
||||||
@@ -12,11 +8,17 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
|
|
||||||
@JsonInclude(Include.NON_EMPTY)
|
@JsonInclude(Include.NON_EMPTY)
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class ShardNodeInfo extends NodeInfo {
|
public class ShardNodeInfo extends NodeInfo {
|
||||||
|
|
||||||
|
public static ShardNodeInfo from(SolrHost node, ShardInstanceState nodeShardState) {
|
||||||
|
return new ShardNodeInfo(node, nodeShardState);
|
||||||
|
}
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private Long txsCompleted;
|
private Long txsCompleted;
|
||||||
|
|
||||||
@@ -24,13 +26,16 @@ public class ShardNodeInfo extends NodeInfo {
|
|||||||
@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
|
@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
|
||||||
private OffsetDateTime latestTx;
|
private OffsetDateTime latestTx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Spring deserialization
|
||||||
|
*/
|
||||||
public ShardNodeInfo() {
|
public ShardNodeInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShardNodeInfo(ShardState shard) {
|
protected ShardNodeInfo(SolrHost node, ShardInstanceState nodeShardState) {
|
||||||
super(shard.getShardInstance());
|
super(node);
|
||||||
this.setLatestTx(OffsetDateTime.ofInstant(Instant.ofEpochMilli(shard.getLastIndexedTxCommitTime()), ZoneOffset.UTC));
|
this.latestTx = nodeShardState.getLastIndexedTxTime();
|
||||||
this.setTxsCompleted(shard.getLastIndexedTxId());
|
this.txsCompleted = nodeShardState.getLastIndexedTxId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getTxsCompleted() {
|
public Long getTxsCompleted() {
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
package com.inteligr8.alfresco.asie.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
|
||||||
public class ShardParameterSet implements RequestParameterSet {
|
public class ShardParameterSet implements RequestParameterSet {
|
||||||
|
|
@@ -4,24 +4,40 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.Floc;
|
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
import com.inteligr8.alfresco.asie.model.ShardSet;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
|
||||||
@JsonInclude(Include.NON_EMPTY)
|
@JsonInclude(Include.NON_EMPTY)
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class ShardSetInfo {
|
public class ShardSetInfo implements ResponseInfo {
|
||||||
|
|
||||||
|
public static ShardSetInfo from(ShardSet shardSet) {
|
||||||
|
return new ShardSetInfo(shardSet);
|
||||||
|
}
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private String methodSpec;
|
private String spec;
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private int shardCount;
|
private ShardMethodEnum method;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private boolean fulltextEnabled;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String template;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private Set<StoreRef> storeRefs;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private Short shardCount;
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private Map<Integer, ShardInfo> shards;
|
private Map<Integer, ShardInfo> shards;
|
||||||
@@ -32,25 +48,60 @@ public class ShardSetInfo {
|
|||||||
public ShardSetInfo() {
|
public ShardSetInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShardSetInfo(Floc floc, ShardState anyShardNode) {
|
protected ShardSetInfo(ShardSet shardSet) {
|
||||||
ShardSet shardSet = new ShardSet(floc, anyShardNode);
|
this.spec = shardSet.toSpec();
|
||||||
this.methodSpec = shardSet.toSpec();
|
this.method = shardSet.getMethod();
|
||||||
this.setShardCount(floc.getNumberOfShards());
|
this.fulltextEnabled = shardSet.hasContent();
|
||||||
|
this.template = shardSet.getTemplate();
|
||||||
|
this.storeRefs = shardSet.getStoreRefs();
|
||||||
|
this.shardCount = shardSet.getShards();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMethodSpec() {
|
public String getSpec() {
|
||||||
return this.methodSpec;
|
return this.spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMethodSpec(String methodSpec) {
|
public void setSpec(String spec) {
|
||||||
this.methodSpec = methodSpec;
|
this.spec = spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getShardCount() {
|
public ShardMethodEnum getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethod(ShardMethodEnum method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFulltextEnabled() {
|
||||||
|
return fulltextEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFulltextEnabled(boolean fulltextEnabled) {
|
||||||
|
this.fulltextEnabled = fulltextEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTemplate() {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemplate(String template) {
|
||||||
|
this.template = template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<StoreRef> getStoreRefs() {
|
||||||
|
return storeRefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoreRefs(Set<StoreRef> storeRefs) {
|
||||||
|
this.storeRefs = storeRefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Short getShardCount() {
|
||||||
return shardCount;
|
return shardCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShardCount(int shardCount) {
|
public void setShardCount(Short shardCount) {
|
||||||
this.shardCount = shardCount;
|
this.shardCount = shardCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,11 +1,7 @@
|
|||||||
package com.inteligr8.alfresco.asie.service;
|
package com.inteligr8.alfresco.asie.service;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.Shard;
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -15,8 +11,8 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.Constants;
|
import com.inteligr8.alfresco.asie.Constants;
|
||||||
import com.inteligr8.alfresco.asie.model.Node;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
import com.inteligr8.alfresco.asie.spi.ShardDiscoveryService;
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class ShardBackupService implements com.inteligr8.alfresco.asie.spi.ShardBackupService {
|
public class ShardBackupService implements com.inteligr8.alfresco.asie.spi.ShardBackupService {
|
||||||
@@ -24,9 +20,6 @@ public class ShardBackupService implements com.inteligr8.alfresco.asie.spi.Shard
|
|||||||
private static final String ATTR_BACKUP_NODE = "backupNode";
|
private static final String ATTR_BACKUP_NODE = "backupNode";
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ShardDiscoveryService sds;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(Constants.QUALIFIER_ASIE)
|
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||||
private AttributeService attributeService;
|
private AttributeService attributeService;
|
||||||
@@ -34,21 +27,14 @@ public class ShardBackupService implements com.inteligr8.alfresco.asie.spi.Shard
|
|||||||
@Value("${inteligr8.asie.backup.persistTimeMinutes}")
|
@Value("${inteligr8.asie.backup.persistTimeMinutes}")
|
||||||
private int persistTimeMinutes;
|
private int persistTimeMinutes;
|
||||||
|
|
||||||
public Node fetchNode(Collection<ShardState> shardNodes) {
|
public SolrHost selectNode(ShardSet shardSet, int shardId, SolrHost node) {
|
||||||
if (shardNodes.isEmpty())
|
String shardKey = shardSet.getCore() + "-" + shardId;
|
||||||
return null;
|
|
||||||
|
|
||||||
ShardState shardNode0 = shardNodes.iterator().next();
|
|
||||||
ShardInstance node0Shard = shardNode0.getShardInstance();
|
|
||||||
Shard shard = node0Shard.getShard();
|
|
||||||
String shardKey = shard.getFloc().getShardMethod().name() + "~" + shard.getFloc().getNumberOfShards() + "~" + shard.getInstance();
|
|
||||||
|
|
||||||
PersistedNode backupNode = (PersistedNode) this.attributeService.getAttribute(Constants.ATTR_ASIE, ATTR_BACKUP_NODE, shardKey);
|
PersistedNode backupNode = (PersistedNode) this.attributeService.getAttribute(Constants.ATTR_ASIE, ATTR_BACKUP_NODE, shardKey);
|
||||||
this.logger.debug("Found backup node: {}", backupNode);
|
this.logger.debug("Found backup node: {}", backupNode);
|
||||||
|
|
||||||
if (backupNode == null || backupNode.isExpired()) {
|
if (backupNode == null || backupNode.isExpired()) {
|
||||||
ShardInstance backupShardInstance = this.sds.computeLeadShard(shardNodes);
|
backupNode = new PersistedNode(node);
|
||||||
backupNode = new PersistedNode(new Node(backupShardInstance));
|
|
||||||
this.attributeService.setAttribute(backupNode, Constants.ATTR_ASIE, ATTR_BACKUP_NODE, shardKey);
|
this.attributeService.setAttribute(backupNode, Constants.ATTR_ASIE, ATTR_BACKUP_NODE, shardKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,11 +45,8 @@ public class ShardBackupService implements com.inteligr8.alfresco.asie.spi.Shard
|
|||||||
this.attributeService.removeAttribute(Constants.ATTR_ASIE, ATTR_BACKUP_NODE);
|
this.attributeService.removeAttribute(Constants.ATTR_ASIE, ATTR_BACKUP_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forget(ShardState shardNode) {
|
public void forget(ShardSet shardSet, int shardId) {
|
||||||
ShardInstance nodeShard = shardNode.getShardInstance();
|
String shardKey = shardSet.getCore() + "-" + shardId;
|
||||||
Shard shard = nodeShard.getShard();
|
|
||||||
String shardKey = shard.getFloc().getShardMethod().name() + "~" + shard.getFloc().getNumberOfShards() + "~" + shard.getInstance();
|
|
||||||
|
|
||||||
this.attributeService.removeAttribute(Constants.ATTR_ASIE, ATTR_BACKUP_NODE, shardKey);
|
this.attributeService.removeAttribute(Constants.ATTR_ASIE, ATTR_BACKUP_NODE, shardKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,10 +56,10 @@ public class ShardBackupService implements com.inteligr8.alfresco.asie.spi.Shard
|
|||||||
|
|
||||||
private static final long serialVersionUID = 4105196543023419818L;
|
private static final long serialVersionUID = 4105196543023419818L;
|
||||||
|
|
||||||
private final Node node;
|
private final SolrHost node;
|
||||||
private long expireTimeMillis;
|
private long expireTimeMillis;
|
||||||
|
|
||||||
PersistedNode(Node node) {
|
PersistedNode(SolrHost node) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
@@ -89,7 +72,7 @@ public class ShardBackupService implements com.inteligr8.alfresco.asie.spi.Shard
|
|||||||
return this.expireTimeMillis < System.currentTimeMillis();
|
return this.expireTimeMillis < System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node getNode() {
|
SolrHost getNode() {
|
||||||
return this.node;
|
return this.node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,159 +0,0 @@
|
|||||||
package com.inteligr8.alfresco.asie.service;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.Floc;
|
|
||||||
import org.alfresco.repo.index.shard.Shard;
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
|
||||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
|
||||||
import org.alfresco.repo.index.shard.ShardRegistry;
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.alfresco.util.Pair;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.Constants;
|
|
||||||
import com.inteligr8.alfresco.asie.model.ShardSet;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class ShardDiscoveryService implements com.inteligr8.alfresco.asie.spi.ShardDiscoveryService {
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
@Qualifier(Constants.QUALIFIER_ASIE)
|
|
||||||
private ShardRegistry shardRegistry;
|
|
||||||
|
|
||||||
public ShardInstance computeLeadShard(Collection<ShardState> shardNodesCache) {
|
|
||||||
if (shardNodesCache.isEmpty())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
long latestTime = 0L;
|
|
||||||
ShardInstance latestNode = null;
|
|
||||||
|
|
||||||
for (ShardState shardNodeCache : shardNodesCache) {
|
|
||||||
if (latestTime < shardNodeCache.getLastIndexedTxCommitTime()) {
|
|
||||||
latestNode = shardNodeCache.getShardInstance();
|
|
||||||
latestTime = shardNodeCache.getLastIndexedTxCommitTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return latestNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<ShardState> findByNode(String nodeHostname, int nodePort) {
|
|
||||||
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
|
||||||
if (flocs.isEmpty())
|
|
||||||
return Collections.emptySet();
|
|
||||||
|
|
||||||
Set<ShardState> shards = new HashSet<>();
|
|
||||||
|
|
||||||
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
|
||||||
for (Entry<Shard, Set<ShardState>> flocShard : floc.getValue().entrySet()) {
|
|
||||||
for (ShardState shardState : flocShard.getValue()) {
|
|
||||||
ShardInstance shardInstance = shardState.getShardInstance();
|
|
||||||
if (!nodeHostname.equalsIgnoreCase(shardInstance.getHostName())) {
|
|
||||||
InetAddress nodeAddress = this.resolve(nodeHostname);
|
|
||||||
if (nodeAddress == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
InetAddress shardInstanceAddress = this.resolve(shardInstance.getHostName());
|
|
||||||
if (!nodeAddress.equals(shardInstanceAddress))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodePort == shardInstance.getPort())
|
|
||||||
shards.add(shardState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return shards;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Shard, Set<ShardState>> findByShardSet(ShardSet shardSet) {
|
|
||||||
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
|
||||||
if (flocs.isEmpty())
|
|
||||||
return Collections.emptyMap();
|
|
||||||
this.logger.trace("Found {} shard sets", flocs.size());
|
|
||||||
|
|
||||||
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
|
||||||
if (!floc.getKey().getShardMethod().equals(shardSet.getMethod()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!shardSet.getConfig().isEmpty()) {
|
|
||||||
if (floc.getValue().isEmpty())
|
|
||||||
continue;
|
|
||||||
Shard firstShard = floc.getValue().keySet().iterator().next();
|
|
||||||
|
|
||||||
Set<ShardState> firstShardStates = floc.getValue().get(firstShard);
|
|
||||||
if (firstShardStates == null || firstShardStates.isEmpty())
|
|
||||||
continue;
|
|
||||||
ShardState firstShardState = firstShardStates.iterator().next();
|
|
||||||
|
|
||||||
Map<String, String> firstShardProps = firstShardState.getPropertyBag();
|
|
||||||
if (!shardSet.isConfigurationFor(firstShardProps))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return floc.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<Pair<Floc, Map<Shard, Set<ShardState>>>> findByShardMethod(ShardMethodEnum shardMethod) {
|
|
||||||
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
|
||||||
if (flocs.isEmpty())
|
|
||||||
return Collections.emptyList();
|
|
||||||
this.logger.trace("Found {} shard sets", flocs.size());
|
|
||||||
|
|
||||||
List<Pair<Floc, Map<Shard, Set<ShardState>>>> filteredFlocs = new LinkedList<>();
|
|
||||||
|
|
||||||
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : flocs.entrySet()) {
|
|
||||||
if (!floc.getKey().getShardMethod().equals(shardMethod))
|
|
||||||
continue;
|
|
||||||
filteredFlocs.add(new Pair<>(floc.getKey(), floc.getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredFlocs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> Set<T> filterByShard(Map<Shard, Set<T>> shards, int shardId) {
|
|
||||||
if (shards == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
for (Entry<Shard, Set<T>> shard : shards.entrySet()) {
|
|
||||||
if (shard.getKey().getInstance() == shardId)
|
|
||||||
return shard.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.emptySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<ShardState> findByShard(ShardSet shardSet, int shardId) {
|
|
||||||
Map<Shard, Set<ShardState>> shards = this.findByShardSet(shardSet);
|
|
||||||
return this.filterByShard(shards, shardId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private InetAddress resolve(String hostname) {
|
|
||||||
try {
|
|
||||||
return InetAddress.getByName(hostname);
|
|
||||||
} catch (UnknownHostException uhe) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,17 +1,14 @@
|
|||||||
package com.inteligr8.alfresco.asie.spi;
|
package com.inteligr8.alfresco.asie.spi;
|
||||||
|
|
||||||
import java.util.Collection;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.model.Node;
|
|
||||||
|
|
||||||
public interface ShardBackupService {
|
public interface ShardBackupService {
|
||||||
|
|
||||||
Node fetchNode(Collection<ShardState> shardNodes);
|
SolrHost selectNode(ShardSet shardSet, int shardId, SolrHost bestNode);
|
||||||
|
|
||||||
void forget();
|
void forget();
|
||||||
|
|
||||||
void forget(ShardState shardNode);
|
void forget(ShardSet shardSet, int shardId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,72 +1,132 @@
|
|||||||
package com.inteligr8.alfresco.asie.spi;
|
package com.inteligr8.alfresco.asie.spi;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.Floc;
|
|
||||||
import org.alfresco.repo.index.shard.Shard;
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
|
||||||
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
import org.alfresco.repo.index.shard.ShardMethodEnum;
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.model.ShardSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
import com.inteligr8.alfresco.asie.model.SolrHost;
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardInstanceState;
|
||||||
|
|
||||||
public interface ShardDiscoveryService {
|
public interface ShardDiscoveryService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the lead shard in the specified node/shard snapshot metadata.
|
* Determine the lead shard in the specified node/shard snapshot metadata.
|
||||||
*
|
*
|
||||||
* @param shardNodes A collection of snapshot metadata.
|
* @param shardNodeStates A collection of shard node/hosts and snapshot metadata.
|
||||||
* @return A single node/shard holding the latest snapshot metadata.
|
* @return A single node/shard holding the latest snapshot metadata.
|
||||||
*/
|
*/
|
||||||
ShardInstance computeLeadShard(Collection<ShardState> shardNodes);
|
default SolrHost computeLeadNode(Collection<Pair<SolrHost, ShardInstanceState>> shardNodeStates) {
|
||||||
|
if (shardNodeStates.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
OffsetDateTime latestTime = OffsetDateTime.MIN;
|
||||||
|
SolrHost latestNode = null;
|
||||||
|
|
||||||
|
for (Pair<SolrHost, ShardInstanceState> shardNodeState : shardNodeStates) {
|
||||||
|
if (latestTime.isBefore(shardNodeState.getSecond().getLastIndexedTxTime())) {
|
||||||
|
latestNode = shardNodeState.getFirst();
|
||||||
|
latestTime = shardNodeState.getSecond().getLastIndexedTxTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return latestNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the shard set by the specified core name.
|
||||||
|
*
|
||||||
|
* @param core A core name (without the shard identifier suffix).
|
||||||
|
* @return A shard set; null if not found.
|
||||||
|
*/
|
||||||
|
ShardSet findSetByCore(String core);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the node with the specified hostname/port.
|
||||||
|
*
|
||||||
|
* @param nodeHostname The hostname of a ASIE node.
|
||||||
|
* @param nodePort The port of an ASIE node.
|
||||||
|
* @return A sharded node/host; null if not found.
|
||||||
|
*/
|
||||||
|
SolrHost findNode(String nodeHostname, int nodePort);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the latest snapshot of each shard on the specified node.
|
* Find the latest snapshot of each shard on the specified node.
|
||||||
*
|
*
|
||||||
* @param nodeHostname The hostname of a ASIE node.
|
* @param node A sharded node/host.
|
||||||
* @param nodePort The port of an ASIE node.
|
|
||||||
* @return A set of the latest snapshot metadata of shards.
|
* @return A set of the latest snapshot metadata of shards.
|
||||||
*/
|
*/
|
||||||
Set<ShardState> findByNode(String nodeHostname, int nodePort);
|
Map<ShardSet, Map<Integer, ShardInstanceState>> findByNode(SolrHost node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the shards, their nodes, and the latest snapshot of each within the
|
* Find all shard sets that support the specified shard methods.
|
||||||
* specified shard set.
|
*
|
||||||
|
* @param shardMethods An array of shard methods.
|
||||||
|
* @return A set of shard sets.
|
||||||
|
*/
|
||||||
|
Set<ShardSet> findSetsByShardMethod(ShardMethodEnum... shardMethods);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the shard node/hosts for the specified shard set.
|
||||||
*
|
*
|
||||||
* @param shardSet A shard set.
|
* @param shardSet A shard set.
|
||||||
* @return A map of shards to sets of the latest snapshot metadata of those shards and their nodes.
|
* @return A set of shard node/hosts.
|
||||||
*/
|
*/
|
||||||
Map<Shard, Set<ShardState>> findByShardSet(ShardSet shardSet);
|
Set<SolrHost> findNodes(ShardSet shardSet);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the shards, their nodes, and the latest snapshot of each using the
|
* Find the shard node/hosts for the specified shard set and identifier.
|
||||||
* specified shard method.
|
|
||||||
*
|
|
||||||
* @param shardMethod A shard method.
|
|
||||||
* @return A collection of maps of shards to sets of the latest snapshot metadata of those shards and their nodes.
|
|
||||||
*/
|
|
||||||
Collection<Pair<Floc, Map<Shard, Set<ShardState>>>> findByShardMethod(ShardMethodEnum shardMethod);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter the latest snapshot of each shard.
|
|
||||||
*
|
|
||||||
* @param shards A map of shards to sets of the latest snapshot metadata of those shards and their nodes.
|
|
||||||
* @param shardId A 0-based index of a shard.
|
|
||||||
* @return A set of the latest snapshot metadata of shards.
|
|
||||||
*/
|
|
||||||
<T> Set<T> filterByShard(Map<Shard, Set<T>> shards, int shardId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the latest snapshot of each shard and their nodes within the
|
|
||||||
* specified shard set.
|
|
||||||
*
|
*
|
||||||
* @param shardSet A shard set.
|
* @param shardSet A shard set.
|
||||||
* @param shardId A 0-based index of a shard.
|
* @param shardId A shard identifier (e.g. 0).
|
||||||
* @return A set of the latest snapshot metadata of shards.
|
* @return A set of shard node/hosts.
|
||||||
*/
|
*/
|
||||||
Set<ShardState> findByShard(ShardSet shardSet, int shardId);
|
Set<SolrHost> findNodesByShard(ShardSet shardSet, int shardId);
|
||||||
|
|
||||||
|
Map<Integer, Pair<SolrHost, ShardInstanceState>> findLatestNodeStates(ShardSet shardSet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the shard node/hosts and their states for the specified shard set
|
||||||
|
* and identifier. The list is left in an unknown order, but it is a list
|
||||||
|
* for easy use of a Comparator for sorting.
|
||||||
|
*
|
||||||
|
* @param shardSet A shard set.
|
||||||
|
* @param shardId A shard identifier (e.g. 0).
|
||||||
|
* @return A list of shard node/hosts and their latest state.
|
||||||
|
*/
|
||||||
|
List<Pair<SolrHost, ShardInstanceState>> findNodeStatesByShard(ShardSet shardSet, int shardId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the shard identifiers for the specified shard set and node/host.
|
||||||
|
*
|
||||||
|
* @param shardSet A shard set.
|
||||||
|
* @param node A shard ndoe/host.
|
||||||
|
* @return A set of shard identifiers.
|
||||||
|
*/
|
||||||
|
Set<Integer> findIdsByNode(ShardSet shardSet, SolrHost node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the shards and their states for the specified shard set and node/host.
|
||||||
|
*
|
||||||
|
* @param shardSet A shard set.
|
||||||
|
* @param node A shard ndoe/host.
|
||||||
|
* @return A map of shards and their states.
|
||||||
|
*/
|
||||||
|
Map<Integer, ShardInstanceState> findStatesByNode(ShardSet shardSet, SolrHost node);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class ShardedNodeShardStateComparator implements Comparator<Pair<SolrHost, ShardInstanceState>> {
|
||||||
|
@Override
|
||||||
|
public int compare(Pair<SolrHost, ShardInstanceState> p1, Pair<SolrHost, ShardInstanceState> p2) {
|
||||||
|
return - Long.compare(p1.getSecond().getLastIndexedTxId(), p2.getSecond().getLastIndexedTxId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.spi;
|
||||||
|
|
||||||
|
import org.alfresco.repo.index.shard.ShardInstance;
|
||||||
|
|
||||||
|
public interface ShardRegistry extends org.alfresco.repo.index.shard.ShardRegistry {
|
||||||
|
|
||||||
|
void unregisterShardInstance(ShardInstance shardInstance);
|
||||||
|
|
||||||
|
}
|
@@ -1,18 +1,13 @@
|
|||||||
package com.inteligr8.alfresco.asie.spi;
|
package com.inteligr8.alfresco.asie.spi;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.attributes.AttributeService.AttributeQueryCallback;
|
|
||||||
|
|
||||||
public interface ShardStateService {
|
public interface ShardStateService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the shard state.
|
* Clears the shard state.
|
||||||
|
*
|
||||||
|
* This allows the framework to provide an alternative implementation from
|
||||||
|
* what is provided by Alfresco Enterprise, which sometimes fails.
|
||||||
*/
|
*/
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void remove(Serializable... keys);
|
|
||||||
|
|
||||||
void iterate(AttributeQueryCallback callback);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -12,12 +12,10 @@
|
|||||||
<dl>
|
<dl>
|
||||||
<dt>nodeEndpoint</dt>
|
<dt>nodeEndpoint</dt>
|
||||||
<dd>A hostname or hostname:port for the ASIE node</dd>
|
<dd>A hostname or hostname:port for the ASIE node</dd>
|
||||||
<dt>shardSet</dt>
|
<dt>shardCore</dt>
|
||||||
<dd>A shard method combined with its distinguishing properties;
|
<dd>A core name (prefix) for the ASIE shard (e.g. alfresco)</dd>
|
||||||
methods: MOD_ACL_ID, ACL_ID, DB_ID, DB_ID_RANGE, DATE, PROPERTY, EXPLICIT_ID;
|
|
||||||
e.g. PROPERTY;key:cm:created;regex:^d{4} or DB_ID</dd>
|
|
||||||
<dt>shardId</dt>
|
<dt>shardId</dt>
|
||||||
<dd>A number starting at 1</dd>
|
<dd>A numeric shard ID for the ASIE shard (e.g. 0)</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<p>The following status codes should be expected:</p>
|
<p>The following status codes should be expected:</p>
|
||||||
<dl>
|
<dl>
|
||||||
@@ -31,7 +29,7 @@
|
|||||||
]]></description>
|
]]></description>
|
||||||
|
|
||||||
<!-- Endpoint Configuration -->
|
<!-- Endpoint Configuration -->
|
||||||
<url>/inteligr8/asie/node/{nodeEndpoint}/shard/{shardSet}/{shardId}</url>
|
<url>/inteligr8/asie/node/{nodeEndpoint}/shard/{shardCore}/{shardId}</url>
|
||||||
|
|
||||||
<!-- Security -->
|
<!-- Security -->
|
||||||
<authentication>admin</authentication>
|
<authentication>admin</authentication>
|
||||||
|
@@ -0,0 +1,41 @@
|
|||||||
|
<webscript xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://bitbucket.org/!api/2.0/snippets/inteligr8/AzMgbp/80fdd26a6b3769a63cdc6b54bf1f39e378545cf7/files/snippet.txt">
|
||||||
|
|
||||||
|
<!-- Naming & Organization -->
|
||||||
|
<shortname>Retrieves ASIE Node Shard Status</shortname>
|
||||||
|
<family>Inteligr8 ASIE</family>
|
||||||
|
<description><![CDATA[
|
||||||
|
<p>Retrieves meta-data about all shards on a single ASIE node as registred with ACS.</p>
|
||||||
|
<p>The following query parameter is supported:</p>
|
||||||
|
<dl>
|
||||||
|
<dt>nodeEndpoint</dt>
|
||||||
|
<dd>A hostname or hostname:port for the ASIE node; dots are not allowed, you may use _ (underscore) instead</dd>
|
||||||
|
<dt>shardCore</dt>
|
||||||
|
<dd>A core name (prefix) for the ASIE shard (e.g. alfresco)</dd>
|
||||||
|
<dt>shardId</dt>
|
||||||
|
<dd>A numeric shard ID for the ASIE shard (e.g. 0)</dd>
|
||||||
|
</dl>
|
||||||
|
<p>The following status codes should be expected:</p>
|
||||||
|
<dl>
|
||||||
|
<dt>200</dt>
|
||||||
|
<dd>OK</dd>
|
||||||
|
<dt>400</dt>
|
||||||
|
<dd>The path parameters are invalid</dd>
|
||||||
|
<dt>404</dt>
|
||||||
|
<dd>The specified ASIE node/shard could not be found</dd>
|
||||||
|
</dl>
|
||||||
|
]]></description>
|
||||||
|
|
||||||
|
<!-- Endpoint Configuration -->
|
||||||
|
<url>/inteligr8/asie/node/{nodeEndpoint}/shard/{shardCore}/{shardId}</url>
|
||||||
|
|
||||||
|
<!-- Security -->
|
||||||
|
<authentication>admin</authentication>
|
||||||
|
|
||||||
|
<!-- Functionality -->
|
||||||
|
<cache>
|
||||||
|
<never>false</never>
|
||||||
|
<public>false</public>
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
</webscript>
|
@@ -2,7 +2,7 @@
|
|||||||
xsi:noNamespaceSchemaLocation="https://bitbucket.org/!api/2.0/snippets/inteligr8/AzMgbp/80fdd26a6b3769a63cdc6b54bf1f39e378545cf7/files/snippet.txt">
|
xsi:noNamespaceSchemaLocation="https://bitbucket.org/!api/2.0/snippets/inteligr8/AzMgbp/80fdd26a6b3769a63cdc6b54bf1f39e378545cf7/files/snippet.txt">
|
||||||
|
|
||||||
<!-- Naming & Organization -->
|
<!-- Naming & Organization -->
|
||||||
<shortname>Adds ASIE Node to Registry</shortname>
|
<shortname>Adds ASIE Node/Shard to Registry</shortname>
|
||||||
<family>Inteligr8 ASIE</family>
|
<family>Inteligr8 ASIE</family>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
<p>Loads an ASIE shard on a single ASIE node, which will eventually register with ACS.</p>
|
<p>Loads an ASIE shard on a single ASIE node, which will eventually register with ACS.</p>
|
||||||
|
@@ -8,12 +8,10 @@
|
|||||||
<p>Retrieve meta-data about the specified ASIE shard registered with ACS.</p>
|
<p>Retrieve meta-data about the specified ASIE shard registered with ACS.</p>
|
||||||
<p>The following path and query parameters are expected or supported:</p>
|
<p>The following path and query parameters are expected or supported:</p>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>shardSet</dt>
|
<dt>shardCore</dt>
|
||||||
<dd>A shard method combined with its distinguishing properties;
|
<dd>A core name (prefix) for the ASIE shard (e.g. alfresco)</dd>
|
||||||
methods: MOD_ACL_ID, ACL_ID, DB_ID, DB_ID_RANGE, DATE, PROPERTY, EXPLICIT_ID;
|
|
||||||
e.g. PROPERTY;key:cm:created;regex:^d{4} or DB_ID</dd>
|
|
||||||
<dt>shardId</dt>
|
<dt>shardId</dt>
|
||||||
<dd>A number starting at 1</dd>
|
<dd>A numeric shard ID for the ASIE shard (e.g. 0)</dd>
|
||||||
<dt>sampleHashType</dt>
|
<dt>sampleHashType</dt>
|
||||||
<dd>A sample hash type; Sample hash types: PropertyYear, PropertyQuarter, PropertyMonth, PropertyWeek</dd>
|
<dd>A sample hash type; Sample hash types: PropertyYear, PropertyQuarter, PropertyMonth, PropertyWeek</dd>
|
||||||
</dl>
|
</dl>
|
||||||
@@ -58,7 +56,7 @@
|
|||||||
]]></description>
|
]]></description>
|
||||||
|
|
||||||
<!-- Endpoint Configuration -->
|
<!-- Endpoint Configuration -->
|
||||||
<url>/inteligr8/asie/shard/{shardSet}/{shardId}?includeSampleHashes={includeSampleHashes?}</url>
|
<url>/inteligr8/asie/shard/{shardCore}/{shardId}?includeSampleHashes={includeSampleHashes?}</url>
|
||||||
<format default="json">any</format>
|
<format default="json">any</format>
|
||||||
|
|
||||||
<!-- Security -->
|
<!-- Security -->
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.inteligr8.alfresco</groupId>
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
<artifactId>asie-platform-module-parent</artifactId>
|
<artifactId>asie-platform-module-parent</artifactId>
|
||||||
<version>1.1-SNAPSHOT</version>
|
<version>1.2-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user