Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.activemq.artemis.core.server.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.client.impl.Topology;
import org.apache.activemq.artemis.core.client.impl.TopologyMemberImpl;
import org.apache.activemq.artemis.core.protocol.core.Channel;
import org.apache.activemq.artemis.core.protocol.core.ChannelHandler;
import org.apache.activemq.artemis.core.protocol.core.Packet;
import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.BackupRequestMessage;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.BackupResponseMessage;
import org.apache.activemq.artemis.core.remoting.server.RemotingService;
import org.apache.activemq.artemis.core.replication.ReplicationManager;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.cluster.ha.ColocatedHAManager;
import org.apache.activemq.artemis.core.server.cluster.ha.ColocatedPolicy;
import org.apache.activemq.artemis.core.server.cluster.ha.HAManager;
import org.apache.activemq.artemis.core.server.cluster.qourum.QuorumVote;
import org.apache.activemq.artemis.core.server.cluster.qourum.QuorumVoteHandler;
import org.apache.activemq.artemis.core.server.cluster.qourum.Vote;
import org.apache.activemq.artemis.spi.core.remoting.Acceptor;
public class ColocatedActivation extends LiveActivation {
private static final SimpleString REQUEST_BACKUP_QUORUM_VOTE = new SimpleString("RequestBackupQuorumVote");
private final ColocatedHAManager colocatedHAManager;
private final ColocatedPolicy colocatedPolicy;
LiveActivation liveActivation;
private final ActiveMQServerImpl server;
public ColocatedActivation(ActiveMQServerImpl activeMQServer,
ColocatedPolicy colocatedPolicy,
LiveActivation liveActivation) {
server = activeMQServer;
this.colocatedPolicy = colocatedPolicy;
this.liveActivation = liveActivation;
colocatedHAManager = new ColocatedHAManager(colocatedPolicy, server);
}
@Override
public void haStarted() {
server.getClusterManager().getQuorumManager().registerQuorumHandler(new RequestBackupQuorumVoteHandler());
//vote for a backup if required
if (colocatedPolicy.isRequestBackup()) {
server.getClusterManager().getQuorumManager().vote(new RequestBackupQuorumVote());
}
}
@Override
public void freezeConnections(RemotingService remotingService) {
liveActivation.freezeConnections(remotingService);
}
@Override
public void postConnectionFreeze() {
liveActivation.postConnectionFreeze();
}
@Override
public void preStorageClose() throws Exception {
liveActivation.preStorageClose();
}
@Override
public void sendLiveIsStopping() {
liveActivation.sendLiveIsStopping();
}
@Override
public ReplicationManager getReplicationManager() {
return liveActivation.getReplicationManager();
}
@Override
public HAManager getHAManager() {
return colocatedHAManager;
}
@Override
public void run() {
liveActivation.run();
}
@Override
public void close(boolean permanently, boolean restarting) throws Exception {
liveActivation.close(permanently, restarting);
}
@Override
public ChannelHandler getActivationChannelHandler(final Channel channel, final Acceptor acceptorUsed) {
final ChannelHandler activationChannelHandler = liveActivation.getActivationChannelHandler(channel, acceptorUsed);
return new ChannelHandler() {
@Override
public void handlePacket(Packet packet) {
if (packet.getType() == PacketImpl.BACKUP_REQUEST) {
BackupRequestMessage backupRequestMessage = (BackupRequestMessage) packet;
boolean started = false;
try {
started = colocatedHAManager.activateBackup(backupRequestMessage.getBackupSize(), backupRequestMessage.getJournalDirectory(), backupRequestMessage.getBindingsDirectory(), backupRequestMessage.getLargeMessagesDirectory(), backupRequestMessage.getPagingDirectory(), backupRequestMessage.getNodeID());
} catch (Exception e) {
ActiveMQServerLogger.LOGGER.failedToActivateBackup(e);
}
channel.send(new BackupResponseMessage(started));
} else if (activationChannelHandler != null) {
activationChannelHandler.handlePacket(packet);
}
}
};
}
/**
* A vote handler for incoming backup request votes
*/
private final class RequestBackupQuorumVoteHandler implements QuorumVoteHandler {
@Override
public Vote vote(Vote vote) {
int size = colocatedHAManager.getBackupServers().size();
return new RequestBackupVote(size, server.getNodeID().toString(), size < colocatedPolicy.getMaxBackups());
}
@Override
public SimpleString getQuorumName() {
return REQUEST_BACKUP_QUORUM_VOTE;
}
@Override
public Vote decode(ActiveMQBuffer voteBuffer) {
RequestBackupVote requestBackupVote = new RequestBackupVote();
requestBackupVote.decode(voteBuffer);
return requestBackupVote;
}
}
/**
* a quorum vote for backup requests
*/
private final class RequestBackupQuorumVote extends QuorumVote> {
//the available nodes that we can request
private final List> nodes = new ArrayList<>();
private RequestBackupQuorumVote() {
super(REQUEST_BACKUP_QUORUM_VOTE);
}
@Override
public Vote connected() {
return new RequestBackupVote();
}
@Override
public Vote notConnected() {
return new RequestBackupVote();
}
@Override
public void vote(RequestBackupVote vote) {
//if the returned vote is available add it to the nodes we can request
if (vote.backupAvailable) {
nodes.add(vote.getVote());
}
}
@Override
public Pair getDecision() {
//sort the nodes by how many backups they have and choose the first
Collections.sort(nodes, new Comparator>() {
@Override
public int compare(Pair o1, Pair o2) {
return o1.getB().compareTo(o2.getB());
}
});
return nodes.get(0);
}
@Override
public void allVotesCast(Topology voteTopology) {
//if we have any nodes that we can request then send a request
if (nodes.size() > 0) {
Pair decision = getDecision();
TopologyMemberImpl member = voteTopology.getMember(decision.getA());
try {
boolean backupStarted = colocatedHAManager.requestBackup(member.getConnector(), decision.getB().intValue(), !colocatedPolicy.isSharedStore());
if (!backupStarted) {
nodes.clear();
server.getScheduledPool().schedule(new Runnable() {
@Override
public void run() {
server.getClusterManager().getQuorumManager().vote(new RequestBackupQuorumVote());
}
}, colocatedPolicy.getBackupRequestRetryInterval(), TimeUnit.MILLISECONDS);
}
} catch (Exception e) {
ActiveMQServerLogger.LOGGER.failedToSendRequestToNode(e);
}
} else {
nodes.clear();
server.getScheduledPool().schedule(new Runnable() {
@Override
public void run() {
server.getClusterManager().getQuorumManager().vote(RequestBackupQuorumVote.this);
}
}, colocatedPolicy.getBackupRequestRetryInterval(), TimeUnit.MILLISECONDS);
}
}
@Override
public SimpleString getName() {
return REQUEST_BACKUP_QUORUM_VOTE;
}
}
class RequestBackupVote extends Vote> {
private int backupsSize;
private String nodeID;
private boolean backupAvailable;
RequestBackupVote() {
backupsSize = -1;
}
RequestBackupVote(int backupsSize, String nodeID, boolean backupAvailable) {
this.backupsSize = backupsSize;
this.nodeID = nodeID;
this.backupAvailable = backupAvailable;
}
@Override
public void encode(ActiveMQBuffer buff) {
buff.writeInt(backupsSize);
buff.writeNullableString(nodeID);
buff.writeBoolean(backupAvailable);
}
@Override
public void decode(ActiveMQBuffer buff) {
backupsSize = buff.readInt();
nodeID = buff.readNullableString();
backupAvailable = buff.readBoolean();
}
@Override
public boolean isRequestServerVote() {
return true;
}
@Override
public Pair getVote() {
return new Pair<>(nodeID, backupsSize);
}
@Override
public String toString() {
return "RequestBackupVote [backupsSize=" + backupsSize + ", nodeID=" + nodeID + ", backupAvailable=" + backupAvailable + "]";
}
}
}