/*
* Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
*
* 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.hazelcast.spi;
import com.hazelcast.core.DistributedObject;
import com.hazelcast.core.HazelcastInstanceNotActiveException;
import com.hazelcast.core.PartitioningStrategy;
import com.hazelcast.nio.serialization.Data;
import com.hazelcast.partition.strategy.StringPartitioningStrategy;
/**
* Abstract DistributedObject implementation. Useful to provide basic functionality.
*
* @param <S>
*/
public abstract class AbstractDistributedObject<S extends RemoteService> implements DistributedObject {
protected static final PartitioningStrategy PARTITIONING_STRATEGY = StringPartitioningStrategy.INSTANCE;
private volatile NodeEngine nodeEngine;
private volatile S service;
protected AbstractDistributedObject(NodeEngine nodeEngine, S service) {
this.nodeEngine = nodeEngine;
this.service = service;
}
protected String getDistributedObjectName() {
return getName();
}
protected Data getNameAsPartitionAwareData() {
String name = getDistributedObjectName();
return getNodeEngine().getSerializationService().toData(name, PARTITIONING_STRATEGY);
}
@Override
public String getPartitionKey() {
return StringPartitioningStrategy.getPartitionKey(getDistributedObjectName());
}
@Override
public final void destroy() {
if (preDestroy()) {
NodeEngine engine = getNodeEngine();
ProxyService proxyService = engine.getProxyService();
proxyService.destroyDistributedObject(getServiceName(), getDistributedObjectName());
postDestroy();
}
}
protected final Data toData(Object object) {
return getNodeEngine().toData(object);
}
protected final <E> InternalCompletableFuture<E> invokeOnPartition(Operation operation) {
return getNodeEngine().getOperationService().invokeOnPartition(operation);
}
protected final int getPartitionId(Data key) {
return getNodeEngine().getPartitionService().getPartitionId(key);
}
protected boolean preDestroy() {
return true;
}
protected void postDestroy() {
}
/**
* Gets the node engine.
*
* @return the node engine
* @throws HazelcastInstanceNotActiveException if NodeEngine not active or DistributedObject destroyed.
*/
public final NodeEngine getNodeEngine() {
final NodeEngine engine = nodeEngine;
lifecycleCheck(engine);
return engine;
}
private void lifecycleCheck(final NodeEngine engine) {
if (engine == null || !engine.isRunning()) {
throwNotActiveException();
}
}
protected void throwNotActiveException() {
throw new HazelcastInstanceNotActiveException();
}
/**
* Gets the Service of this AbstractDistributedObject.
*
* @return the Service of this AbstractDistributedObject
* @throws HazelcastInstanceNotActiveException if object is destroyed or HazelcastInstance shutdown.
*/
public final S getService() {
final S s = service;
if (s == null) {
throw new HazelcastInstanceNotActiveException();
}
return s;
}
/**
* Gets the OperationService.
*
* @return the OperationService.
* @throws HazelcastInstanceNotActiveException if object is destroyed or HazelcastInstance shutdown.
*/
public final OperationService getOperationService() {
return getNodeEngine().getOperationService();
}
@Override
public abstract String getServiceName();
public final void invalidate() {
nodeEngine = null;
service = null;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AbstractDistributedObject that = (AbstractDistributedObject) o;
Object name = getDistributedObjectName();
if (name != null ? !name.equals(that.getDistributedObjectName()) : that.getDistributedObjectName() != null) {
return false;
}
String serviceName = getServiceName();
if (serviceName != null ? !serviceName.equals(that.getServiceName()) : that.getServiceName() != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = getServiceName() != null ? getServiceName().hashCode() : 0;
result = 31 * result + (getDistributedObjectName() != null ? getDistributedObjectName().hashCode() : 0);
return result;
}
@Override
public String toString() {
return getClass().getName() + '{' + "service=" + getServiceName() + ", name=" + getName() + '}';
}
}