/*
* Copyright 2014 Avanza Bank AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.avanza.astrix.gs.localview;
import org.openspaces.core.GigaSpace;
import org.openspaces.core.GigaSpaceConfigurer;
import org.openspaces.core.space.UrlSpaceConfigurer;
import org.openspaces.core.space.cache.LocalViewSpaceConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avanza.astrix.beans.core.AstrixConfigAware;
import com.avanza.astrix.beans.core.AstrixSettings;
import com.avanza.astrix.beans.core.BeanProxy;
import com.avanza.astrix.beans.core.BeanProxyFilter;
import com.avanza.astrix.beans.core.BeanProxyNames;
import com.avanza.astrix.beans.service.BoundServiceBeanInstance;
import com.avanza.astrix.beans.service.ServiceComponent;
import com.avanza.astrix.beans.service.ServiceDefinition;
import com.avanza.astrix.beans.service.ServiceProperties;
import com.avanza.astrix.beans.service.UnsupportedTargetTypeException;
import com.avanza.astrix.config.DynamicBooleanProperty;
import com.avanza.astrix.config.DynamicConfig;
import com.avanza.astrix.config.DynamicIntProperty;
import com.avanza.astrix.config.DynamicLongProperty;
import com.avanza.astrix.core.util.ReflectionUtil;
import com.avanza.astrix.gs.ClusteredProxyBinder;
import com.avanza.astrix.gs.GigaSpaceProxy;
import com.avanza.astrix.gs.GsBinder;
import com.avanza.astrix.provider.component.AstrixServiceComponentNames;
import com.avanza.astrix.spring.AstrixSpringContext;
import com.j_spaces.core.IJSpace;
/**
* Allows publishing a GigaSpace's local-view.
*
* @author Elias Lindholm (elilin)
*
*/
public class GsLocalViewComponent implements ServiceComponent, AstrixConfigAware, BeanProxyFilter {
private static Logger log = LoggerFactory.getLogger(GsLocalViewComponent.class);
private GsBinder gsBinder;
private AstrixSpringContext astrixSpringContext;
private DynamicBooleanProperty disableLocalView;
private DynamicLongProperty maxDisonnectionTime;
private DynamicIntProperty lookupTimeout;
private ClusteredProxyBinder clusteredProxyBinder;
public GsLocalViewComponent(GsBinder gsBinder,
AstrixSpringContext astrixSpringContext,
ClusteredProxyBinder clusteredProxyBinder) {
this.gsBinder = gsBinder;
this.astrixSpringContext = astrixSpringContext;
this.clusteredProxyBinder = clusteredProxyBinder;
}
@Override
public <T> BoundServiceBeanInstance<T> bind(
ServiceDefinition<T> serviceDefinition,
ServiceProperties serviceProperties) {
Class<T> type = serviceDefinition.getServiceType();
if (!GigaSpace.class.isAssignableFrom(type)) {
throw new UnsupportedTargetTypeException(getName(), type);
}
if (disableLocalView.get()) {
log.info("LocalView is disabled. Creating reqular proxy");
return clusteredProxyBinder.bind(serviceDefinition, serviceProperties);
}
log.info("Creating local view. bean={} serviceProperties={}", serviceDefinition.getBeanKey(), serviceProperties.getProperties());
// TODO: protect creation of localView with fault-tolerance?
Class<LocalViewConfigurer> serviceConfigClass = serviceDefinition.getServiceConfigClass(LocalViewConfigurer.class);
LocalViewConfigurer localViewConfigurer = ReflectionUtil.newInstance(serviceConfigClass);
UrlSpaceConfigurer gsSpaceConfigurer = new UrlSpaceConfigurer(serviceProperties.getProperty(GsBinder.SPACE_URL_PROPERTY));
IJSpace space = gsSpaceConfigurer.lookupTimeout(this.lookupTimeout.get())
// Disable memory shortage check for local view clients
.addParameter("space-config.engine.memory_usage.enabled", "false").create();
LocalViewSpaceConfigurer gslocalViewSpaceConfigurer = new LocalViewSpaceConfigurer(space);
gslocalViewSpaceConfigurer.maxDisconnectionDuration(this.maxDisonnectionTime.get());
localViewConfigurer.configure(new LocalViewSpaceConfigurerAdapter(gslocalViewSpaceConfigurer));
String spaceName = serviceProperties.getProperty(GsBinder.SPACE_NAME_PROPERTY);
String commandKey = spaceName + "_" + GigaSpace.class.getSimpleName();
String qualifier = serviceProperties.getProperty(ServiceProperties.QUALIFIER);
if (qualifier != null) {
commandKey = commandKey + "-" + qualifier;
}
IJSpace localViewSpace = gslocalViewSpaceConfigurer.create();
GigaSpace localViewGigaSpace = GigaSpaceProxy.create(new GigaSpaceConfigurer(localViewSpace).create());
BoundLocalViewGigaSpaceBeanInstance localViewGigaSpaceBeanInstance =
new BoundLocalViewGigaSpaceBeanInstance(localViewGigaSpace, gslocalViewSpaceConfigurer, gsSpaceConfigurer);
return (BoundServiceBeanInstance<T>) localViewGigaSpaceBeanInstance;
}
@Override
public boolean applyBeanProxy(BeanProxy beanProxy) {
if (beanProxy.name().equals(BeanProxyNames.FAULT_TOLERANCE)) {
if (disableLocalView.get()) {
return true; // Apply faultTolerance proxy if local-view is disabled
}
return false;
}
return true;
}
@Override
public ServiceProperties parseServiceProviderUri(String serviceProviderUri) {
return gsBinder.createServiceProperties(serviceProviderUri);
}
@Override
public <T> ServiceProperties createServiceProperties(ServiceDefinition<T> definition) {
if (!definition.getServiceType().equals(GigaSpace.class)) {
throw new UnsupportedTargetTypeException(getName(), definition.getServiceType());
}
GigaSpace space = gsBinder.getEmbeddedSpace(astrixSpringContext.getApplicationContext());
ServiceProperties properties = gsBinder.createProperties(space);
return properties;
}
@Override
public String getName() {
return AstrixServiceComponentNames.GS_LOCAL_VIEW;
}
@Override
public boolean canBindType(Class<?> type) {
return GigaSpace.class.equals(type);
}
@Override
public <T> void exportService(Class<T> providedApi,
T provider,
ServiceDefinition<T> serviceDefintition) {
// Intentionally empty
}
@Override
public boolean requiresProviderInstance() {
return false;
}
@Override
public void setConfig(DynamicConfig config) {
this.disableLocalView = AstrixSettings.GS_DISABLE_LOCAL_VIEW.getFrom(config);
this.maxDisonnectionTime = AstrixSettings.GS_LOCAL_VIEW_MAX_DISCONNECTION_TIME.getFrom(config);
this.lookupTimeout = AstrixSettings.GS_LOCAL_VIEW_LOOKUP_TIMEOUT.getFrom(config);
}
private static class BoundLocalViewGigaSpaceBeanInstance implements BoundServiceBeanInstance<GigaSpace> {
private GigaSpace instance;
private LocalViewSpaceConfigurer localViewSpaceConfigurer;
private UrlSpaceConfigurer spaceConfigurer;
public BoundLocalViewGigaSpaceBeanInstance(GigaSpace instance,
LocalViewSpaceConfigurer localViewSpaceConfigurer,
UrlSpaceConfigurer spaceConfigurer) {
this.instance = instance;
this.localViewSpaceConfigurer = localViewSpaceConfigurer;
this.spaceConfigurer = spaceConfigurer;
}
@Override
public GigaSpace get() {
return instance;
}
@Override
public void release() {
try {
localViewSpaceConfigurer.close();
spaceConfigurer.close();
} catch (Exception e) {
log.error("Failed to destroy local-view", e);
}
}
}
}