/*
* 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.internal.partition.operation;
import com.hazelcast.internal.partition.NonFragmentedServiceNamespace;
import com.hazelcast.internal.partition.impl.PartitionDataSerializerHook;
import com.hazelcast.nio.serialization.IdentifiedDataSerializable;
import com.hazelcast.spi.FragmentedMigrationAwareService;
import com.hazelcast.spi.MigrationAwareService;
import com.hazelcast.spi.Operation;
import com.hazelcast.spi.PartitionReplicationEvent;
import com.hazelcast.spi.ServiceNamespace;
import com.hazelcast.spi.impl.NodeEngineImpl;
import com.hazelcast.spi.impl.servicemanager.ServiceInfo;
import java.util.ArrayList;
import java.util.Collection;
import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
abstract class AbstractPartitionOperation extends Operation implements IdentifiedDataSerializable {
final Collection<MigrationAwareService> getMigrationAwareServices() {
NodeEngineImpl nodeEngine = (NodeEngineImpl) getNodeEngine();
return nodeEngine.getServices(MigrationAwareService.class);
}
final Collection<Operation> createAllReplicationOperations(PartitionReplicationEvent event) {
return createReplicationOperations(event, false);
}
final Collection<Operation> createNonFragmentedReplicationOperations(PartitionReplicationEvent event) {
return createReplicationOperations(event, true);
}
private Collection<Operation> createReplicationOperations(PartitionReplicationEvent event, boolean nonFragmentedOnly) {
Collection<Operation> operations = new ArrayList<Operation>();
NodeEngineImpl nodeEngine = (NodeEngineImpl) getNodeEngine();
Collection<ServiceInfo> services = nodeEngine.getServiceInfos(MigrationAwareService.class);
for (ServiceInfo serviceInfo : services) {
MigrationAwareService service = serviceInfo.getService();
if (nonFragmentedOnly && service instanceof FragmentedMigrationAwareService) {
// skip fragmented services
continue;
}
Operation op = service.prepareReplicationOperation(event);
if (op != null) {
op.setServiceName(serviceInfo.getName());
operations.add(op);
}
}
return operations;
}
final Collection<Operation> createFragmentReplicationOperations(PartitionReplicationEvent event, ServiceNamespace ns,
Collection<String> serviceNames) {
assert !(ns instanceof NonFragmentedServiceNamespace) : ns + " should be used only for non-fragmented services!";
Collection<Operation> operations = emptySet();
NodeEngineImpl nodeEngine = (NodeEngineImpl) getNodeEngine();
for (String serviceName : serviceNames) {
FragmentedMigrationAwareService service = nodeEngine.getService(serviceName);
assert service.isKnownServiceNamespace(ns) : ns + " should be known by " + service;
operations = prepareAndAppendReplicationOperation(event, ns, service, serviceName, operations);
}
return operations;
}
final Collection<Operation> createFragmentReplicationOperations(PartitionReplicationEvent event, ServiceNamespace ns) {
assert !(ns instanceof NonFragmentedServiceNamespace) : ns + " should be used only for non-fragmented services!";
Collection<Operation> operations = emptySet();
NodeEngineImpl nodeEngine = (NodeEngineImpl) getNodeEngine();
Collection<ServiceInfo> services = nodeEngine.getServiceInfos(FragmentedMigrationAwareService.class);
for (ServiceInfo serviceInfo : services) {
FragmentedMigrationAwareService service = serviceInfo.getService();
if (!service.isKnownServiceNamespace(ns)) {
continue;
}
operations = prepareAndAppendReplicationOperation(event, ns, service, serviceInfo.getName(), operations);
}
return operations;
}
private Collection<Operation> prepareAndAppendReplicationOperation(PartitionReplicationEvent event, ServiceNamespace ns,
FragmentedMigrationAwareService service, String serviceName, Collection<Operation> operations) {
Operation op = service.prepareReplicationOperation(event, singleton(ns));
if (op == null) {
return operations;
}
op.setServiceName(serviceName);
if (operations.isEmpty()) {
// generally a namespace belongs to a single service only
operations = singleton(op);
} else if (operations.size() == 1) {
operations = new ArrayList<Operation>(operations);
operations.add(op);
} else {
operations.add(op);
}
return operations;
}
@Override
public final int getFactoryId() {
return PartitionDataSerializerHook.F_ID;
}
}