/*
* 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.cluster.impl.operations;
import com.hazelcast.instance.Node;
import com.hazelcast.internal.cluster.MemberInfo;
import com.hazelcast.internal.cluster.impl.ClusterDataSerializerHook;
import com.hazelcast.internal.cluster.impl.ClusterServiceImpl;
import com.hazelcast.internal.cluster.impl.MembersView;
import com.hazelcast.internal.partition.PartitionRuntimeState;
import com.hazelcast.nio.Address;
import com.hazelcast.nio.Connection;
import com.hazelcast.nio.ObjectDataInput;
import com.hazelcast.nio.ObjectDataOutput;
import com.hazelcast.spi.impl.NodeEngineImpl;
import com.hazelcast.util.Clock;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
public class MembersUpdateOp extends VersionedClusterOperation {
/** The master cluster clock time. */
long masterTime = Clock.currentTimeMillis();
/** The updated member info collection. */
private List<MemberInfo> memberInfos;
/** The UUID of the receiving member. */
private String targetUuid;
private boolean returnResponse;
private PartitionRuntimeState partitionRuntimeState;
public MembersUpdateOp() {
super(0);
memberInfos = emptyList();
}
public MembersUpdateOp(String targetUuid, MembersView membersView, long masterTime,
PartitionRuntimeState partitionRuntimeState, boolean returnResponse) {
super(membersView.getVersion());
this.targetUuid = targetUuid;
this.masterTime = masterTime;
this.memberInfos = membersView.getMembers();
this.returnResponse = returnResponse;
this.partitionRuntimeState = partitionRuntimeState;
}
@Override
public void run() throws Exception {
checkLocalMemberUuid();
ClusterServiceImpl clusterService = getService();
Address callerAddress = getConnectionEndpointOrThisAddress();
String callerUuid = getCallerUuid();
if (clusterService.updateMembers(getMembersView(), callerAddress, callerUuid)) {
processPartitionState();
}
}
final MembersView getMembersView() {
return new MembersView(getMemberListVersion(), unmodifiableList(memberInfos));
}
final Address getConnectionEndpointOrThisAddress() {
ClusterServiceImpl clusterService = getService();
NodeEngineImpl nodeEngine = clusterService.getNodeEngine();
Node node = nodeEngine.getNode();
Connection conn = getConnection();
return conn != null ? conn.getEndPoint() : node.getThisAddress();
}
final void processPartitionState() {
if (partitionRuntimeState == null) {
return;
}
partitionRuntimeState.setEndpoint(getCallerAddress());
ClusterServiceImpl clusterService = getService();
Node node = clusterService.getNodeEngine().getNode();
node.partitionService.processPartitionRuntimeState(partitionRuntimeState);
}
final void checkLocalMemberUuid() {
ClusterServiceImpl clusterService = getService();
if (!clusterService.getThisUuid().equals(targetUuid)) {
String msg = "targetUuid: " + targetUuid + " is different than this node's uuid: " + clusterService.getThisUuid();
throw new IllegalStateException(msg);
}
}
@Override
public final boolean returnsResponse() {
return returnResponse;
}
@Override
protected void readInternalImpl(ObjectDataInput in) throws IOException {
targetUuid = in.readUTF();
masterTime = in.readLong();
int size = in.readInt();
memberInfos = new ArrayList<MemberInfo>(size);
while (size-- > 0) {
MemberInfo memberInfo = new MemberInfo();
memberInfo.readData(in);
memberInfos.add(memberInfo);
}
partitionRuntimeState = in.readObject();
returnResponse = in.readBoolean();
}
@Override
protected void writeInternalImpl(ObjectDataOutput out) throws IOException {
out.writeUTF(targetUuid);
out.writeLong(masterTime);
out.writeInt(memberInfos.size());
for (MemberInfo memberInfo : memberInfos) {
memberInfo.writeData(out);
}
out.writeObject(partitionRuntimeState);
out.writeBoolean(returnResponse);
}
@Override
protected void toString(StringBuilder sb) {
super.toString(sb);
sb.append(", targetUuid=").append(targetUuid);
sb.append(", members=");
for (MemberInfo address : memberInfos) {
sb.append(address).append(' ');
}
}
@Override
public int getId() {
return ClusterDataSerializerHook.MEMBER_INFO_UPDATE;
}
}