blob: dad540201732d5777152187934ee8c21fb391e8f [file] [log] [blame]
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.je.rep;
import java.util.Set;
import com.sleepycat.je.Environment;
import com.sleepycat.je.OperationFailureException;
import com.sleepycat.je.Transaction;
import com.sleepycat.je.Durability.ReplicaAckPolicy;
import com.sleepycat.je.txn.Locker;
/**
* Thrown by {@link Environment#beginTransaction} and {@link
* Transaction#commit} when these operations are initiated at a Master which is
* not in contact with a quorum of Replicas as determined by the {@link
* ReplicaAckPolicy} that is in effect for the operation.
*/
public class InsufficientReplicasException extends OperationFailureException {
private static final long serialVersionUID = 1;
private final ReplicaAckPolicy commitPolicy;
private final int requiredAckCount;
private final Set<String> availableReplicas;
/**
* Creates a Commit exception.
*
* @param ackPolicy the ack policy that could not be implemented
* @param requiredAckCount the replica acks required to satisfy the policy
* @param availableReplicas the set of available Replicas
*/
public InsufficientReplicasException(Locker locker,
ReplicaAckPolicy ackPolicy,
int requiredAckCount,
Set<String> availableReplicas) {
super(locker, true /*abortOnly*/,
makeMsg(ackPolicy, requiredAckCount, availableReplicas),
null /*cause*/);
this.commitPolicy = ackPolicy;
this.requiredAckCount = requiredAckCount;
this.availableReplicas = availableReplicas;
}
/**
* For internal use only.
* @hidden
*/
private InsufficientReplicasException(String message,
InsufficientReplicasException
cause) {
super(message, cause);
this.commitPolicy = cause.commitPolicy;
this.requiredAckCount = cause.requiredAckCount;
this.availableReplicas = cause.availableReplicas;
}
/**
* For internal use only.
* @hidden
*/
@Override
public OperationFailureException wrapSelf(String msg) {
return new InsufficientReplicasException(msg, this);
}
/**
* Returns the Replica ack policy that was in effect for the transaction.
*
* @return the Replica ack policy
*/
public ReplicaAckPolicy getCommitPolicy() {
return commitPolicy;
}
/**
* Returns the number of nodes (including the master) that were
* required to be active in order to satisfy the Replica ack
* policy.
*
* @return the required number of nodes
*/
public int getRequiredNodeCount() {
return requiredAckCount + 1;
}
/**
* Returns the set of Replicas that were in contact with the master at the
* time of the commit operation.
*
* @return a set of Replica node names
*/
public Set<String> getAvailableReplicas() {
return availableReplicas;
}
private static String makeMsg(ReplicaAckPolicy commitPolicy,
int requiredAckCount,
Set<String> availableReplicas) {
String errorPrefix = "Commit policy: " + commitPolicy.name() +
" required " + requiredAckCount + " replica" +
(requiredAckCount > 1 ? "s. " : ". ");
switch (availableReplicas.size()) {
case 0:
return errorPrefix + "But none were active with this master.";
case 1:
return errorPrefix + "Only replica: " + availableReplicas +
" was available.";
default:
return errorPrefix + " Only the following " +
availableReplicas.size() +
" replicas listed here were available: " +
availableReplicas;
}
}
}