refactored; split enterprise from generic
This commit is contained in:
parent
ae4f664ba7
commit
dc13bc09de
@ -10,10 +10,10 @@
|
|||||||
<relativePath>../</relativePath>
|
<relativePath>../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>asie-platform-module</artifactId>
|
<artifactId>asie-enterprise-platform-module</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>ASIE Platform Module</name>
|
<name>ASIE Platform Module for ACS Enterprise</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<alfresco.sdk.version>5.2.0</alfresco.sdk.version>
|
<alfresco.sdk.version>5.2.0</alfresco.sdk.version>
|
||||||
@ -30,6 +30,13 @@
|
|||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Provided by cxf-jaxrs-platform-module, but packaged due to shared -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.inteligr8</groupId>
|
||||||
|
<artifactId>common-rest-client</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Provided by cxf-jaxrs-platform-module, but packaged due to solr-api -->
|
<!-- Provided by cxf-jaxrs-platform-module, but packaged due to solr-api -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.ws.rs</groupId>
|
<groupId>jakarta.ws.rs</groupId>
|
||||||
@ -57,8 +64,8 @@
|
|||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.inteligr8.alfresco</groupId>
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
<artifactId>asie-api</artifactId>
|
<artifactId>asie-shared</artifactId>
|
||||||
<version>1.0-SNAPSHOT-asie2</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Needed by this module, but provided by ACS -->
|
<!-- Needed by this module, but provided by ACS -->
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.enterprise;
|
||||||
|
|
||||||
|
public interface EnterpriseConstants {
|
||||||
|
|
||||||
|
static final String BEAN_SHARD_REGISTRY = "search.ShardRegistry";
|
||||||
|
|
||||||
|
static final String ATTR_SHARD_STATE = ".SHARD_STATE";
|
||||||
|
static final String ATTR_SHARD_SUBSCRIPTION = ".SHARD_SUBSCRIPTION";
|
||||||
|
|
||||||
|
}
|
@ -1,16 +1,14 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.bootstrap;
|
package com.inteligr8.alfresco.asie.enterprise.bootstrap;
|
||||||
|
|
||||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
|
||||||
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;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.ApplicationEvent;
|
import org.springframework.context.ApplicationEvent;
|
||||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.Constants;
|
import com.inteligr8.alfresco.asie.spi.ShardStateService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a workaround to a bug with the Alfresco Enterprise Solr purge
|
* This is a workaround to a bug with the Alfresco Enterprise Solr purge
|
||||||
@ -18,28 +16,26 @@ import com.inteligr8.alfresco.asie.Constants;
|
|||||||
* all the fancy stuff and just hard purges the shards.
|
* all the fancy stuff and just hard purges the shards.
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class ShardPurgeService extends AbstractLifecycleBean {
|
public class ShardPurgeOnInitService extends AbstractLifecycleBean {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(Constants.QUALIFIER_ASIE)
|
private ShardStateService sss;
|
||||||
private AttributeService attributeService;
|
|
||||||
|
|
||||||
@Value("${search.solrShardRegistry.purgeOnInit}")
|
@Value("${search.solrShardRegistry.purgeOnInit}")
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onBootstrap(ApplicationEvent event) {
|
protected void onBootstrap(ApplicationEvent event) {
|
||||||
this.logger.info("Using workaround for Alfresco Enterprise Solr ShardRegistry purge");
|
if (this.enabled) {
|
||||||
this.attributeService.removeAttributes(Constants.ATTR_SHARD_STATE);
|
this.logger.debug("Purge on initialization is enabled with 'search.solrShardRegistry.purgeOnInit'");
|
||||||
this.attributeService.removeAttributes(Constants.ATTR_SHARD_SUBSCRIPTION);
|
this.sss.clear();
|
||||||
this.attributeService.removeAttributes(Constants.ATTR_ASIE);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onShutdown(ApplicationEvent event) {
|
protected void onShutdown(ApplicationEvent event) {
|
||||||
// nothing to do
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.enterprise.provider;
|
||||||
|
|
||||||
|
import org.alfresco.repo.index.shard.ShardRegistry;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.asie.Constants;
|
||||||
|
import com.inteligr8.alfresco.asie.enterprise.EnterpriseConstants;
|
||||||
|
import com.inteligr8.alfresco.asie.provider.AbstractProvider;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ShardRegistryProvider extends AbstractProvider<ShardRegistry> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This allows for the selection of the primary or first ShardRegistry
|
||||||
|
* registered in the Spring BeanFactory.
|
||||||
|
*
|
||||||
|
* @return A ShardRegistry.
|
||||||
|
*/
|
||||||
|
@Bean(Constants.BEAN_SHARD_REGISTRY)
|
||||||
|
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||||
|
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||||
|
public ShardRegistry selectBean() {
|
||||||
|
return this.getPrimaryOrNamed(ShardRegistry.class, EnterpriseConstants.BEAN_SHARD_REGISTRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.enterprise.service;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
|
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.AttributeQueryCallback;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
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.enterprise.EnterpriseConstants;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ShardStateService implements com.inteligr8.alfresco.asie.spi.ShardStateService {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||||
|
private AttributeService attrService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier(Constants.BEAN_SHARD_STATE_CACHE)
|
||||||
|
private SimpleCache<ShardInstance, ShardState> shardStateCache;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier(Constants.BEAN_SHARD_GUID_CACHE)
|
||||||
|
private SimpleCache<ShardInstance, String> shardToGuidCache;
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
this.logger.info("Removing all nodes/shards from the shard registry");
|
||||||
|
|
||||||
|
// this clears the state from the backend database
|
||||||
|
this.attrService.removeAttributes(EnterpriseConstants.ATTR_SHARD_STATE);
|
||||||
|
this.attrService.removeAttributes(EnterpriseConstants.ATTR_SHARD_SUBSCRIPTION);
|
||||||
|
this.attrService.removeAttributes(Constants.ATTR_ASIE);
|
||||||
|
|
||||||
|
// this clears the state from Hazelcast
|
||||||
|
this.shardStateCache.clear();
|
||||||
|
this.shardToGuidCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(Serializable... keys) {
|
||||||
|
if (keys.length == 0)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
this.logger.info("Removing from the shard registry: {}", Arrays.toString(keys));
|
||||||
|
|
||||||
|
Serializable[] shardStateKeys = keys;
|
||||||
|
Serializable[] shardSubKeys;
|
||||||
|
if (EnterpriseConstants.ATTR_SHARD_STATE.equals(keys[0])) {
|
||||||
|
shardSubKeys = ArrayUtils.clone(keys);
|
||||||
|
shardSubKeys[0] = EnterpriseConstants.ATTR_SHARD_SUBSCRIPTION;
|
||||||
|
} else {
|
||||||
|
shardStateKeys = ArrayUtils.addFirst(keys, EnterpriseConstants.ATTR_SHARD_STATE);
|
||||||
|
shardSubKeys = ArrayUtils.addFirst(keys, EnterpriseConstants.ATTR_SHARD_SUBSCRIPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShardState shardState = (ShardState) this.attrService.getAttribute(shardStateKeys);
|
||||||
|
|
||||||
|
// this clears the state from the backend database
|
||||||
|
this.attrService.removeAttribute(shardStateKeys);
|
||||||
|
this.attrService.removeAttribute(shardSubKeys);
|
||||||
|
|
||||||
|
// this clears the state from Hazelcast
|
||||||
|
if (shardState != null) {
|
||||||
|
this.shardStateCache.remove(shardState.getShardInstance());
|
||||||
|
this.shardToGuidCache.remove(shardState.getShardInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void iterate(AttributeQueryCallback callback) {
|
||||||
|
this.attrService.getAttributes(callback, EnterpriseConstants.ATTR_SHARD_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
logger.inteligr8-asie.name=com.inteligr8.alfresco.asie.enterprise
|
||||||
|
logger.inteligr8-asie.level=INFO
|
@ -6,10 +6,6 @@
|
|||||||
xmlns:context="http://www.springframework.org/schema/context"
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||||
|
|
||||||
<!-- Enable Spring annotation scanning for classes -->
|
|
||||||
<context:component-scan base-package="com.inteligr8.alfresco.asie"
|
|
||||||
name-generator="org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator" />
|
|
||||||
|
|
||||||
<bean id="search.ShardRegistry" class="org.alfresco.repo.management.subsystems.SubsystemProxyFactory">
|
<bean id="search.ShardRegistry" class="org.alfresco.repo.management.subsystems.SubsystemProxyFactory">
|
||||||
<property name="sourceApplicationContextFactory" ref="Search" />
|
<property name="sourceApplicationContextFactory" ref="Search" />
|
@ -1,13 +0,0 @@
|
|||||||
package com.inteligr8.alfresco.asie;
|
|
||||||
|
|
||||||
public interface Constants {
|
|
||||||
|
|
||||||
static final String QUALIFIER_ASIE = "asie";
|
|
||||||
static final String BEAN_SOLR_ADMIN_CLIENT = "search.SolrAdminClient";
|
|
||||||
static final String BEAN_SHARD_REGISTRY = "search.ShardRegistry";
|
|
||||||
static final String ATTR_SHARD_STATE = ".SHARD_STATE";
|
|
||||||
static final String ATTR_SHARD_SUBSCRIPTION = ".SHARD_SUBSCRIPTION";
|
|
||||||
static final String ATTR_ASIE = "inteligr8.asie";
|
|
||||||
static final String ATTR_UNLOADED_NODE_CORES = "unloadedNode.cores";
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.service;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class ShardAnalysisService {
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.service;
|
|
||||||
|
|
||||||
import org.alfresco.repo.cache.SimpleCache;
|
|
||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
|
||||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
|
||||||
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;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class ShardStateService {
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
@Qualifier(Constants.QUALIFIER_ASIE)
|
|
||||||
private AttributeService attrService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("shardStateCache")
|
|
||||||
private SimpleCache<ShardInstance, ShardState> shardStateCache;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("shardToGuidCache")
|
|
||||||
private SimpleCache<ShardInstance, String> shardToGuidCache;
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
this.logger.info("Removing all nodes/shards from the shard registry");
|
|
||||||
|
|
||||||
// this clears the state from the backend database
|
|
||||||
this.attrService.removeAttribute(Constants.ATTR_SHARD_STATE);
|
|
||||||
this.attrService.removeAttribute(Constants.ATTR_SHARD_SUBSCRIPTION);
|
|
||||||
|
|
||||||
// this clears the state from Hazelcast
|
|
||||||
this.shardStateCache.clear();
|
|
||||||
this.shardToGuidCache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear(String guid) {
|
|
||||||
this.logger.info("Removing node from the shard registry: {}", guid);
|
|
||||||
|
|
||||||
ShardState shardState = (ShardState) this.attrService.getAttribute(Constants.ATTR_SHARD_STATE, guid);
|
|
||||||
|
|
||||||
// this clears the state from the backend database
|
|
||||||
this.attrService.removeAttribute(Constants.ATTR_SHARD_STATE, guid);
|
|
||||||
this.attrService.removeAttribute(Constants.ATTR_SHARD_SUBSCRIPTION, guid);
|
|
||||||
|
|
||||||
// this clears the state from Hazelcast
|
|
||||||
if (shardState != null) {
|
|
||||||
this.shardStateCache.remove(shardState.getShardInstance());
|
|
||||||
this.shardToGuidCache.remove(shardState.getShardInstance());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
# defaulting to 3 days = 60 * 24 * 3 = 4320
|
|
||||||
inteligr8.asie.backup.persistTimeMinutes=4320
|
|
||||||
|
|
||||||
inteligr8.asie.allowedAuthorities=ALFRESCO_ADMINISTRATORS
|
|
||||||
|
|
||||||
# same as solr.baseUrl, but that property is private to the Search subsystem
|
|
||||||
inteligr8.asie.basePath=/solr
|
|
3
pom.xml
3
pom.xml
@ -70,7 +70,8 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module>solr-api</module>
|
<module>solr-api</module>
|
||||||
<module>asie-api</module>
|
<module>asie-api</module>
|
||||||
<module>module</module>
|
<module>shared</module>
|
||||||
|
<module>enterprise-module</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
12
shared/.gitignore
vendored
Normal file
12
shared/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Maven
|
||||||
|
target
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
|
||||||
|
# Eclipse
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.settings
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# IDEA
|
||||||
|
/.idea/
|
1
shared/README.md
Normal file
1
shared/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# ASIE Platform Module Library
|
73
shared/pom.xml
Normal file
73
shared/pom.xml
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
|
<artifactId>asie-platform-module-parent</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>asie-shared</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>ASIE Shared Library for Platform Modules</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<alfresco.sdk.version>5.2.0</alfresco.sdk.version>
|
||||||
|
<alfresco.platform.version>23.3.0</alfresco.platform.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.alfresco</groupId>
|
||||||
|
<artifactId>acs-community-packaging</artifactId>
|
||||||
|
<version>${alfresco.platform.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
|
<artifactId>asie-api</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT-asie2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.inteligr8</groupId>
|
||||||
|
<artifactId>common-rest-client</artifactId>
|
||||||
|
<version>3.0.1-cxf</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Needed by this module, but provided by ACS -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.alfresco</groupId>
|
||||||
|
<artifactId>alfresco-repository</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Including for testing purposes only -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>alfresco-public</id>
|
||||||
|
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
</project>
|
74
shared/rad.ps1
Normal file
74
shared/rad.ps1
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
|
||||||
|
function discoverArtifactId {
|
||||||
|
$script:ARTIFACT_ID=(mvn -q -Dexpression=project"."artifactId -DforceStdout help:evaluate)
|
||||||
|
}
|
||||||
|
|
||||||
|
function rebuild {
|
||||||
|
echo "Rebuilding project ..."
|
||||||
|
mvn process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
function start_ {
|
||||||
|
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||||
|
mvn -Drad process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
function start_log {
|
||||||
|
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||||
|
mvn -Drad "-Ddocker.showLogs" process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop_ {
|
||||||
|
discoverArtifactId
|
||||||
|
echo "Stopping Docker containers that supported rapid application development ..."
|
||||||
|
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||||
|
echo "Stopping containers ..."
|
||||||
|
docker container stop (docker container ls -q --filter name=${ARTIFACT_ID}-*)
|
||||||
|
echo "Removing containers ..."
|
||||||
|
docker container rm (docker container ls -aq --filter name=${ARTIFACT_ID}-*)
|
||||||
|
}
|
||||||
|
|
||||||
|
function tail_logs {
|
||||||
|
param (
|
||||||
|
$container
|
||||||
|
)
|
||||||
|
|
||||||
|
discoverArtifactId
|
||||||
|
docker container logs -f (docker container ls -q --filter name=${ARTIFACT_ID}-${container})
|
||||||
|
}
|
||||||
|
|
||||||
|
function list {
|
||||||
|
discoverArtifactId
|
||||||
|
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($args[0]) {
|
||||||
|
"start" {
|
||||||
|
start_
|
||||||
|
}
|
||||||
|
"start_log" {
|
||||||
|
start_log
|
||||||
|
}
|
||||||
|
"stop" {
|
||||||
|
stop_
|
||||||
|
}
|
||||||
|
"restart" {
|
||||||
|
stop_
|
||||||
|
start_
|
||||||
|
}
|
||||||
|
"rebuild" {
|
||||||
|
rebuild
|
||||||
|
}
|
||||||
|
"tail" {
|
||||||
|
tail_logs $args[1]
|
||||||
|
}
|
||||||
|
"containers" {
|
||||||
|
list
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
echo "Usage: .\rad.ps1 [ start | start_log | stop | restart | rebuild | tail {container} | containers ]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Completed!"
|
||||||
|
|
71
shared/rad.sh
Normal file
71
shared/rad.sh
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
discoverArtifactId() {
|
||||||
|
ARTIFACT_ID=`mvn -q -Dexpression=project.artifactId -DforceStdout help:evaluate`
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuild() {
|
||||||
|
echo "Rebuilding project ..."
|
||||||
|
mvn process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||||
|
mvn -Drad process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
start_log() {
|
||||||
|
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||||
|
mvn -Drad -Ddocker.showLogs process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
discoverArtifactId
|
||||||
|
echo "Stopping Docker containers that supported rapid application development ..."
|
||||||
|
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||||
|
echo "Stopping containers ..."
|
||||||
|
docker container stop `docker container ls -q --filter name=${ARTIFACT_ID}-*`
|
||||||
|
echo "Removing containers ..."
|
||||||
|
docker container rm `docker container ls -aq --filter name=${ARTIFACT_ID}-*`
|
||||||
|
}
|
||||||
|
|
||||||
|
tail_logs() {
|
||||||
|
discoverArtifactId
|
||||||
|
docker container logs -f `docker container ls -q --filter name=${ARTIFACT_ID}-$1`
|
||||||
|
}
|
||||||
|
|
||||||
|
list() {
|
||||||
|
discoverArtifactId
|
||||||
|
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
start_log)
|
||||||
|
start_log
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
rebuild)
|
||||||
|
rebuild
|
||||||
|
;;
|
||||||
|
tail)
|
||||||
|
tail_logs $2
|
||||||
|
;;
|
||||||
|
containers)
|
||||||
|
list
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: ./rad.sh [ start | start_log | stop | restart | rebuild | tail {container} | containers ]"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "Completed!"
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.inteligr8.alfresco.asie;
|
||||||
|
|
||||||
|
public interface Constants {
|
||||||
|
|
||||||
|
static final String QUALIFIER_ASIE = "asie";
|
||||||
|
|
||||||
|
// 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_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_NODES = "inteligr8.asie.nodes";
|
||||||
|
static final String ATTR_STATE = "state";
|
||||||
|
static final String ATTR_ONLINE = "online";
|
||||||
|
static final String ATTR_UNLOADED = "unloadedNode.cores";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
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,6 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.model;
|
package com.inteligr8.alfresco.asie.model;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.model.NodeParameterSet;
|
|
||||||
|
|
||||||
public class NodeShardParameterSet extends NodeParameterSet {
|
public class NodeShardParameterSet extends NodeParameterSet {
|
||||||
|
|
@ -1,6 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.model;
|
package com.inteligr8.alfresco.asie.model;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.model.RequestParameterSet;
|
|
||||||
|
|
||||||
public class ShardParameterSet implements RequestParameterSet {
|
public class ShardParameterSet implements RequestParameterSet {
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.model;
|
package com.inteligr8.alfresco.asie.model;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.provider;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
public abstract class AbstractProvider<T> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext context;
|
||||||
|
|
||||||
|
public abstract T selectBean();
|
||||||
|
|
||||||
|
protected <U extends T> U getPrimaryOrNamed(Class<U> type, String beanName) {
|
||||||
|
ObjectProvider<U> provider = this.context.getBeanProvider(type);
|
||||||
|
|
||||||
|
// this will select the primary or if there is just one impl, that one impl
|
||||||
|
U u = provider.getIfUnique();
|
||||||
|
if (u == null) {
|
||||||
|
// this will select the named bean; throwing exception if there is none
|
||||||
|
u = this.context.getBean(beanName, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <U extends T> U getPrimary(Class<U> type) {
|
||||||
|
ObjectProvider<U> provider = this.context.getBeanProvider(type);
|
||||||
|
|
||||||
|
// this will select the primary or if there is just one impl, that one impl
|
||||||
|
return provider.getObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,8 @@
|
|||||||
package com.inteligr8.alfresco.asie.provider;
|
package com.inteligr8.alfresco.asie.provider;
|
||||||
|
|
||||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
@ -13,10 +10,7 @@ import org.springframework.context.annotation.Scope;
|
|||||||
import com.inteligr8.alfresco.asie.Constants;
|
import com.inteligr8.alfresco.asie.Constants;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class AttributeServiceProvider {
|
public class AttributeServiceProvider extends AbstractProvider<AttributeService> {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ApplicationContext context;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This allows for the selection of the primary or first AttributeService
|
* This allows for the selection of the primary or first AttributeService
|
||||||
@ -27,24 +21,11 @@ public class AttributeServiceProvider {
|
|||||||
*
|
*
|
||||||
* @return An AttributeService.
|
* @return An AttributeService.
|
||||||
*/
|
*/
|
||||||
@Bean("asieAttributeService")
|
@Bean(Constants.BEAN_ATTRIBUTE_SERVICE)
|
||||||
@Qualifier(Constants.QUALIFIER_ASIE)
|
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||||
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
|
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||||
public AttributeService selectAttributeService() {
|
public AttributeService selectBean() {
|
||||||
return this.getPrimaryOrNamed(AttributeService.class, "attributeService");
|
return this.getPrimaryOrNamed(AttributeService.class, "attributeService");
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T getPrimaryOrNamed(Class<T> type, String beanName) {
|
|
||||||
ObjectProvider<T> provider = this.context.getBeanProvider(type);
|
|
||||||
|
|
||||||
// this will select the primary or if there is just one impl, that one impl
|
|
||||||
T t = provider.getIfUnique();
|
|
||||||
if (t == null) {
|
|
||||||
// this will select the named bean; throwing exception if there is none
|
|
||||||
t = this.context.getBean(beanName, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ import com.inteligr8.alfresco.asie.Constants;
|
|||||||
@Configuration
|
@Configuration
|
||||||
public class ObjectMapperProvider {
|
public class ObjectMapperProvider {
|
||||||
|
|
||||||
@Bean("asieObjectMapper")
|
@Bean(Constants.BEAN_OBJECT_MAPPER)
|
||||||
@Qualifier(Constants.QUALIFIER_ASIE)
|
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||||
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
|
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||||
public ObjectMapper createObjectMapper() {
|
public ObjectMapper createObjectMapper() {
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -7,9 +7,9 @@ import org.slf4j.LoggerFactory;
|
|||||||
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 com.inteligr8.alfresco.asie.enterprise.model.ShardSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
|
||||||
public abstract class AbstractAsieNodeShardWebScript extends AbstractAsieEnterpriseWebScript {
|
public abstract class AbstractAsieNodeShardWebScript extends AbstractAsieShardableWebScript {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -12,9 +12,9 @@ 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.enterprise.service.ShardDiscoveryService;
|
import com.inteligr8.alfresco.asie.service.ShardDiscoveryService;
|
||||||
|
|
||||||
public abstract class AbstractAsieNodeWebScript extends AbstractAsieEnterpriseWebScript {
|
public abstract class AbstractAsieNodeWebScript extends AbstractAsieShardableWebScript {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -12,10 +12,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.enterprise.model.ShardSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.service.ShardDiscoveryService;
|
import com.inteligr8.alfresco.asie.service.ShardDiscoveryService;
|
||||||
|
|
||||||
public abstract class AbstractAsieShardWebScript extends AbstractAsieEnterpriseWebScript {
|
public abstract class AbstractAsieShardWebScript extends AbstractAsieShardableWebScript {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
@ -24,12 +24,11 @@ import com.inteligr8.alfresco.asie.api.CoreAdminApi;
|
|||||||
import com.inteligr8.alfresco.asie.compute.SolrShardEnumeratedHashTable;
|
import com.inteligr8.alfresco.asie.compute.SolrShardEnumeratedHashTable;
|
||||||
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
||||||
import com.inteligr8.alfresco.asie.compute.SolrShardNumericHashTable;
|
import com.inteligr8.alfresco.asie.compute.SolrShardNumericHashTable;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardSetInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardSetInfo;
|
||||||
import com.inteligr8.alfresco.asie.rest.AbstractAsieWebScript;
|
|
||||||
import com.inteligr8.alfresco.asie.service.SolrShardHashService;
|
import com.inteligr8.alfresco.asie.service.SolrShardHashService;
|
||||||
|
|
||||||
public abstract class AbstractAsieEnterpriseWebScript extends AbstractAsieWebScript {
|
public abstract class AbstractAsieShardableWebScript extends AbstractAsieWebScript {
|
||||||
|
|
||||||
private final Pattern sampleTypePattern = Pattern.compile("([A-Za-z]+)([0-9]+)");
|
private final Pattern sampleTypePattern = Pattern.compile("([A-Za-z]+)([0-9]+)");
|
||||||
|
|
||||||
@ -41,7 +40,7 @@ public abstract class AbstractAsieEnterpriseWebScript extends AbstractAsieWebScr
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(Constants.BEAN_SHARD_REGISTRY)
|
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||||
private ShardRegistry shardRegistry;
|
private ShardRegistry shardRegistry;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
@ -1,13 +1,9 @@
|
|||||||
package com.inteligr8.alfresco.asie.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -15,12 +11,7 @@ import org.springframework.beans.factory.InitializingBean;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.extensions.webscripts.AbstractWebScript;
|
|
||||||
import org.springframework.extensions.webscripts.Description.RequiredAuthentication;
|
|
||||||
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.http.HttpStatus;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.inteligr8.alfresco.asie.Constants;
|
import com.inteligr8.alfresco.asie.Constants;
|
||||||
@ -31,7 +22,6 @@ import com.inteligr8.rs.ClientCxfConfiguration;
|
|||||||
import com.inteligr8.rs.ClientCxfImpl;
|
import com.inteligr8.rs.ClientCxfImpl;
|
||||||
|
|
||||||
import jakarta.ws.rs.client.ClientRequestContext;
|
import jakarta.ws.rs.client.ClientRequestContext;
|
||||||
import net.sf.acegisecurity.GrantedAuthority;
|
|
||||||
|
|
||||||
public abstract class AbstractAsieWebScript extends AbstractWebScript implements InitializingBean {
|
public abstract class AbstractAsieWebScript extends AbstractWebScript implements InitializingBean {
|
||||||
|
|
||||||
@ -81,30 +71,12 @@ public abstract class AbstractAsieWebScript extends AbstractWebScript implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void execute(WebScriptRequest request, WebScriptResponse response) throws IOException {
|
protected Set<String> getAuthorities() {
|
||||||
if (RequiredAuthentication.user.equals(this.getDescription().getRequiredAuthentication())) {
|
return this.authorizedAuthorities;
|
||||||
if (!this.isAuthorized())
|
|
||||||
throw new WebScriptException(HttpStatus.FORBIDDEN.value(), "You are not authorized for access this resource.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.executeAuthorized(request, response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAuthorized() {
|
|
||||||
if (this.authorizedAuthorities.contains(AuthenticationUtil.getFullyAuthenticatedUser()))
|
|
||||||
return true;
|
|
||||||
for (GrantedAuthority auth : AuthenticationUtil.getFullAuthentication().getAuthorities()) {
|
|
||||||
if (this.authorizedAuthorities.contains(auth.getAuthority()))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void executeAuthorized(WebScriptRequest request, WebScriptResponse response) throws IOException;
|
|
||||||
|
|
||||||
public ObjectMapper getObjectMapper() {
|
protected ObjectMapper getObjectMapper() {
|
||||||
return objectMapper;
|
return this.objectMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CoreAdminApi createApi(String hostname, int port) {
|
protected CoreAdminApi createApi(String hostname, int port) {
|
||||||
@ -164,64 +136,5 @@ public abstract class AbstractAsieWebScript extends AbstractWebScript implements
|
|||||||
client.register();
|
client.register();
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getRequiredPathParameter(WebScriptRequest req, String pathParamName) {
|
|
||||||
String pathParamValue = this.getOptionalPathParameter(req, pathParamName);
|
|
||||||
if (pathParamValue == null)
|
|
||||||
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "The '" + pathParamName + "' path parameter is required");
|
|
||||||
return pathParamValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T> T getRequiredPathParameter(WebScriptRequest req, String pathParamName, Class<T> type) {
|
|
||||||
T pathParamValue = this.getOptionalPathParameter(req, pathParamName, type);
|
|
||||||
if (pathParamValue == null)
|
|
||||||
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "The '" + pathParamName + "' path parameter is required");
|
|
||||||
return pathParamValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getOptionalPathParameter(WebScriptRequest req, String pathParamName) {
|
|
||||||
return StringUtils.trimToNull(req.getServiceMatch().getTemplateVars().get(pathParamName));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T> T getOptionalPathParameter(WebScriptRequest req, String pathParamName, Class<T> type) {
|
|
||||||
String str = StringUtils.trimToNull(req.getServiceMatch().getTemplateVars().get(pathParamName));
|
|
||||||
return this.getOptionalParameter(req, pathParamName, str, "path element", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getOptionalQueryParameter(WebScriptRequest req, String queryParamName) {
|
|
||||||
return StringUtils.trimToNull(req.getParameter(queryParamName));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T> T getOptionalQueryParameter(WebScriptRequest req, String queryParamName, Class<T> type) {
|
|
||||||
String str = StringUtils.trimToNull(req.getParameter(queryParamName));
|
|
||||||
return this.getOptionalParameter(req, queryParamName, str, "query parameter", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T> T getOptionalParameter(WebScriptRequest req, String paramName, String paramValue, String paramTypeDisplay, Class<T> type) {
|
|
||||||
if (paramValue == null)
|
|
||||||
return null;
|
|
||||||
if (type.equals(String.class))
|
|
||||||
return type.cast(paramValue);
|
|
||||||
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
Constructor<T> constructor = type.getConstructor(String.class);
|
|
||||||
return constructor.newInstance(paramValue);
|
|
||||||
} catch (NoSuchMethodException nsme) {
|
|
||||||
Method method = type.getDeclaredMethod("valueOf", String.class);
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T t = (T) method.invoke(null, paramValue);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
} catch (InvocationTargetException ite) {
|
|
||||||
if (ite.getTargetException() instanceof NumberFormatException) {
|
|
||||||
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "The `" + paramName + "` " + paramTypeDisplay + " '" + paramValue + "' must be a number");
|
|
||||||
} else {
|
|
||||||
throw new WebScriptException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An unexpected issue occurred", ite);
|
|
||||||
}
|
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) {
|
|
||||||
throw new WebScriptException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An unexpected issue occurred", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,16 +1,18 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
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;
|
||||||
|
import org.apache.commons.lang3.tuple.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;
|
||||||
@ -22,10 +24,9 @@ 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.enterprise.service.ShardBackupService;
|
|
||||||
import com.inteligr8.alfresco.asie.enterprise.service.ShardStateService;
|
|
||||||
import com.inteligr8.alfresco.asie.model.NodeParameterSet;
|
import com.inteligr8.alfresco.asie.model.NodeParameterSet;
|
||||||
import com.inteligr8.alfresco.asie.model.core.DisableIndexingRequest;
|
import com.inteligr8.alfresco.asie.service.ShardBackupService;
|
||||||
|
import com.inteligr8.alfresco.asie.spi.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;
|
||||||
@ -52,7 +53,7 @@ public abstract class AbstractUnregisterNodeWebScript<T extends NodeParameterSet
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
T params = this.createParameters(req, nodeHostname, nodePort);
|
T params = this.createParameters(req, nodeHostname, nodePort);
|
||||||
|
|
||||||
final Map<String, ShardState> guidCores = new HashMap<>();
|
final List<Pair<Serializable[], ShardState>> matchingCores = new LinkedList<>();
|
||||||
|
|
||||||
AttributeQueryCallback callback = new AttributeQueryCallback() {
|
AttributeQueryCallback callback = new AttributeQueryCallback() {
|
||||||
@Override
|
@Override
|
||||||
@ -61,17 +62,16 @@ public abstract class AbstractUnregisterNodeWebScript<T extends NodeParameterSet
|
|||||||
if (!matches(params, shardState))
|
if (!matches(params, shardState))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
String guid = (String) keys[1];
|
matchingCores.add(Pair.of(keys, shardState));
|
||||||
guidCores.put(guid, shardState);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.attrService.getAttributes(callback, Constants.ATTR_SHARD_STATE);
|
this.sss.iterate(callback);
|
||||||
|
|
||||||
Serializable[] keys = new String[] {
|
Serializable[] keys = new String[] {
|
||||||
Constants.ATTR_ASIE,
|
Constants.ATTR_ASIE,
|
||||||
Constants.ATTR_UNLOADED_NODE_CORES,
|
Constants.ATTR_UNLOADED,
|
||||||
nodeHostname + ":" + nodePort
|
nodeHostname + ":" + nodePort
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -80,8 +80,8 @@ public abstract class AbstractUnregisterNodeWebScript<T extends NodeParameterSet
|
|||||||
if (cores == null)
|
if (cores == null)
|
||||||
cores = new HashMap<>();
|
cores = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
for (Entry<String, ShardState> guidCore : guidCores.entrySet()) {
|
for (Pair<Serializable[], ShardState> matchingCore : matchingCores) {
|
||||||
ShardState shardNode = guidCore.getValue();
|
ShardState shardNode = matchingCore.getValue();
|
||||||
String core = shardNode.getPropertyBag().get("coreName");
|
String core = shardNode.getPropertyBag().get("coreName");
|
||||||
|
|
||||||
StatusResponse status = this.getCoreStatus(nodeHostname, nodePort, core);
|
StatusResponse status = this.getCoreStatus(nodeHostname, nodePort, core);
|
||||||
@ -90,14 +90,13 @@ public abstract class AbstractUnregisterNodeWebScript<T extends NodeParameterSet
|
|||||||
CoreMetadata coreMetadata = status.getStatus().getCores().get(core);
|
CoreMetadata coreMetadata = status.getStatus().getCores().get(core);
|
||||||
if (coreMetadata == null || coreMetadata.getName() == null) {
|
if (coreMetadata == null || coreMetadata.getName() == null) {
|
||||||
this.logger.warn("Registered core does not actually exist on the node host; could be a DNS issue: {}:{}/solr/{}", nodeHostname, nodePort, core);
|
this.logger.warn("Registered core does not actually exist on the node host; could be a DNS issue: {}:{}/solr/{}", nodeHostname, nodePort, core);
|
||||||
continue;
|
} else {
|
||||||
|
this.unloadCore(nodeHostname, nodePort, core);
|
||||||
|
cores.put(core, coreMetadata.getInstancePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.unloadCore(nodeHostname, nodePort, core);
|
this.sss.remove(matchingCore.getKey());
|
||||||
cores.put(core, coreMetadata.getInstancePath());
|
this.sbs.forget(shardNode);
|
||||||
|
|
||||||
String guid = guidCore.getKey();
|
|
||||||
this.removeShard(guid, shardNode);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// FIXME maybe a separate tx?
|
// FIXME maybe a separate tx?
|
||||||
@ -143,22 +142,5 @@ public abstract class AbstractUnregisterNodeWebScript<T extends NodeParameterSet
|
|||||||
CoreAdminApi api = this.createApi(nodeHostname, nodePort);
|
CoreAdminApi api = this.createApi(nodeHostname, nodePort);
|
||||||
api.unload(new UnloadRequest().withCore(core));
|
api.unload(new UnloadRequest().withCore(core));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void disableIndexing(String nodeHostname, int nodePort) {
|
|
||||||
this.logger.info("Disabling indexing on ASIE node: {}", nodeHostname);
|
|
||||||
CoreAdminApi api = this.createApi(nodeHostname, nodePort);
|
|
||||||
api.disableIndexing(new DisableIndexingRequest());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void disableCoreIndexing(String nodeHostname, int nodePort, String core) {
|
|
||||||
this.logger.info("Disabling indexing on ASIE node/core: {}/{}", nodeHostname, core);
|
|
||||||
CoreAdminApi api = this.createApi(nodeHostname, nodePort);
|
|
||||||
api.disableIndexing(new DisableIndexingRequest().withCore(core));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removeShard(String guid, ShardState shardNode) {
|
|
||||||
this.sss.clear(guid);
|
|
||||||
this.sbs.forget(shardNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.extensions.webscripts.Description.RequiredAuthentication;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.GrantedAuthority;
|
||||||
|
|
||||||
|
public abstract class AbstractWebScript extends org.springframework.extensions.webscripts.AbstractWebScript {
|
||||||
|
|
||||||
|
protected abstract Set<String> getAuthorities();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void execute(WebScriptRequest request, WebScriptResponse response) throws IOException {
|
||||||
|
if (RequiredAuthentication.user.equals(this.getDescription().getRequiredAuthentication())) {
|
||||||
|
if (!this.isAuthorized())
|
||||||
|
throw new WebScriptException(HttpStatus.FORBIDDEN.value(), "You are not authorized for access this resource.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.executeAuthorized(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isAuthorized() {
|
||||||
|
if (this.getAuthorities().contains(AuthenticationUtil.getFullyAuthenticatedUser()))
|
||||||
|
return true;
|
||||||
|
for (GrantedAuthority auth : AuthenticationUtil.getFullAuthentication().getAuthorities()) {
|
||||||
|
if (this.getAuthorities().contains(auth.getAuthority()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void executeAuthorized(WebScriptRequest request, WebScriptResponse response) throws IOException;
|
||||||
|
|
||||||
|
protected String getRequiredPathParameter(WebScriptRequest req, String pathParamName) {
|
||||||
|
String pathParamValue = this.getOptionalPathParameter(req, pathParamName);
|
||||||
|
if (pathParamValue == null)
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "The '" + pathParamName + "' path parameter is required");
|
||||||
|
return pathParamValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> T getRequiredPathParameter(WebScriptRequest req, String pathParamName, Class<T> type) {
|
||||||
|
T pathParamValue = this.getOptionalPathParameter(req, pathParamName, type);
|
||||||
|
if (pathParamValue == null)
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "The '" + pathParamName + "' path parameter is required");
|
||||||
|
return pathParamValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getOptionalPathParameter(WebScriptRequest req, String pathParamName) {
|
||||||
|
return StringUtils.trimToNull(req.getServiceMatch().getTemplateVars().get(pathParamName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> T getOptionalPathParameter(WebScriptRequest req, String pathParamName, Class<T> type) {
|
||||||
|
String str = StringUtils.trimToNull(req.getServiceMatch().getTemplateVars().get(pathParamName));
|
||||||
|
return this.getOptionalParameter(req, pathParamName, str, "path element", type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getOptionalQueryParameter(WebScriptRequest req, String queryParamName) {
|
||||||
|
return StringUtils.trimToNull(req.getParameter(queryParamName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> T getOptionalQueryParameter(WebScriptRequest req, String queryParamName, Class<T> type) {
|
||||||
|
String str = StringUtils.trimToNull(req.getParameter(queryParamName));
|
||||||
|
return this.getOptionalParameter(req, queryParamName, str, "query parameter", type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> T getOptionalParameter(WebScriptRequest req, String paramName, String paramValue, String paramTypeDisplay, Class<T> type) {
|
||||||
|
if (paramValue == null)
|
||||||
|
return null;
|
||||||
|
if (type.equals(String.class))
|
||||||
|
return type.cast(paramValue);
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
Constructor<T> constructor = type.getConstructor(String.class);
|
||||||
|
return constructor.newInstance(paramValue);
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
Method method = type.getDeclaredMethod("valueOf", String.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T t = (T) method.invoke(null, paramValue);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
} catch (InvocationTargetException ite) {
|
||||||
|
if (ite.getTargetException() instanceof NumberFormatException) {
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "The `" + paramName + "` " + paramTypeDisplay + " '" + paramValue + "' must be a number");
|
||||||
|
} else {
|
||||||
|
throw new WebScriptException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An unexpected issue occurred", ite);
|
||||||
|
}
|
||||||
|
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) {
|
||||||
|
throw new WebScriptException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An unexpected issue occurred", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -9,10 +9,10 @@ import org.springframework.extensions.webscripts.WebScriptResponse;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.asie.enterprise.service.ShardBackupService;
|
import com.inteligr8.alfresco.asie.service.ShardBackupService;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.service.ShardStateService;
|
import com.inteligr8.alfresco.asie.spi.ShardStateService;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.registry.delete")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.registry.delete")
|
||||||
public class ClearRegistryWebScript extends AbstractWebScript {
|
public class ClearRegistryWebScript extends AbstractWebScript {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -12,9 +12,10 @@ 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.enterprise.service.ShardBackupService;
|
import com.inteligr8.alfresco.asie.model.Node;
|
||||||
|
import com.inteligr8.alfresco.asie.service.ShardBackupService;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.backupNode.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.backupNode.get")
|
||||||
public class GetBackupNodeWebScript extends AbstractAsieShardWebScript {
|
public class GetBackupNodeWebScript extends AbstractAsieShardWebScript {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -25,11 +26,11 @@ public class GetBackupNodeWebScript extends AbstractAsieShardWebScript {
|
|||||||
if (shardNodes.isEmpty())
|
if (shardNodes.isEmpty())
|
||||||
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard state could not be found");
|
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard state could not be found");
|
||||||
|
|
||||||
String nodeId = this.sbs.fetchNodeId(shardNodes);
|
Node node = this.sbs.fetchNode(shardNodes);
|
||||||
|
|
||||||
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(), nodeId);
|
this.getObjectMapper().writeValue(res.getWriter(), node.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -13,27 +13,27 @@ 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.enterprise.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.model.Node;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.service.ShardAnalysisService;
|
import com.inteligr8.alfresco.asie.spi.ShardDiscoveryService;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.leadNode.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.leadNode.get")
|
||||||
public class GetLeadNodeWebScript extends AbstractAsieShardWebScript {
|
public class GetLeadNodeWebScript extends AbstractAsieShardWebScript {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ShardAnalysisService sas;
|
private ShardDiscoveryService sds;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(WebScriptRequest req, WebScriptResponse res, Set<ShardState> shardNodesCache) throws IOException {
|
public void execute(WebScriptRequest req, WebScriptResponse res, Set<ShardState> shardNodesCache) throws IOException {
|
||||||
if (shardNodesCache.isEmpty())
|
if (shardNodesCache.isEmpty())
|
||||||
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard state could not be found");
|
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The ASIE shard state could not be found");
|
||||||
|
|
||||||
ShardInstance latestNode = this.sas.computeLeadShard(shardNodesCache);
|
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 shard state 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(), NodeInfo.determineId(latestNode));
|
this.getObjectMapper().writeValue(res.getWriter(), new Node(latestNode).getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@ -13,12 +13,12 @@ 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.enterprise.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.NodeShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardSetInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardSetInfo;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.node.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.node.get")
|
||||||
public class GetNodeWebScript extends AbstractAsieNodeWebScript {
|
public class GetNodeWebScript extends AbstractAsieNodeWebScript {
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -18,13 +18,14 @@ 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.enterprise.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.model.Node;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.NodeShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardSetInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
|
import com.inteligr8.alfresco.asie.rest.model.ShardSetInfo;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.nodes.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.nodes.get")
|
||||||
public class GetNodesWebScript extends AbstractAsieEnterpriseWebScript {
|
public class GetNodesWebScript extends AbstractAsieShardableWebScript {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
@ -47,7 +48,8 @@ public class GetNodesWebScript extends AbstractAsieEnterpriseWebScript {
|
|||||||
|
|
||||||
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()) {
|
||||||
NodeInfo node = nodes.get(NodeInfo.determineId(registeredShardNode.getShardInstance()));
|
String nodeId = new Node(registeredShardNode.getShardInstance()).getId();
|
||||||
|
NodeInfo node = nodes.get(nodeId);
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
node = new NodeShardInfo(registeredShardNode.getShardInstance());
|
node = new NodeShardInfo(registeredShardNode.getShardInstance());
|
||||||
nodes.put(node.getId(), node);
|
nodes.put(node.getId(), node);
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@ -30,14 +30,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.enterprise.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.PropertyHashShardSetInfo;
|
import com.inteligr8.alfresco.asie.rest.model.PropertyHashShardSetInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardNodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardNodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.service.ShardDiscoveryService;
|
import com.inteligr8.alfresco.asie.service.ShardDiscoveryService;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.propertyHashShards.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.propertyHashShards.get")
|
||||||
public class GetPropertyHashShardsWebScript extends AbstractAsieEnterpriseWebScript {
|
public class GetPropertyHashShardsWebScript extends AbstractAsieShardableWebScript {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -24,8 +24,8 @@ import com.inteligr8.alfresco.asie.compute.SolrShardHashTable;
|
|||||||
import com.inteligr8.alfresco.asie.compute.SolrShardNumericHashTable;
|
import com.inteligr8.alfresco.asie.compute.SolrShardNumericHashTable;
|
||||||
import com.inteligr8.alfresco.asie.service.SolrShardHashService;
|
import com.inteligr8.alfresco.asie.service.SolrShardHashService;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.sampleHashes.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.sampleHashes.get")
|
||||||
public class GetSampleHashesWebScript extends AbstractAsieEnterpriseWebScript {
|
public class GetSampleHashesWebScript extends AbstractAsieShardableWebScript {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@ -15,12 +15,12 @@ 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.enterprise.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardNodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardNodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardSetInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardSetInfo;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.shard.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.shard.get")
|
||||||
public class GetShardWebScript extends AbstractAsieShardWebScript {
|
public class GetShardWebScript extends AbstractAsieShardWebScript {
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@ -22,13 +22,13 @@ 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.enterprise.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.NodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardNodeInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardNodeInfo;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.rest.model.ShardSetInfo;
|
import com.inteligr8.alfresco.asie.rest.model.ShardSetInfo;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.shards.get")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.shards.get")
|
||||||
public class GetShardsWebScript extends AbstractAsieEnterpriseWebScript {
|
public class GetShardsWebScript extends AbstractAsieShardableWebScript {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -28,7 +28,7 @@ import com.inteligr8.solr.model.core.ReloadRequest;
|
|||||||
import jakarta.ws.rs.BadRequestException;
|
import jakarta.ws.rs.BadRequestException;
|
||||||
import jakarta.ws.rs.InternalServerErrorException;
|
import jakarta.ws.rs.InternalServerErrorException;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.nodeShard.post")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.nodeShard.post")
|
||||||
public class ReloadNodeShardWebScript extends AbstractAsieNodeWebScript {
|
public class ReloadNodeShardWebScript extends AbstractAsieNodeWebScript {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
@ -47,7 +47,7 @@ public class ReloadNodeShardWebScript extends AbstractAsieNodeWebScript {
|
|||||||
|
|
||||||
Serializable[] keys = new String[] {
|
Serializable[] keys = new String[] {
|
||||||
Constants.ATTR_ASIE,
|
Constants.ATTR_ASIE,
|
||||||
Constants.ATTR_UNLOADED_NODE_CORES,
|
Constants.ATTR_UNLOADED,
|
||||||
nodeHostname + ":" + nodePort
|
nodeHostname + ":" + nodePort
|
||||||
};
|
};
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -30,7 +30,7 @@ import com.inteligr8.solr.model.core.ReloadRequest;
|
|||||||
import jakarta.ws.rs.BadRequestException;
|
import jakarta.ws.rs.BadRequestException;
|
||||||
import jakarta.ws.rs.InternalServerErrorException;
|
import jakarta.ws.rs.InternalServerErrorException;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.node.post")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.node.post")
|
||||||
public class ReloadNodeWebScript extends AbstractAsieNodeWebScript {
|
public class ReloadNodeWebScript extends AbstractAsieNodeWebScript {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
@ -45,7 +45,7 @@ public class ReloadNodeWebScript extends AbstractAsieNodeWebScript {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
Serializable[] keys = new String[] {
|
Serializable[] keys = new String[] {
|
||||||
Constants.ATTR_ASIE,
|
Constants.ATTR_ASIE,
|
||||||
Constants.ATTR_UNLOADED_NODE_CORES,
|
Constants.ATTR_UNLOADED,
|
||||||
nodeHostname + ":" + nodePort
|
nodeHostname + ":" + nodePort
|
||||||
};
|
};
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.rest;
|
||||||
|
|
||||||
import org.alfresco.repo.index.shard.ShardState;
|
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.enterprise.model.NodeShardParameterSet;
|
import com.inteligr8.alfresco.asie.model.NodeShardParameterSet;
|
||||||
import com.inteligr8.alfresco.asie.enterprise.model.ShardSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.nodeShard.delete")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.nodeShard.delete")
|
||||||
public class UnloadNodeShardWebScript extends AbstractUnregisterNodeWebScript<NodeShardParameterSet> {
|
public class UnloadNodeShardWebScript extends AbstractUnregisterNodeWebScript<NodeShardParameterSet> {
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -1,11 +1,11 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest;
|
package com.inteligr8.alfresco.asie.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.model.NodeParameterSet;
|
||||||
|
|
||||||
@Component(value = "webscript.com.inteligr8.alfresco.asie.enterprise.node.delete")
|
@Component(value = "webscript.com.inteligr8.alfresco.asie.node.delete")
|
||||||
public class UnloadNodeWebScript extends AbstractUnregisterNodeWebScript<NodeParameterSet> {
|
public class UnloadNodeWebScript extends AbstractUnregisterNodeWebScript<NodeParameterSet> {
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
@ -6,13 +6,9 @@ import java.util.TreeMap;
|
|||||||
import org.alfresco.repo.index.shard.ShardInstance;
|
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;
|
||||||
|
|
||||||
public abstract class NodeInfo {
|
public abstract class NodeInfo {
|
||||||
|
|
||||||
public static String determineId(ShardInstance nodeCache) {
|
|
||||||
int lastSlash = nodeCache.getBaseUrl().lastIndexOf('/');
|
|
||||||
return nodeCache.getHostName() + ":" + nodeCache.getPort() + nodeCache.getBaseUrl().substring(0, lastSlash);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private String id;
|
private String id;
|
||||||
@ -24,7 +20,7 @@ public abstract class NodeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public NodeInfo(ShardInstance nodeCache) {
|
public NodeInfo(ShardInstance nodeCache) {
|
||||||
this.setId(determineId(nodeCache));
|
this.setId(new Node(nodeCache).getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ 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.enterprise.model.ShardSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
@JsonInclude(Include.NON_EMPTY)
|
@JsonInclude(Include.NON_EMPTY)
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.rest.model;
|
package com.inteligr8.alfresco.asie.rest.model;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -10,7 +10,7 @@ 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.enterprise.model.ShardSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
@JsonInclude(Include.NON_EMPTY)
|
@JsonInclude(Include.NON_EMPTY)
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.service;
|
package com.inteligr8.alfresco.asie.service;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -15,16 +15,17 @@ 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.enterprise.rest.model.NodeInfo;
|
import com.inteligr8.alfresco.asie.model.Node;
|
||||||
|
import com.inteligr8.alfresco.asie.spi.ShardDiscoveryService;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class ShardBackupService {
|
public class ShardBackupService implements com.inteligr8.alfresco.asie.spi.ShardBackupService {
|
||||||
|
|
||||||
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
|
@Autowired
|
||||||
private ShardAnalysisService sas;
|
private ShardDiscoveryService sds;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(Constants.QUALIFIER_ASIE)
|
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||||
@ -33,7 +34,7 @@ public class ShardBackupService {
|
|||||||
@Value("${inteligr8.asie.backup.persistTimeMinutes}")
|
@Value("${inteligr8.asie.backup.persistTimeMinutes}")
|
||||||
private int persistTimeMinutes;
|
private int persistTimeMinutes;
|
||||||
|
|
||||||
public String fetchNodeId(Collection<ShardState> shardNodes) {
|
public Node fetchNode(Collection<ShardState> shardNodes) {
|
||||||
if (shardNodes.isEmpty())
|
if (shardNodes.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -46,8 +47,8 @@ public class ShardBackupService {
|
|||||||
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.sas.computeLeadShard(shardNodes);
|
ShardInstance backupShardInstance = this.sds.computeLeadShard(shardNodes);
|
||||||
backupNode = new PersistedNode(NodeInfo.determineId(backupShardInstance));
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,12 +71,12 @@ public class ShardBackupService {
|
|||||||
|
|
||||||
private class PersistedNode implements Serializable {
|
private class PersistedNode implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 4105196543023419818L;
|
||||||
|
|
||||||
private final String node;
|
private final Node node;
|
||||||
private long expireTimeMillis;
|
private long expireTimeMillis;
|
||||||
|
|
||||||
PersistedNode(String node) {
|
PersistedNode(Node node) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
@ -88,7 +89,7 @@ public class ShardBackupService {
|
|||||||
return this.expireTimeMillis < System.currentTimeMillis();
|
return this.expireTimeMillis < System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getNode() {
|
Node getNode() {
|
||||||
return this.node;
|
return this.node;
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.alfresco.asie.enterprise.service;
|
package com.inteligr8.alfresco.asie.service;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
@ -25,16 +25,33 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
|||||||
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.enterprise.model.ShardSet;
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class ShardDiscoveryService {
|
public class ShardDiscoveryService implements com.inteligr8.alfresco.asie.spi.ShardDiscoveryService {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(Constants.BEAN_SHARD_REGISTRY)
|
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||||
private ShardRegistry shardRegistry;
|
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) {
|
public Set<ShardState> findByNode(String nodeHostname, int nodePort) {
|
||||||
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
Map<Floc, Map<Shard, Set<ShardState>>> flocs = this.shardRegistry.getFlocs();
|
||||||
@ -114,11 +131,11 @@ public class ShardDiscoveryService {
|
|||||||
return filteredFlocs;
|
return filteredFlocs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ShardState> findByShard(Map<Shard, Set<ShardState>> shards, int shardId) {
|
public <T> Set<T> filterByShard(Map<Shard, Set<T>> shards, int shardId) {
|
||||||
if (shards == null)
|
if (shards == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
for (Entry<Shard, Set<ShardState>> shard : shards.entrySet()) {
|
for (Entry<Shard, Set<T>> shard : shards.entrySet()) {
|
||||||
if (shard.getKey().getInstance() == shardId)
|
if (shard.getKey().getInstance() == shardId)
|
||||||
return shard.getValue();
|
return shard.getValue();
|
||||||
}
|
}
|
||||||
@ -128,7 +145,7 @@ public class ShardDiscoveryService {
|
|||||||
|
|
||||||
public Set<ShardState> findByShard(ShardSet shardSet, int shardId) {
|
public Set<ShardState> findByShard(ShardSet shardSet, int shardId) {
|
||||||
Map<Shard, Set<ShardState>> shards = this.findByShardSet(shardSet);
|
Map<Shard, Set<ShardState>> shards = this.findByShardSet(shardSet);
|
||||||
return this.findByShard(shards, shardId);
|
return this.filterByShard(shards, shardId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private InetAddress resolve(String hostname) {
|
private InetAddress resolve(String hostname) {
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.spi;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.alfresco.repo.index.shard.ShardState;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.asie.model.Node;
|
||||||
|
|
||||||
|
public interface ShardBackupService {
|
||||||
|
|
||||||
|
Node fetchNode(Collection<ShardState> shardNodes);
|
||||||
|
|
||||||
|
void forget();
|
||||||
|
|
||||||
|
void forget(ShardState shardNode);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.spi;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
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.ShardState;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||||
|
|
||||||
|
public interface ShardDiscoveryService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the lead shard in the specified node/shard snapshot metadata.
|
||||||
|
*
|
||||||
|
* @param shardNodes A collection of snapshot metadata.
|
||||||
|
* @return A single node/shard holding the latest snapshot metadata.
|
||||||
|
*/
|
||||||
|
ShardInstance computeLeadShard(Collection<ShardState> shardNodes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the latest snapshot of each shard on the specified node.
|
||||||
|
*
|
||||||
|
* @param nodeHostname The hostname of a ASIE node.
|
||||||
|
* @param nodePort The port of an ASIE node.
|
||||||
|
* @return A set of the latest snapshot metadata of shards.
|
||||||
|
*/
|
||||||
|
Set<ShardState> findByNode(String nodeHostname, int nodePort);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the shards, their nodes, and the latest snapshot of each within the
|
||||||
|
* specified 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.
|
||||||
|
*/
|
||||||
|
Map<Shard, Set<ShardState>> findByShardSet(ShardSet shardSet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the shards, their nodes, and the latest snapshot of each using the
|
||||||
|
* 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 shardId A 0-based index of a shard.
|
||||||
|
* @return A set of the latest snapshot metadata of shards.
|
||||||
|
*/
|
||||||
|
Set<ShardState> findByShard(ShardSet shardSet, int shardId);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.inteligr8.alfresco.asie.spi;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.attributes.AttributeService.AttributeQueryCallback;
|
||||||
|
|
||||||
|
public interface ShardStateService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the shard state.
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
void remove(Serializable... keys);
|
||||||
|
|
||||||
|
void iterate(AttributeQueryCallback callback);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
# defaulting to 3 days = 60 * 24 * 3 = 4320
|
||||||
|
inteligr8.asie.backup.persistTimeMinutes=4320
|
||||||
|
|
||||||
|
inteligr8.asie.allowedAuthorities=ALFRESCO_ADMINISTRATORS
|
||||||
|
|
||||||
|
# same as solr.baseUrl, but that property is private to the Search subsystem
|
||||||
|
inteligr8.asie.basePath=/solr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Overrides of alfresco-repository.jar/alfresco/caches.properties
|
||||||
|
cache.shardStateSharedCache.tx.maxItems=0
|
||||||
|
cache.shardStateSharedCache.tx.statsEnabled=${caches.tx.statsEnabled}
|
||||||
|
cache.shardStateSharedCache.maxItems=0
|
||||||
|
cache.shardStateSharedCache.timeToLiveSeconds=1800
|
||||||
|
cache.shardStateSharedCache.maxIdleSeconds=0
|
||||||
|
cache.shardStateSharedCache.cluster.type=fully-distributed
|
||||||
|
cache.shardStateSharedCache.backup-count=1
|
||||||
|
cache.shardStateSharedCache.eviction-policy=LRU
|
||||||
|
cache.shardStateSharedCache.merge-policy=com.hazelcast.spi.merge.PutIfAbsentMergePolicy
|
||||||
|
cache.shardStateSharedCache.readBackupData=false
|
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
|
||||||
|
<!-- Use this file for beans to be loaded in whatever order Alfresco/Spring decides -->
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||||
|
|
||||||
|
<!-- Enable Spring annotation scanning for classes -->
|
||||||
|
<context:component-scan base-package="com.inteligr8.alfresco.asie"
|
||||||
|
name-generator="org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator" />
|
||||||
|
|
||||||
|
</beans>
|
Loading…
x
Reference in New Issue
Block a user