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

com.hazelcast.internal.partition.PartitionRuntimeState Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * Copyright (c) 2008-2016, 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;

import com.hazelcast.internal.partition.impl.PartitionDataSerializerHook;
import com.hazelcast.nio.Address;
import com.hazelcast.nio.ObjectDataInput;
import com.hazelcast.nio.ObjectDataOutput;
import com.hazelcast.nio.serialization.IdentifiedDataSerializable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static com.hazelcast.internal.partition.InternalPartition.MAX_REPLICA_COUNT;
import static com.hazelcast.util.StringUtil.LINE_SEPARATOR;

public final class PartitionRuntimeState implements IdentifiedDataSerializable {

    // used for writing state
    private Map addressToIndexes;

    // used for reading state
    private Address[] addresses;

    private int[][] minimizedPartitionTable;
    private int version;
    private Collection completedMigrations;
    // used to know ongoing migrations when master changed
    private MigrationInfo activeMigration;

    private Address endpoint;

    public PartitionRuntimeState() {
    }

    public PartitionRuntimeState(InternalPartition[] partitions, Collection migrationInfos, int version) {
        this.version = version;
        completedMigrations = migrationInfos != null ? migrationInfos : Collections.emptyList();
        addressToIndexes = createAddressToIndexMap(partitions);
        minimizedPartitionTable = createMinimizedPartitionTable(partitions);
    }

    private int[][] createMinimizedPartitionTable(InternalPartition[] partitions) {
        int[][] partitionTable = new int[partitions.length][MAX_REPLICA_COUNT];

        for (InternalPartition partition : partitions) {
            int[] indexes = partitionTable[partition.getPartitionId()];

            for (int replicaIndex = 0; replicaIndex < MAX_REPLICA_COUNT; replicaIndex++) {
                Address address = partition.getReplicaAddress(replicaIndex);
                if (address == null) {
                    indexes[replicaIndex] = -1;
                } else {
                    int index = addressToIndexes.get(address);
                    indexes[replicaIndex] = index;
                }
            }
        }
        return partitionTable;
    }

    private Map createAddressToIndexMap(InternalPartition[] partitions) {
        Map map = new HashMap();
        int addressIndex = 0;
        for (InternalPartition partition : partitions) {
            for (int i = 0; i < MAX_REPLICA_COUNT; i++) {
                Address address = partition.getReplicaAddress(i);
                if (address == null) {
                    continue;
                }
                if (map.containsKey(address)) {
                    continue;
                }
                map.put(address, addressIndex++);
            }
        }
        return map;
    }

    public Address[][] getPartitionTable() {
        if (addresses == null) {
            addresses = new Address[addressToIndexes.size()];
            for (Map.Entry entry : addressToIndexes.entrySet()) {
                addresses[entry.getValue()] = entry.getKey();
            }
        }

        int length = minimizedPartitionTable.length;
        Address[][] result = new Address[length][MAX_REPLICA_COUNT];
        for (int partitionId = 0; partitionId < length; partitionId++) {
            Address[] replicas = result[partitionId];
            int[] addressIndexes = minimizedPartitionTable[partitionId];
            for (int replicaIndex = 0; replicaIndex < addressIndexes.length; replicaIndex++) {
                int index = addressIndexes[replicaIndex];
                if (index != -1) {
                    Address address = addresses[index];
                    assert address != null;
                    replicas[replicaIndex] = address;
                }
            }
        }
        return result;
    }

    public Address getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(final Address endpoint) {
        this.endpoint = endpoint;
    }

    public Collection getCompletedMigrations() {
        return completedMigrations != null ? completedMigrations : Collections.emptyList();
    }

    public MigrationInfo getActiveMigration() {
        return activeMigration;
    }

    public void setActiveMigration(MigrationInfo activeMigration) {
        this.activeMigration = activeMigration;
    }

    public void setCompletedMigrations(Collection completedMigrations) {
        this.completedMigrations = completedMigrations;
    }

    @Override
    public void readData(ObjectDataInput in) throws IOException {
        version = in.readInt();
        int memberCount = in.readInt();
        addresses = new Address[memberCount];
        for (int i = 0; i < memberCount; i++) {
            Address address = new Address();
            address.readData(in);
            int index = in.readInt();
            assert addresses[index] == null : "Duplicate address! Address: " + address + ", index: " + index
                    + ", addresses: " + Arrays.toString(addresses);
            addresses[index] = address;
        }

        int partitionCount = in.readInt();
        minimizedPartitionTable = new int[partitionCount][MAX_REPLICA_COUNT];
        for (int i = 0; i < partitionCount; i++) {
            int[] indexes = minimizedPartitionTable[i];
            for (int ix = 0; ix < MAX_REPLICA_COUNT; ix++) {
                indexes[ix] = in.readInt();
            }
        }

        if (in.readBoolean()) {
            activeMigration = new MigrationInfo();
            activeMigration.readData(in);
        }

        int k = in.readInt();
        if (k > 0) {
            completedMigrations = new ArrayList(k);
            for (int i = 0; i < k; i++) {
                MigrationInfo migrationInfo = new MigrationInfo();
                migrationInfo.readData(in);
                completedMigrations.add(migrationInfo);
            }
        }
    }

    @SuppressWarnings("checkstyle:npathcomplexity")
    @Override
    public void writeData(ObjectDataOutput out) throws IOException {
        out.writeInt(version);
        if (addressToIndexes == null) {
            out.writeInt(addresses.length);
            for (int index = 0; index < addresses.length; index++) {
                Address address = addresses[index];
                address.writeData(out);
                out.writeInt(index);
            }
        } else {
            int memberCount = addressToIndexes.size();
            out.writeInt(memberCount);
            for (Map.Entry entry : addressToIndexes.entrySet()) {
                Address address = entry.getKey();
                address.writeData(out);
                int index = entry.getValue();
                out.writeInt(index);
            }
        }

        out.writeInt(minimizedPartitionTable.length);
        for (int[] indexes : minimizedPartitionTable) {
            for (int ix = 0; ix < MAX_REPLICA_COUNT; ix++) {
                out.writeInt(indexes[ix]);
            }
        }

        if (activeMigration != null) {
            out.writeBoolean(true);
            activeMigration.writeData(out);
        } else {
            out.writeBoolean(false);
        }

        if (completedMigrations != null) {
            int k = completedMigrations.size();
            out.writeInt(k);
            for (MigrationInfo migrationInfo : completedMigrations) {
                migrationInfo.writeData(out);
            }
        } else {
            out.writeInt(0);
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("PartitionRuntimeState [" + version + "]{" + LINE_SEPARATOR);

        if (addressToIndexes == null) {
            //addressToIndexes is null after deserialization. let's use the array
            for (Address address : addresses) {
                sb.append(address).append(LINE_SEPARATOR);
            }
        } else {
            for (Address address : addressToIndexes.keySet()) {
                sb.append(address).append(LINE_SEPARATOR);
            }
        }
        sb.append(", completedMigrations=").append(completedMigrations);
        sb.append('}');
        return sb.toString();
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    @Override
    public int getFactoryId() {
        return PartitionDataSerializerHook.F_ID;
    }

    @Override
    public int getId() {
        return PartitionDataSerializerHook.PARTITION_STATE;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy