All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.partition.MigrationOperation Maven / Gradle / Ivy

/*
 * Copyright (c) 2008-2013, 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.partition;

import com.hazelcast.core.HazelcastException;
import com.hazelcast.nio.BufferObjectDataInput;
import com.hazelcast.nio.IOUtil;
import com.hazelcast.nio.ObjectDataInput;
import com.hazelcast.nio.ObjectDataOutput;
import com.hazelcast.nio.serialization.SerializationService;
import com.hazelcast.spi.*;
import com.hazelcast.spi.exception.RetryableHazelcastException;
import com.hazelcast.spi.impl.NodeEngineImpl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;

public final class MigrationOperation extends BaseMigrationOperation {

    private static final ResponseHandler ERROR_RESPONSE_HANDLER = new ErrorResponseHandler();

    private long[] replicaVersions;
    private transient Collection tasks;
    private byte[] zippedTaskData;
    private int taskCount;

    public MigrationOperation() {
    }

    public MigrationOperation(MigrationInfo migrationInfo, long[] replicaVersions, byte[] taskData, int taskCount) {
        super(migrationInfo);
        this.replicaVersions = replicaVersions;
        this.taskCount = taskCount;
        this.zippedTaskData = taskData;
    }

    public void run() throws Exception {
        NodeEngine nodeEngine = getNodeEngine();
        if (!nodeEngine.getMasterAddress().equals(migrationInfo.getMaster())) {
            throw new RetryableHazelcastException("Migration initiator is not master node! => " + toString());
        }
        SerializationService serializationService = nodeEngine.getSerializationService();
        BufferObjectDataInput in = null;
        if (migrationInfo.startProcessing()) {
            try {
                final byte[] taskData = IOUtil.decompress(zippedTaskData);
                in = serializationService.createObjectDataInput(taskData);
                int size = in.readInt();
                tasks = new ArrayList(size);
                for (int i = 0; i < size; i++) {
                    Operation task = (Operation) serializationService.readObject(in);
                    tasks.add(task);
                }
                if (taskCount != tasks.size()) {
                    getLogger().log(Level.SEVERE, "Migration task count mismatch! => " +
                            "expected-count: " + size + ", actual-count: " + tasks.size() +
                            "\nfrom: " + migrationInfo.getSource() + ", partition: " + getPartitionId()
                            + ", replica: " + getReplicaIndex());
                }
                success = runMigrationTasks();
                if (success) {
                    final PartitionServiceImpl partitionService = getService();
                    partitionService.setPartitionReplicaVersions(migrationInfo.getPartitionId(), replicaVersions);
                }
            } catch (Throwable e) {
                Level level = Level.WARNING;
                if (e instanceof IllegalStateException) {
                    level = Level.FINEST;
                }
                getLogger().log(level, e.getMessage(), e);
                success = false;
            } finally {
                migrationInfo.doneProcessing();
                IOUtil.closeResource(in);
            }
        } else {
            getLogger().log(Level.WARNING, "Migration is cancelled -> " + migrationInfo);
            success = false;
        }
    }

    public Object getResponse() {
        return success;
    }

    private boolean runMigrationTasks() {
        boolean error = false;
        final NodeEngineImpl nodeEngine = (NodeEngineImpl) getNodeEngine();
        final PartitionServiceImpl partitionService = getService();
        partitionService.addActiveMigration(migrationInfo);

        for (Operation op : tasks) {
            try {
                op.setNodeEngine(nodeEngine)
                        .setPartitionId(getPartitionId()).setReplicaIndex(getReplicaIndex());
                op.setResponseHandler(ERROR_RESPONSE_HANDLER);
                OperationAccessor.setCallerAddress(op, migrationInfo.getSource());
                MigrationAwareService service = op.getService();
                service.beforeMigration(new PartitionMigrationEvent(MigrationEndpoint.DESTINATION, migrationInfo.getPartitionId()));
                op.beforeRun();
                op.run();
                op.afterRun();
            } catch (Throwable e) {
                error = true;
                getLogger().log(Level.SEVERE, "While executing " + op, e);
                break;
            }
        }
        return !error;
    }

    private static class ErrorResponseHandler implements ResponseHandler {
        public void sendResponse(final Object obj) {
            throw new HazelcastException("Migration operations can not send response!");
        }
    }

    protected void writeInternal(ObjectDataOutput out) throws IOException {
        super.writeInternal(out);
        out.writeInt(taskCount);
        out.writeInt(zippedTaskData.length);
        out.write(zippedTaskData);
        out.writeLongArray(replicaVersions);
    }

    protected void readInternal(ObjectDataInput in) throws IOException {
        super.readInternal(in);
        taskCount = in.readInt();
        int size = in.readInt();
        zippedTaskData = new byte[size];
        in.readFully(zippedTaskData);
        replicaVersions = in.readLongArray();
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append(getClass().getName());
        sb.append("{partitionId=").append(getPartitionId());
        sb.append(", migration=").append(migrationInfo);
        sb.append(", taskCount=").append(taskCount);
        sb.append('}');
        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy