
com.hazelcast.internal.cluster.impl.operations.OnJoinOp Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2008-2024, 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.cluster.Member;
import com.hazelcast.config.OnJoinPermissionOperationName;
import com.hazelcast.config.SecurityConfig;
import com.hazelcast.internal.cluster.ClusterService;
import com.hazelcast.internal.cluster.impl.ClusterDataSerializerHook;
import com.hazelcast.internal.cluster.impl.ClusterJoinManager;
import com.hazelcast.internal.cluster.impl.ClusterServiceImpl;
import com.hazelcast.internal.management.operation.UpdatePermissionConfigOperation;
import com.hazelcast.cluster.Address;
import com.hazelcast.nio.ObjectDataInput;
import com.hazelcast.nio.ObjectDataOutput;
import com.hazelcast.spi.impl.NodeEngine;
import com.hazelcast.spi.impl.operationservice.Operation;
import com.hazelcast.spi.impl.operationservice.OperationAccessor;
import com.hazelcast.spi.impl.operationservice.OperationResponseHandler;
import com.hazelcast.spi.impl.operationservice.OperationService;
import com.hazelcast.spi.impl.operationservice.TargetAware;
import com.hazelcast.spi.impl.operationservice.UrgentSystemOperation;
import java.io.IOException;
import java.util.Collection;
import java.util.Set;
import static com.hazelcast.internal.serialization.impl.SerializationUtil.readCollection;
import static com.hazelcast.internal.serialization.impl.SerializationUtil.writeCollection;
import static com.hazelcast.spi.impl.operationexecutor.OperationRunner.runDirect;
import static com.hazelcast.spi.impl.operationservice.OperationResponseHandlerFactory.createErrorLoggingResponseHandler;
import static com.hazelcast.internal.util.Preconditions.checkNegative;
import static com.hazelcast.internal.util.Preconditions.checkNotNull;
public class OnJoinOp
extends AbstractJoinOperation implements UrgentSystemOperation, TargetAware {
private Collection operations;
public OnJoinOp() {
}
public OnJoinOp(Collection ops) {
for (Operation op : ops) {
checkNotNull(op, "op can't be null");
checkNegative(op.getPartitionId(), "Post join operation can not have a partition ID!");
}
operations = ops;
}
@Override
public String getServiceName() {
return ClusterServiceImpl.SERVICE_NAME;
}
@Override
public void beforeRun() throws Exception {
if (!operations.isEmpty()) {
NodeEngine nodeEngine = getNodeEngine();
OperationResponseHandler responseHandler = createErrorLoggingResponseHandler(getLogger());
for (Operation op : operations) {
op.setNodeEngine(nodeEngine);
op.setOperationResponseHandler(responseHandler);
OperationAccessor.setCallerAddress(op, getCallerAddress());
OperationAccessor.setConnection(op, getConnection());
}
}
}
@Override
public void run() throws Exception {
run(null);
}
/**
* Used in {@link ClusterJoinManager#startJoin()} to prevent
* quadratic complexity during batched cluster joining
*
* @param skippedForBroadcast Set of {@link Address} to skip broadcasting
* to if we are master of a cluster
*/
public void runWithoutBroadcastTo(Set skippedForBroadcast) {
run(skippedForBroadcast);
}
private void run(Set skippedForBroadcast) {
if (!operations.isEmpty()) {
SecurityConfig securityConfig = getNodeEngine().getConfig().getSecurityConfig();
boolean runPermissionUpdates = securityConfig.getOnJoinPermissionOperation() == OnJoinPermissionOperationName.RECEIVE;
for (Operation op : operations) {
if ((op instanceof UpdatePermissionConfigOperation) && !runPermissionUpdates) {
continue;
}
try {
// not running via OperationService since we don't want any restrictions like cluster state check etc.
runDirect(op);
} catch (Exception e) {
getLogger().warning("Error while running post-join operation: " + op, e);
}
}
final ClusterService clusterService = getService();
// if executed on master, broadcast to all other members except sender (joining member)
if (clusterService.isMaster()) {
final OperationService operationService = getNodeEngine().getOperationService();
for (Member member : clusterService.getMembers()) {
if (skippedForBroadcast != null && skippedForBroadcast.contains(member.getAddress())) {
continue;
}
if (!member.localMember() && !member.getUuid().equals(getCallerUuid())) {
OnJoinOp operation = new OnJoinOp(operations);
operationService.invokeOnTarget(getServiceName(), operation, member.getAddress());
}
}
}
}
}
@Override
public void onExecutionFailure(Throwable e) {
for (Operation op : operations) {
onOperationFailure(op, e);
}
}
private void onOperationFailure(Operation op, Throwable e) {
try {
op.onExecutionFailure(e);
} catch (Throwable t) {
getLogger().warning("While calling operation.onFailure(). op: " + op, t);
}
}
@Override
public boolean validatesTarget() {
return false;
}
@Override
protected void writeInternal(ObjectDataOutput out) throws IOException {
writeCollection(operations, out);
}
@Override
protected void readInternal(ObjectDataInput in) throws IOException {
operations = readCollection(in);
}
@Override
protected void toString(StringBuilder sb) {
super.toString(sb);
sb.append(", operations=").append(operations);
}
@Override
public int getClassId() {
return ClusterDataSerializerHook.POST_JOIN;
}
@Override
public void setTarget(Address address) {
for (Operation op : operations) {
if (op instanceof TargetAware aware) {
aware.setTarget(address);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy