Package com.hazelcast.partition.impl

Source Code of com.hazelcast.partition.impl.InternalPartitionImpl

package com.hazelcast.partition.impl;

import com.hazelcast.nio.Address;
import com.hazelcast.partition.InternalPartition;

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

import static java.lang.System.arraycopy;

class InternalPartitionImpl implements InternalPartition {

    private static final AtomicReferenceFieldUpdater<InternalPartitionImpl, Address[]> ADDRESSES_UPDATER
            = AtomicReferenceFieldUpdater.newUpdater(InternalPartitionImpl.class, Address[].class, "addresses");

    //The content of this array will never be updated, so it can be safely read using a volatile read.
    //Writing to 'addresses' is done using the 'addressUpdater' AtomicReferenceFieldUpdater which involves a
    //cas to prevent lost updates.
    //The old approach relied on a AtomicReferenceArray, but this performed a lot slower that the current approach.
    //Number of reads will outweigh the number of writes to the field.

    @edu.umd.cs.findbugs.annotations.SuppressWarnings("VO_VOLATILE_REFERENCE_TO_ARRAY")
    volatile Address[] addresses = new Address[MAX_REPLICA_COUNT];
    private final int partitionId;
    private final PartitionListener partitionListener;
    private volatile boolean isMigrating;

    InternalPartitionImpl(int partitionId, PartitionListener partitionListener) {
        this.partitionId = partitionId;
        this.partitionListener = partitionListener;
    }

    @Override
    public int getPartitionId() {
        return partitionId;
    }

    @Override
    public boolean isMigrating() {
        return isMigrating;
    }

    public void setMigrating(boolean isMigrating) {
        this.isMigrating = isMigrating;
    }

    @Override
    public Address getOwner() {
        return addresses[0];
    }

    void setOwner(Address ownerAddress) {
        setReplicaAddress(0, ownerAddress);
    }

    @Override
    public Address getReplicaAddress(int replicaIndex) {
        return addresses[replicaIndex];
    }

    void setReplicaAddress(int replicaIndex, Address newAddress) {
        boolean changed = false;
        Address oldAddress;
        for (; ; ) {
            Address[] oldAddresses = addresses;
            oldAddress = oldAddresses[replicaIndex];
            if (partitionListener != null) {
                if (oldAddress == null) {
                    changed = newAddress != null;
                } else {
                    changed = !oldAddress.equals(newAddress);
                }
            }

            Address[] newAddresses = createNewAddresses(replicaIndex, newAddress, oldAddresses);
            if (ADDRESSES_UPDATER.compareAndSet(this, oldAddresses, newAddresses)) {
                break;
            }
        }

        if (changed) {
            PartitionReplicaChangeEvent event
                    = new PartitionReplicaChangeEvent(partitionId, replicaIndex, oldAddress, newAddress);
            partitionListener.replicaChanged(event);
        }
    }

    private Address[] createNewAddresses(int replicaIndex, Address newAddress, Address[] oldAddresses) {
        Address[] newAddresses = new Address[MAX_REPLICA_COUNT];
        arraycopy(oldAddresses, 0, newAddresses, 0, MAX_REPLICA_COUNT);
        newAddresses[replicaIndex] = newAddress;
        return newAddresses;
    }

    boolean onDeadAddress(Address deadAddress) {
        for (int i = 0; i < MAX_REPLICA_COUNT; i++) {
            if (!deadAddress.equals(addresses[i])) {
                continue;
            }

            for (int a = i; a + 1 < MAX_REPLICA_COUNT; a++) {
                setReplicaAddress(a, addresses[a + 1]);
            }
            setReplicaAddress(MAX_REPLICA_COUNT - 1, null);
            return true;
        }
        return false;
    }

    void setPartitionInfo(Address[] replicas) {
        for (int i = 0; i < MAX_REPLICA_COUNT; i++) {
            setReplicaAddress(i, replicas[i]);
        }
    }

    @Override
    public boolean isOwnerOrBackup(Address address) {
        for (int i = 0; i < MAX_REPLICA_COUNT; i++) {
            if (address.equals(getReplicaAddress(i))) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("Partition [").append(partitionId).append("]{\n");
        for (int i = 0; i < MAX_REPLICA_COUNT; i++) {
            Address address = addresses[i];
            if (address != null) {
                sb.append('\t');
                sb.append(i).append(":").append(address);
                sb.append("\n");
            }
        }
        sb.append("}");
        return sb.toString();
    }
}
TOP

Related Classes of com.hazelcast.partition.impl.InternalPartitionImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.