package org.infinispan.xsite; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Objects; import java.util.concurrent.CompletableFuture; import org.infinispan.commands.remote.BaseRpcCommand; import org.infinispan.commons.marshall.MarshallUtil; import org.infinispan.util.ByteString; import org.infinispan.util.concurrent.CompletableFutures; /** * Command used for handling XSiteReplication administrative operations. * * @author Mircea Markus * @since 5.2 */ public class XSiteAdminCommand extends BaseRpcCommand { public static final int COMMAND_ID = 32; public enum AdminOperation { SITE_STATUS, STATUS, TAKE_OFFLINE, BRING_ONLINE, AMEND_TAKE_OFFLINE; private static final AdminOperation[] CACHED_VALUES = values(); private static AdminOperation valueOf(int index) { return CACHED_VALUES[index]; } } public enum Status { OFFLINE, ONLINE } private String siteName; private Integer afterFailures; private Long minTimeToWait; private AdminOperation adminOperation; private BackupSender backupSender; @SuppressWarnings("unused") public XSiteAdminCommand() { super(null);// For command id uniqueness test } public XSiteAdminCommand(ByteString cacheName) { super(cacheName);// For command id uniqueness test } public XSiteAdminCommand(ByteString cacheName, String siteName, AdminOperation op, Integer afterFailures, Long minTimeToWait) { this(cacheName); this.siteName = siteName; this.adminOperation = op; this.afterFailures = afterFailures; this.minTimeToWait = minTimeToWait; } public void init(BackupSender backupSender) { this.backupSender = backupSender; } @Override public CompletableFuture<Object> invokeAsync() throws Throwable { switch (adminOperation) { case SITE_STATUS: { if (backupSender.getOfflineStatus(siteName).isOffline()) { return CompletableFuture.completedFuture(Status.OFFLINE); } else { return CompletableFuture.completedFuture(Status.ONLINE); } } case STATUS: { return CompletableFuture.completedFuture(backupSender.status()); } case TAKE_OFFLINE: { return CompletableFuture.completedFuture(backupSender.takeSiteOffline(siteName)); } case BRING_ONLINE: { return CompletableFuture.completedFuture(backupSender.bringSiteOnline(siteName)); } case AMEND_TAKE_OFFLINE: { backupSender.getOfflineStatus(siteName).amend(afterFailures, minTimeToWait); return CompletableFutures.completedNull(); } default: { throw new IllegalStateException("Unhandled admin operation " + adminOperation); } } } @Override public byte getCommandId() { return COMMAND_ID; } @Override public void writeTo(ObjectOutput output) throws IOException { MarshallUtil.marshallEnum(adminOperation, output); switch (adminOperation) { case SITE_STATUS: case TAKE_OFFLINE: case BRING_ONLINE: output.writeUTF(siteName); return; case AMEND_TAKE_OFFLINE: output.writeUTF(siteName); output.writeObject(afterFailures); output.writeObject(minTimeToWait); return; case STATUS: return; default: throw new IllegalStateException("Unknown admin operation " + adminOperation); } } @Override public void readFrom(ObjectInput input) throws IOException, ClassNotFoundException { adminOperation = Objects.requireNonNull(MarshallUtil.unmarshallEnum(input, AdminOperation::valueOf)); switch (adminOperation) { case SITE_STATUS: case TAKE_OFFLINE: case BRING_ONLINE: siteName = input.readUTF(); return; case AMEND_TAKE_OFFLINE: siteName = input.readUTF(); afterFailures = (Integer) input.readObject(); minTimeToWait = (Long) input.readObject(); return; case STATUS: return; default: throw new IllegalStateException("Unknown admin operation " + adminOperation); } } @Override public final boolean isReturnValueExpected() { return true; } @Override public String toString() { return "XSiteAdminCommand{" + "siteName='" + siteName + '\'' + ", afterFailures=" + afterFailures + ", minTimeToWait=" + minTimeToWait + ", adminOperation=" + adminOperation + ", backupSender=" + backupSender + '}'; } }