/* * Copyright (c) 2008-2012, Hazel Bilisim Ltd. 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.impl.partition; import com.hazelcast.nio.Address; import java.util.concurrent.atomic.AtomicReferenceArray; public class PartitionInfo { public static final int MAX_REPLICA_COUNT = 7; private final int partitionId; private final AtomicReferenceArray<Address> addresses = new AtomicReferenceArray<Address>(MAX_REPLICA_COUNT); private final PartitionListener partitionListener; public PartitionInfo(int partitionId, PartitionListener partitionListener) { this.partitionId = partitionId; this.partitionListener = partitionListener; } public PartitionInfo(int partitionId) { this(partitionId, null); } public PartitionInfo(PartitionInfo partition) { this(partition.getPartitionId(), null); setPartitionInfo(partition); } public int getPartitionId() { return partitionId; } public Address getOwner() { return addresses.get(0); } public void setOwner(Address ownerAddress) { setReplicaAddress(0, ownerAddress); } public void setReplicaAddress(int index, Address address) { boolean changed = false; Address currentAddress = addresses.get(index); if (partitionListener != null) { if (currentAddress == null) { changed = (address != null); } else { changed = !currentAddress.equals(address); } } addresses.set(index, address); if (changed) { partitionListener.replicaChanged(new PartitionReplicaChangeEvent(partitionId, index, currentAddress, address)); } } public Address getReplicaAddress(int index) { return (addresses != null && addresses.length() > index) ? addresses.get(index) : null; } public void setPartitionInfo(PartitionInfo partitionInfo) { for (int i = 0; i < MAX_REPLICA_COUNT; i++) { setReplicaAddress(i, partitionInfo.getReplicaAddress(i)); } } public boolean isBackup(Address address, int backupCount) { int backup = Math.min(backupCount + 1, MAX_REPLICA_COUNT); for (int i = 1; i < backup; i++) { if (address.equals(getReplicaAddress(i))) { return true; } } return false; } public boolean isOwnerOrBackup(Address address, int backupCount) { int replicaCount = Math.min(backupCount + 1, MAX_REPLICA_COUNT); for (int i = 0; i < replicaCount; 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.get(i); if (address != null) { sb.append(i).append(":").append(address); sb.append("\n"); } } sb.append("}"); return sb.toString(); } public boolean onDeadAddress(Address deadAddress) { for (int i = 0; i < MAX_REPLICA_COUNT; i++) { if (deadAddress.equals(addresses.get(i))) { for (int a = i; a + 1 < MAX_REPLICA_COUNT; a++) { setReplicaAddress(a, addresses.get(a + 1)); } setReplicaAddress(MAX_REPLICA_COUNT - 1, null); return true; } } return false; } public int getReplicaIndexOf(Address address) { for (int i = 0; i < MAX_REPLICA_COUNT; i++) { if (address.equals(addresses.get(i))) { return i; } } return -1; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PartitionInfo that = (PartitionInfo) o; if (partitionId != that.partitionId) return false; for (int i = 0; i < MAX_REPLICA_COUNT; i++) { Address a1 = addresses.get(i); Address a2 = that.addresses.get(i); if (a1 == null) { if (a2 != null) { return false; } } else if (!a1.equals(a2)) { return false; } } return true; } @Override public int hashCode() { int result = partitionId; for (int i = 0; i < MAX_REPLICA_COUNT; i++) { Address address = addresses.get(i); result = 31 * result + (address != null ? address.hashCode() : 0); } return result; } }