diff --git a/asie-api/pom.xml b/asie-api/pom.xml
index 16e8ef2..d44825d 100644
--- a/asie-api/pom.xml
+++ b/asie-api/pom.xml
@@ -6,7 +6,7 @@
com.inteligr8.alfrescoasie-platform-module-parent
- 1.1-SNAPSHOT
+ 1.2-SNAPSHOT../
diff --git a/enterprise-module/pom.xml b/enterprise-module/pom.xml
index dab60a0..c072d81 100644
--- a/enterprise-module/pom.xml
+++ b/enterprise-module/pom.xml
@@ -6,7 +6,7 @@
com.inteligr8.alfrescoasie-platform-module-parent
- 1.1-SNAPSHOT
+ 1.2-SNAPSHOT../
diff --git a/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/rest/AbstractUnregisterNodeWebScript.java b/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/rest/AbstractUnregisterNodeWebScript.java
index 3e34e5c..0b22feb 100755
--- a/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/rest/AbstractUnregisterNodeWebScript.java
+++ b/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/rest/AbstractUnregisterNodeWebScript.java
@@ -9,6 +9,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import org.alfresco.repo.index.shard.Shard;
import org.alfresco.repo.index.shard.ShardState;
import org.alfresco.service.cmr.attributes.AttributeService;
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.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.service.ShardBackupService;
-import com.inteligr8.alfresco.asie.spi.ShardStateService;
+import com.inteligr8.alfresco.asie.rest.model.NodeParameterSet;
+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.core.StatusRequest;
import com.inteligr8.solr.model.core.StatusResponse;
@@ -99,7 +101,9 @@ public abstract class AbstractUnregisterNodeWebScript {
@@ -20,7 +20,7 @@ public class UnloadNodeShardWebScript extends AbstractUnregisterNodeWebScript {
diff --git a/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardDiscoveryService.java b/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardDiscoveryService.java
new file mode 100644
index 0000000..92bf678
--- /dev/null
+++ b/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardDiscoveryService.java
@@ -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>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return null;
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ for (Entry>> floc : flocs.entrySet()) {
+ for (Entry> 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>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return null;
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ Map resolvedAddresses = new HashMap<>();
+
+ for (Entry>> floc : flocs.entrySet()) {
+ for (Entry> 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> findByNode(SolrHost node) {
+ Map>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return Collections.emptyMap();
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ Map> setShardStates = new HashMap<>();
+
+ for (Entry>> floc : flocs.entrySet())
+ setShardStates.putAll(this.findByNode(node, floc.getKey(), floc.getValue()));
+
+ return setShardStates;
+ }
+
+ private Map> findByNode(SolrHost node, Floc floc, Map> shards) {
+ ShardSet shardSet = null;
+ Map> setShardStates = new HashMap<>();
+ int shardStateCount = 0;
+
+ for (Entry> 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 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 findSetsByShardMethod(ShardMethodEnum... shardMethods) {
+ Map>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return Collections.emptySet();
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ Set shardMethodSet = CollectionUtils.asSet(shardMethods);
+ Set shardSets = new HashSet<>();
+
+ for (Entry>> 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 findNodes(ShardSet shardSet) {
+ Map>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return Collections.emptySet();
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ for (Entry>> floc : flocs.entrySet()) {
+ Set 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 findNodesByShard(ShardSet shardSet, int shardId) {
+ Map>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return Collections.emptySet();
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ for (Entry>> floc : flocs.entrySet()) {
+ Set 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 findNodes(ShardSet shardSet, Integer shardId, Floc floc, Map> shards) {
+ Set nodes = new HashSet<>();
+ boolean checked = false;
+
+ for (Entry> 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> findLatestNodeStates(ShardSet shardSet) {
+ Map>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return Collections.emptyMap();
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ for (Entry>> floc : flocs.entrySet()) {
+ Map> 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> findLatestNodeStates(ShardSet shardSet, Floc floc, Map> shards) {
+ Map> 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 : 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 pair = new Pair<>(node, nodeShardState);
+ if (comparator.compare(pair, shardNodeStates.get(shardId)) < 0)
+ shardNodeStates.put(shardId, pair);
+ }
+ }
+
+ return shardNodeStates;
+ }
+
+ @Override
+ public List> findNodeStatesByShard(ShardSet shardSet, int shardId) {
+ Map>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return Collections.emptyList();
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ for (Entry>> floc : flocs.entrySet()) {
+ List> 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> findNodeStates(ShardSet shardSet, Integer shardId, Floc floc, Map> shards) {
+ List> nodeStates = new LinkedList<>();
+ boolean checked = false;
+
+ for (Entry> 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 findIdsByNode(ShardSet shardSet, SolrHost node) {
+ Map>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return Collections.emptySet();
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ for (Entry>> floc : flocs.entrySet()) {
+ Set 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 findIdsByNode(ShardSet shardSet, SolrHost node, Floc floc, Map> shards) {
+ Set shardIds = new HashSet<>();
+ boolean checked = false;
+
+ for (Entry> 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 findStatesByNode(ShardSet shardSet, SolrHost node) {
+ Map>> flocs = this.shardRegistry.getFlocs();
+ if (flocs.isEmpty())
+ return Collections.emptyMap();
+ this.logger.trace("Found {} shard sets", flocs.size());
+
+ for (Entry>> floc : flocs.entrySet()) {
+ Map 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 findStatesByNode(ShardSet shardSet, SolrHost node, Floc floc, Map> shards) {
+ Map shardStates = new HashMap<>();
+ boolean checked = false;
+
+ for (Entry> 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> shards) {
+ if (shards.isEmpty())
+ return null;
+
+ for (Set 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;
+ }
+ }
+
+}
diff --git a/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardStateService.java b/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardStateService.java
index f60fc39..c6bf625 100644
--- a/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardStateService.java
+++ b/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardStateService.java
@@ -34,7 +34,8 @@ public class ShardStateService implements com.inteligr8.alfresco.asie.spi.ShardS
@Autowired
@Qualifier(Constants.BEAN_SHARD_GUID_CACHE)
private SimpleCache shardToGuidCache;
-
+
+ @Override
public void clear() {
this.logger.info("Removing all nodes/shards from the shard registry");
@@ -76,7 +77,7 @@ public class ShardStateService implements com.inteligr8.alfresco.asie.spi.ShardS
this.shardToGuidCache.remove(shardState.getShardInstance());
}
}
-
+
public void iterate(AttributeQueryCallback callback) {
this.attrService.getAttributes(callback, EnterpriseConstants.ATTR_SHARD_STATE);
}
diff --git a/pom.xml b/pom.xml
index 6ccf9b6..8954c20 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.inteligr8.alfrescoasie-platform-module-parent
- 1.1-SNAPSHOT
+ 1.2-SNAPSHOTpomASIE Platform Module Parent
diff --git a/shared/pom.xml b/shared/pom.xml
index 872cceb..e0e48dc 100644
--- a/shared/pom.xml
+++ b/shared/pom.xml
@@ -6,7 +6,7 @@
com.inteligr8.alfrescoasie-platform-module-parent
- 1.1-SNAPSHOT
+ 1.2-SNAPSHOT../
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/Constants.java b/shared/src/main/java/com/inteligr8/alfresco/asie/Constants.java
index 08c5636..f2e5a89 100755
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/Constants.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/Constants.java
@@ -6,20 +6,15 @@ public interface Constants {
static final String QUALIFIER_ASIE = "asie";
- // OOTB
+ // defined OOTB
static final String BEAN_SHARD_STATE_CACHE = "shardStateCache";
static final String BEAN_SHARD_GUID_CACHE = "shardToGuidCache";
- static final String BEAN_OFFILINE_SHARD_STATE_CACHE = "offlineShardStateCache";
- static final String BEAN_CORE_EXPLICIT_CACHE = "coreExplicitIdCache";
+ static final String BEAN_SHARD_REGISTRY = "asie.ShardRegistry";
static final String BEAN_OBJECT_MAPPER = "asie.ObjectMapper";
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_NODE_SHARD = "inteligr8.asie.nodeShard";
- static final String ATTR_STATE = "state";
- static final String ATTR_ONLINE = "online";
static final String ATTR_UNLOADED = "unloadedNode.cores";
}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/SimpleCaster.java b/shared/src/main/java/com/inteligr8/alfresco/asie/SimpleCaster.java
new file mode 100644
index 0000000..092e0ce
--- /dev/null
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/SimpleCaster.java
@@ -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 transform(String str, Class returnType) {
+ if (str == null)
+ return null;
+
+ if (returnType.isAssignableFrom(String.class)) {
+ @SuppressWarnings("unchecked")
+ T t = (T) str;
+ return t;
+ }
+
+ try {
+ Constructor 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 invoke(Class 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;
+ }
+
+}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/model/Node.java b/shared/src/main/java/com/inteligr8/alfresco/asie/model/Node.java
deleted file mode 100644
index 92613b7..0000000
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/model/Node.java
+++ /dev/null
@@ -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;
- }
-
-}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/model/RequestParameterSet.java b/shared/src/main/java/com/inteligr8/alfresco/asie/model/RequestParameterSet.java
deleted file mode 100644
index 4c96557..0000000
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/model/RequestParameterSet.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.inteligr8.alfresco.asie.model;
-
-public interface RequestParameterSet {
-
-}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/model/Shard.java b/shared/src/main/java/com/inteligr8/alfresco/asie/model/Shard.java
new file mode 100644
index 0000000..6841050
--- /dev/null
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/model/Shard.java
@@ -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;
+ }
+
+}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardInstance.java b/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardInstance.java
new file mode 100644
index 0000000..53aa456
--- /dev/null
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardInstance.java
@@ -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;
+ }
+
+}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardInstanceState.java b/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardInstanceState.java
new file mode 100644
index 0000000..eb143c2
--- /dev/null
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardInstanceState.java
@@ -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 {
+
+ 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 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();
+ }
+
+}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardSet.java b/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardSet.java
index 348db29..811a810 100644
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardSet.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/model/ShardSet.java
@@ -1,56 +1,194 @@
package com.inteligr8.alfresco.asie.model;
import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
+import java.util.HashSet;
+import java.util.Set;
import java.util.regex.Pattern;
import org.alfresco.repo.index.shard.Floc;
import org.alfresco.repo.index.shard.ShardMethodEnum;
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 {
private static final long serialVersionUID = -8891094367429601316L;
-
- /**
- * Examples:
- *
- * 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 static final String DEFAULT_SOLR_TEMPLATE = "rerank";
- private final ShardMethodEnum method;
- private final boolean hasContent;
- private final Map 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 static ShardSet from(Floc floc, ShardState anyShardState) {
+ return new ShardSet(floc, anyShardState);
}
- public ShardSet(String shardSetSpec) {
- Matcher matcher = shardSetPattern.matcher(shardSetSpec);
- if (!matcher.find())
- throw new IllegalArgumentException("The shard set '" + shardSetSpec + "' is not properly formatted");
-
- this.method = ShardMethodEnum.valueOf(matcher.group(1));
- this.hasContent = ";fulltext".equals(matcher.group(2));
- this.config = new HashMap<>();
- for (int g = 3; g < matcher.groupCount(); g += 3)
- if (matcher.group(g) != null)
- this.config.put("shard." + matcher.group(g+1), matcher.group(g+2));
+ public static ShardSet from(String coreName, String spec) {
+ return new ShardSet(coreName, spec);
+ }
+
+ private final String core;
+ private final ShardMethodEnum method;
+ private final boolean hasContent;
+ private final String template;
+ private final Set storeRefs;
+ private final Short shards;
+ private final Pair 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 propbag = new CompositeMap<>(floc.getPropertyBag(), anyShardNode.getPropertyBag());
+
+ Short shards = null;
+ Pair 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 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 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() {
@@ -61,35 +199,70 @@ public class ShardSet implements Serializable {
return hasContent;
}
+ public String getTemplate() {
+ return template;
+ }
+
+ public Set getStoreRefs() {
+ return storeRefs;
+ }
+
+ public Short getShards() {
+ return shards;
+ }
+
+ public Pair getRange() {
+ return range;
+ }
+
+ public Byte getDateGrouping() {
+ return dateGrouping;
+ }
+
+ public String getPrefixedProperty() {
+ return prefixedProperty;
+ }
+
+ public Pattern getRegex() {
+ return regex;
+ }
+
public String toSpec() {
- StringBuilder spec = new StringBuilder(this.method.toString());
- if (this.hasContent)
- spec.append(";fulltext");
- for (Entry c : this.config.entrySet()) {
- if (!c.getKey().startsWith("shard."))
- continue;
- spec.append(';').append(c.getKey().substring(6)).append(':').append(c.getValue());
- }
- return spec.toString();
- }
-
- public Map getConfig() {
- return config;
- }
-
- public boolean isFor(ShardState shardState) {
- return this.method.equals(shardState.getShardInstance().getShard().getFloc().getShardMethod()) &&
- this.hasContent == shardState.getShardInstance().getShard().getFloc().hasContent() &&
- this.isConfigurationFor(shardState.getPropertyBag());
- }
-
- public boolean isConfigurationFor(Map propertyBag) {
- for (Entry config : this.config.entrySet()) {
- if (config.getValue() == null || !config.getValue().equals(propertyBag.get(config.getKey())))
- return false;
+ if (this.spec == null) {
+ StringBuilder spec = new StringBuilder(this.method.toString());
+ if (this.hasContent)
+ spec.append(";txt");
+ spec.append(";t:").append(this.template);
+ spec.append(";sref:").append(StringUtils.join(this.storeRefs, ','));
+ if (this.shards != null)
+ spec.append(";s:").append(this.shards);
+ if (this.range != null)
+ 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();
}
- return true;
+ return spec;
+ }
+
+ public boolean contains(ShardState shardState) {
+ Floc floc = shardState.getShardInstance().getShard().getFloc();
+ CompositeMap propbag = new CompositeMap<>(shardState.getPropertyBag(), floc.getPropertyBag());
+
+ return this.method.equals(floc.getShardMethod()) &&
+ this.hasContent == floc.hasContent() &&
+ StringUtils.equals(this.template, floc.getTemplate()) &&
+ this.storeRefs.equals(floc.getStoreRefs()) &&
+ this.equals(this.shards, floc.getNumberOfShards()) &&
+ this.equals(this.range, this.strToRange(propbag.get("shard.range"))) &&
+ 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
@@ -98,21 +271,34 @@ public class ShardSet implements Serializable {
return false;
ShardSet shardSet = (ShardSet) obj;
- return this.method.equals(shardSet.method) && this.config.equals(shardSet.config);
+ return this.core.equals(shardSet.core);
+ }
+
+ private boolean equals(Pattern p1, String s2) {
+ s2 = StringUtils.trimToNull(s2);
+ if (p1 == null) {
+ return s2 == null;
+ } else {
+ return p1.pattern().equals(s2);
+ }
+ }
+
+ private boolean equals(T t1, T t2) {
+ if (t1 == null) {
+ return t2 == null;
+ } else {
+ return t1.equals(t2);
+ }
}
@Override
public int hashCode() {
- if (this.hash == null) {
- this.hash = new HashCodeBuilder().append(this.method).append(this.hasContent).append(this.config).build();
- }
-
- return this.hash;
+ return this.core.hashCode();
}
@Override
public String toString() {
- return this.toSpec();
+ return this.core;
}
}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/model/SolrHost.java b/shared/src/main/java/com/inteligr8/alfresco/asie/model/SolrHost.java
new file mode 100644
index 0000000..b935e97
--- /dev/null
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/model/SolrHost.java
@@ -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;
+ }
+
+}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieNodeWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieNodeWebScript.java
index b44ddb5..e40244b 100644
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieNodeWebScript.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieNodeWebScript.java
@@ -1,9 +1,8 @@
package com.inteligr8.alfresco.asie.rest;
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.LoggerFactory;
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.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 {
@@ -36,16 +38,17 @@ public abstract class AbstractAsieNodeWebScript extends AbstractAsieShardableWeb
protected void execute(WebScriptRequest req, WebScriptResponse res, String nodeHostname, int nodePort) throws IOException {
this.logger.trace("execute({}, {})", nodeHostname, nodePort);
-
- Set shardsOnNode = this.sds.findByNode(nodeHostname, nodePort);
+
+ SolrHost node = this.sds.findNode(nodeHostname, nodePort);
+ Map> shardsOnNode = this.sds.findByNode(node);
if (shardsOnNode == null || shardsOnNode.isEmpty())
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 registeredNodeShards) throws IOException {
- this.logger.trace("execute({})", registeredNodeShards.size());
+ protected void execute(WebScriptRequest req, WebScriptResponse res, SolrHost node, Map> shardSetShardStates) throws IOException {
+ this.logger.trace("execute({})", shardSetShardStates.size());
// made to be optionally overridden
}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieShardWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieShardWebScript.java
index 81e672f..00c8deb 100644
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieShardWebScript.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieShardWebScript.java
@@ -1,9 +1,9 @@
package com.inteligr8.alfresco.asie.rest;
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.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -13,7 +13,9 @@ import org.springframework.extensions.webscripts.WebScriptResponse;
import org.springframework.http.HttpStatus;
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 {
@@ -26,21 +28,24 @@ public abstract class AbstractAsieShardWebScript extends AbstractAsieShardableWe
public void executeAuthorized(WebScriptRequest req, WebScriptResponse res) throws IOException {
this.logger.trace("execute()");
- ShardSet shardSet = this.getRequiredPathParameter(req, "shardSet", ShardSet.class);
- this.logger.debug("Parsed shard set: {}", shardSet);
+ String coreName = this.getRequiredPathParameter(req, "shardCore");
int shardId = this.getRequiredPathParameter(req, "shardId", Integer.class);
try {
- Set registeredShardNodes = this.sds.findByShard(shardSet, shardId);
- if (registeredShardNodes == null || registeredShardNodes.isEmpty())
- throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard set or shard could not be found");
+ ShardSet shardSet = this.sds.findSetByCore(coreName);
+ if (shardSet == null)
+ throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard set could not be found");
- this.execute(req, res, registeredShardNodes);
+ List> 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) {
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), iae.getMessage());
}
}
- protected abstract void execute(WebScriptRequest req, WebScriptResponse res, Set registeredShardNodes) throws IOException;
+ protected abstract void execute(WebScriptRequest req, WebScriptResponse res, int shardId, ShardSet shardSet, List> nodeShardStates) throws IOException;
}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieShardableWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieShardableWebScript.java
index a3bf089..2b4d3d7 100644
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieShardableWebScript.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/AbstractAsieShardableWebScript.java
@@ -57,7 +57,7 @@ public abstract class AbstractAsieShardableWebScript extends AbstractAsieWebScri
try {
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);
} catch (NumberFormatException nfe) {
// 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();
switch (sampleType) {
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetBackupNodeWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetBackupNodeWebScript.java
index 800ae7e..ab5c9da 100644
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetBackupNodeWebScript.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetBackupNodeWebScript.java
@@ -1,19 +1,21 @@
package com.inteligr8.alfresco.asie.rest;
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.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
-import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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.spi.ShardDiscoveryService;
@Component(value = "webscript.com.inteligr8.alfresco.asie.backupNode.get")
public class GetBackupNodeWebScript extends AbstractAsieShardWebScript {
@@ -22,15 +24,15 @@ public class GetBackupNodeWebScript extends AbstractAsieShardWebScript {
private ShardBackupService sbs;
@Override
- public void execute(WebScriptRequest req, WebScriptResponse res, Set shardNodes) throws IOException {
- if (shardNodes.isEmpty())
- throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard state could not be found");
-
- Node node = this.sbs.fetchNode(shardNodes);
+ public void execute(WebScriptRequest req, WebScriptResponse res, int shardId, ShardSet shardSet, List> nodeShardStates) throws IOException {
+ Collections.sort(nodeShardStates, new ShardDiscoveryService.ShardedNodeShardStateComparator());
+ SolrHost mostRecentNode = nodeShardStates.iterator().next().getFirst();
+
+ SolrHost backupNode = this.sbs.selectNode(shardSet, shardId, mostRecentNode);
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
res.setContentEncoding("utf-8");
- this.getObjectMapper().writeValue(res.getWriter(), node.getId());
+ this.getObjectMapper().writeValue(res.getWriter(), backupNode.getSpec());
}
}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetLeadNodeWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetLeadNodeWebScript.java
index 60faaec..803dbd8 100644
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetLeadNodeWebScript.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetLeadNodeWebScript.java
@@ -1,10 +1,9 @@
package com.inteligr8.alfresco.asie.rest;
import java.io.IOException;
-import java.util.Set;
+import java.util.List;
-import org.alfresco.repo.index.shard.ShardInstance;
-import org.alfresco.repo.index.shard.ShardState;
+import org.alfresco.util.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
@@ -13,7 +12,9 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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;
@Component(value = "webscript.com.inteligr8.alfresco.asie.leadNode.get")
@@ -23,17 +24,14 @@ public class GetLeadNodeWebScript extends AbstractAsieShardWebScript {
private ShardDiscoveryService sds;
@Override
- public void execute(WebScriptRequest req, WebScriptResponse res, Set shardNodesCache) throws IOException {
- if (shardNodesCache.isEmpty())
- throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard state could not be found");
-
- ShardInstance latestNode = this.sds.computeLeadShard(shardNodesCache);
+ public void execute(WebScriptRequest req, WebScriptResponse res, int shardId, ShardSet shardSet, List> nodeShardStates) throws IOException {
+ SolrHost latestNode = this.sds.computeLeadNode(nodeShardStates);
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.setContentEncoding("utf-8");
- this.getObjectMapper().writeValue(res.getWriter(), new Node(latestNode).getId());
+ this.getObjectMapper().writeValue(res.getWriter(), latestNode.getSpec());
}
}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetNodeWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetNodeWebScript.java
index 3620d31..9d49887 100644
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetNodeWebScript.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetNodeWebScript.java
@@ -1,18 +1,17 @@
package com.inteligr8.alfresco.asie.rest;
import java.io.IOException;
-import java.time.Instant;
-import java.time.OffsetDateTime;
-import java.time.ZoneOffset;
-import java.util.Set;
+import java.util.Map;
+import java.util.Map.Entry;
-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.WebScriptResponse;
import org.springframework.stereotype.Component;
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.NodeShardInfo;
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 {
@Override
- protected void execute(WebScriptRequest req, WebScriptResponse res, Set registeredNodeShards) throws IOException {
- ShardState anyRegisteredNodeShard = registeredNodeShards.iterator().next();
- ShardInstance registeredNode = anyRegisteredNodeShard.getShardInstance();
- int maxShards = registeredNode.getShard().getFloc().getNumberOfShards();
-
+ protected void execute(WebScriptRequest req, WebScriptResponse res, SolrHost node, Map> shardSetShardStates) throws IOException {
SolrShardHashSampleType sampleHashType = this.getOptionalQueryParameter(req, "sampleHashType", SolrShardHashSampleType.class);
- SolrShardHashTable> sampleHashTable = sampleHashType == null ? null : this.createSampleHashTable(sampleHashType, maxShards);
- NodeInfo node = new NodeShardInfo(registeredNode);
-
- for (ShardState registeredNodeShard : registeredNodeShards) {
- ShardInfo shard = new ShardInfo();
- shard.setId(registeredNodeShard.getShardInstance().getShard().getInstance());
- shard.setLatestTx(OffsetDateTime.ofInstant(Instant.ofEpochMilli(registeredNodeShard.getLastIndexedTxCommitTime()), ZoneOffset.UTC));
- shard.setTxsCompleted(registeredNodeShard.getLastIndexedTxId());
-
- shard.setShardSet(new ShardSetInfo(registeredNodeShard.getShardInstance().getShard().getFloc(), registeredNodeShard));
- if (sampleHashTable != null)
- this.addShardHashSamples(shard, sampleHashTable);
-
- node.getShards().put(shard.getId(), shard);
- }
+ NodeInfo nodeResponse = NodeShardInfo.from(node);
+
+ for (Entry> shardSet : shardSetShardStates.entrySet()) {
+ Short maxShards = shardSet.getKey().getShards();
+ SolrShardHashTable> sampleHashTable = null;
+ if (sampleHashType != null && maxShards != null)
+ sampleHashTable = this.createSampleHashTable(sampleHashType, maxShards);
+
+ ShardSetInfo shardSetResponse = ShardSetInfo.from(shardSet.getKey());
+
+ for (Entry shard : shardSet.getValue().entrySet()) {
+ ShardInfo shardResponse = ShardInfo.from(shard.getKey(), shard.getValue());
+ shardResponse.setShardSet(shardSetResponse);
+ if (sampleHashTable != null)
+ this.addShardHashSamples(shardResponse, sampleHashTable);
+
+ nodeResponse.getShards().put(shardResponse.getId(), shardResponse);
+ }
+ }
res.setContentType("application/json");
res.setContentEncoding("utf-8");
- this.getObjectMapper().writeValue(res.getWriter(), node);
+ this.getObjectMapper().writeValue(res.getWriter(), nodeResponse);
}
}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetNodesWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetNodesWebScript.java
index 0e47169..195d229 100644
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetNodesWebScript.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetNodesWebScript.java
@@ -8,6 +8,7 @@ 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.ShardState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,7 +19,9 @@ import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
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.NodeShardInfo;
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);
- Map nodes = new TreeMap<>();
+ Map nodesResponse = new TreeMap<>();
for (Entry>> 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> registeredShards : floc.getValue().entrySet()) {
for (ShardState registeredShardNode : registeredShards.getValue()) {
- String nodeId = new Node(registeredShardNode.getShardInstance()).getId();
- NodeInfo node = nodes.get(nodeId);
- if (node == null) {
- node = new NodeShardInfo(registeredShardNode.getShardInstance());
- nodes.put(node.getId(), node);
+ if (shardSetResponse == null) {
+ ShardSet shardSet = ShardSet.from(floc.getKey(), registeredShardNode);
+ shardSetResponse = ShardSetInfo.from(shardSet);
}
- ShardInfo shard = new ShardInfo(registeredShardNode);
- shard.setShardSet(new ShardSetInfo(floc.getKey(), registeredShardNode));
+ SolrHost node = SolrHost.from(registeredShardNode.getShardInstance());
+ 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)
- this.addShardHashSamples(shard, sampleHashTable);
- node.getShards().put(shard.getId(), shard);
+ this.addShardHashSamples(shardResponse, sampleHashTable);
+ nodeResponse.getShards().put(shardResponse.getId(), shardResponse);
}
}
}
res.setContentType("application/json");
res.setContentEncoding("utf-8");
- this.getObjectMapper().writeValue(res.getWriter(), nodes);
+ this.getObjectMapper().writeValue(res.getWriter(), nodesResponse);
}
}
diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetPropertyHashShardsWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetPropertyHashShardsWebScript.java
index 0139460..7ed169e 100644
--- a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetPropertyHashShardsWebScript.java
+++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/GetPropertyHashShardsWebScript.java
@@ -1,11 +1,7 @@
package com.inteligr8.alfresco.asie.rest;
import java.io.IOException;
-import java.time.Instant;
-import java.time.OffsetDateTime;
-import java.time.ZoneOffset;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -14,10 +10,7 @@ import java.util.Map.Entry;
import java.util.Set;
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.ShardState;
import org.alfresco.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,11 +23,14 @@ import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
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.PropertyHashShardSetInfo;
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
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")
public class GetPropertyHashShardsWebScript extends AbstractAsieShardableWebScript {
@@ -55,19 +51,18 @@ public class GetPropertyHashShardsWebScript extends AbstractAsieShardableWebScri
List values = this.getOptionalQueryParameterAsList(req);
this.validateParameters(min, max, values);
- List shardSets = new LinkedList<>();
-
- Collection>>> flocs = this.sds.findByShardMethod(ShardMethodEnum.PROPERTY);
- if (flocs.isEmpty())
+ List shardSetsResponse = new LinkedList<>();
+
+ Set shardSets = this.sds.findSetsByShardMethod(ShardMethodEnum.PROPERTY);
+ if (shardSets.isEmpty())
throw new WebScriptException(HttpStatus.NO_CONTENT.value(), "There are no property-based shards");
- for (Pair>> floc : flocs) {
- ShardState anyShardNode = this.getAnyShardNode(floc.getSecond());
- PropertyHashShardSetInfo shardSet = new PropertyHashShardSetInfo(floc.getFirst(), anyShardNode);
- shardSet.setShards(new TreeMap<>());
+ for (ShardSet shardSet : shardSets) {
+ PropertyHashShardSetInfo shardSetResponse = PropertyHashShardSetInfo.from(shardSet);
+ shardSetResponse.setShards(new TreeMap<>());
- int maxShards = floc.getFirst().getNumberOfShards();
- SolrShardHashTable> sampleHashTable = this.createSampleHashTable(sampleHashType, maxShards);
+ Short shardCount = shardSet.getShards();
+ SolrShardHashTable> sampleHashTable = this.createSampleHashTable(sampleHashType, shardCount);
Map> shardToHashMap = new HashMap<>();
@@ -83,39 +78,24 @@ public class GetPropertyHashShardsWebScript extends AbstractAsieShardableWebScri
}
}
- for (Entry> shardCache : floc.getSecond().entrySet()) {
- ShardInfo shard = new ShardInfo();
- shard.setId(shardCache.getKey().getInstance());
- shard.setNodes(new HashMap<>());
-
- for (ShardState shardNodeCache : shardCache.getValue()) {
- if (shard.getTxsCompleted() == null || shard.getTxsCompleted().longValue() < shardNodeCache.getLastIndexedTxId()) {
- shard.setLatestTx(OffsetDateTime.ofInstant(Instant.ofEpochMilli(shardNodeCache.getLastIndexedTxCommitTime()), ZoneOffset.UTC));
- shard.setTxsCompleted(shardNodeCache.getLastIndexedTxId());
- }
+ for (Entry> shard : this.sds.findLatestNodeStates(shardSet).entrySet()) {
+ ShardInfo shardResponse = ShardInfo.from(shard.getKey(), shard.getValue().getSecond());
+ shardResponse.setNodes(new HashMap<>());
- NodeInfo node = new ShardNodeInfo(shardNodeCache);
- shard.getNodes().put(node.getId(), node);
- }
+ NodeInfo nodeResponse = ShardNodeInfo.from(shard.getValue().getFirst(), shard.getValue().getSecond());
+ shardResponse.getNodes().put(nodeResponse.getId(), nodeResponse);
- List
+
The following query parameter is supported:
+
+
nodeEndpoint
+
A hostname or hostname:port for the ASIE node; dots are not allowed, you may use _ (underscore) instead
+
shardCore
+
A core name (prefix) for the ASIE shard (e.g. alfresco)
+
shardId
+
A numeric shard ID for the ASIE shard (e.g. 0)
+
+
The following status codes should be expected:
+
+
200
+
OK
+
400
+
The path parameters are invalid
+
404
+
The specified ASIE node/shard could not be found
+
+ ]]>
+
+
+ /inteligr8/asie/node/{nodeEndpoint}/shard/{shardCore}/{shardId}
+
+
+ admin
+
+
+
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/nodeShard.post.desc.xml b/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/nodeShard.post.desc.xml
index a3b3348..b502ed3 100644
--- a/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/nodeShard.post.desc.xml
+++ b/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/nodeShard.post.desc.xml
@@ -2,7 +2,7 @@
xsi:noNamespaceSchemaLocation="https://bitbucket.org/!api/2.0/snippets/inteligr8/AzMgbp/80fdd26a6b3769a63cdc6b54bf1f39e378545cf7/files/snippet.txt">
- Adds ASIE Node to Registry
+ Adds ASIE Node/Shard to RegistryInteligr8 ASIELoads an ASIE shard on a single ASIE node, which will eventually register with ACS.
diff --git a/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/shard.get.desc.xml b/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/shard.get.desc.xml
index b595269..28f19b1 100644
--- a/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/shard.get.desc.xml
+++ b/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/shard.get.desc.xml
@@ -8,12 +8,10 @@
Retrieve meta-data about the specified ASIE shard registered with ACS.
The following path and query parameters are expected or supported:
-
shardSet
-
A shard method combined with its distinguishing properties;
- 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
+
shardCore
+
A core name (prefix) for the ASIE shard (e.g. alfresco)