/* * 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.core.Member; import com.hazelcast.core.MemberLeftException; import com.hazelcast.internal.partition.InternalPartition; import com.hazelcast.internal.partition.MigrationInfo; import com.hazelcast.internal.partition.impl.InternalMigrationListener.MigrationParticipant; import com.hazelcast.nio.Address; import com.hazelcast.spi.ExceptionAction; import com.hazelcast.spi.NodeEngine; import com.hazelcast.spi.PartitionMigrationEvent; import com.hazelcast.spi.PartitionReplicationEvent; import com.hazelcast.spi.exception.RetryableHazelcastException; import com.hazelcast.spi.exception.TargetNotMemberException; import com.hazelcast.spi.partition.MigrationEndpoint; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import static com.hazelcast.internal.cluster.Versions.V3_9; abstract class BaseMigrationSourceOperation extends BaseMigrationOperation { boolean returnResponse = true; BaseMigrationSourceOperation() { } BaseMigrationSourceOperation(MigrationInfo migrationInfo, int partitionStateVersion) { super(migrationInfo, partitionStateVersion); } @Override protected PartitionMigrationEvent getMigrationEvent() { return new PartitionMigrationEvent(MigrationEndpoint.SOURCE, migrationInfo.getPartitionId(), migrationInfo.getSourceCurrentReplicaIndex(), migrationInfo.getSourceNewReplicaIndex()); } @Override protected MigrationParticipant getMigrationParticipantType() { return MigrationParticipant.SOURCE; } /** Verifies that the local master is equal to the migration master. */ final void verifyMasterOnMigrationSource() { NodeEngine nodeEngine = getNodeEngine(); Address masterAddress = nodeEngine.getMasterAddress(); boolean shouldFail = nodeEngine.getClusterService().getClusterVersion().isGreaterOrEqual(V3_9); if (!migrationInfo.getMaster().equals(masterAddress)) { if (shouldFail) { throw new IllegalStateException("Migration initiator is not master node! => " + toString()); } else { throw new RetryableHazelcastException("Migration initiator is not master node! => " + toString()); } } if (!masterAddress.equals(getCallerAddress())) { if (shouldFail) { throw new IllegalStateException("Caller is not master node! => " + toString()); } else { throw new RetryableHazelcastException("Caller is not master node! => " + toString()); } } } /** Verifies that this node is the owner of the partition. */ final void verifySource(Address thisAddress, InternalPartition partition) { Address owner = partition.getOwnerOrNull(); if (owner == null) { throw new RetryableHazelcastException("Cannot migrate at the moment! Owner of the partition is null => " + migrationInfo); } if (!thisAddress.equals(owner)) { throw new RetryableHazelcastException("Owner of partition is not this node! => " + toString()); } } /** Verifies that the destination is a cluster member. */ final void verifyExistingTarget(NodeEngine nodeEngine, Address destination) { Member target = nodeEngine.getClusterService().getMember(destination); if (target == null) { throw new TargetNotMemberException("Destination of migration could not be found! => " + toString()); } } final PartitionReplicationEvent getPartitionReplicationEvent() { return new PartitionReplicationEvent(migrationInfo.getPartitionId(), migrationInfo.getDestinationNewReplicaIndex()); } final void setFailed() { success = false; onMigrationComplete(false); } final void completeMigration(boolean result) { success = result; migrationInfo.doneProcessing(); onMigrationComplete(result); sendResponse(result); } final void logThrowable(Throwable t) { Throwable throwableToLog = t; if (throwableToLog instanceof ExecutionException) { throwableToLog = throwableToLog.getCause() != null ? throwableToLog.getCause() : throwableToLog; } Level level = getLogLevel(throwableToLog); getLogger().log(level, throwableToLog.getMessage(), throwableToLog); } private Level getLogLevel(Throwable e) { return (e instanceof MemberLeftException || e instanceof InterruptedException) || !getNodeEngine().isRunning() ? Level.INFO : Level.WARNING; } @Override public ExceptionAction onInvocationException(Throwable throwable) { if (throwable instanceof TargetNotMemberException) { return ExceptionAction.THROW_EXCEPTION; } return super.onInvocationException(throwable); } @Override public boolean returnsResponse() { return returnResponse; } @Override void executeBeforeMigrations() throws Exception { NodeEngine nodeEngine = getNodeEngine(); boolean ownerMigration = nodeEngine.getThisAddress().equals(migrationInfo.getSource()); if (!ownerMigration) { return; } super.executeBeforeMigrations(); } }