blob: 06826a672ede9796b8190a992d63969d823f2bc4 [file] [log] [blame]
/*
* 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.zookeeper;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.yetus.audience.InterfaceAudience;
@InterfaceAudience.Public
public abstract class KeeperException extends Exception {
/**
* All multi-requests that result in an exception retain the results
* here so that it is possible to examine the problems in the catch
* scope. Non-multi requests will get a null if they try to access
* these results.
*/
private List<OpResult> results;
/**
* All non-specific keeper exceptions should be constructed via
* this factory method in order to guarantee consistency in error
* codes and such. If you know the error code, then you should
* construct the special purpose exception directly. That will
* allow you to have the most specific possible declarations of
* what exceptions might actually be thrown.
*
* @param code The error code.
* @param path The ZooKeeper path being operated on.
* @return The specialized exception, presumably to be thrown by
* the caller.
*/
public static KeeperException create(Code code, String path) {
KeeperException r = create(code);
r.path = path;
return r;
}
/**
* @deprecated deprecated in 3.1.0, use {@link #create(Code, String)}
* instead
*/
@Deprecated
public static KeeperException create(int code, String path) {
KeeperException r = create(Code.get(code));
r.path = path;
return r;
}
/**
* @deprecated deprecated in 3.1.0, use {@link #create(Code)}
* instead
*/
@Deprecated
public static KeeperException create(int code) {
return create(Code.get(code));
}
/**
* All non-specific keeper exceptions should be constructed via
* this factory method in order to guarantee consistency in error
* codes and such. If you know the error code, then you should
* construct the special purpose exception directly. That will
* allow you to have the most specific possible declarations of
* what exceptions might actually be thrown.
*
* @param code The error code of your new exception. This will
* also determine the specific type of the exception that is
* returned.
* @return The specialized exception, presumably to be thrown by
* the caller.
*/
public static KeeperException create(Code code) {
switch (code) {
case SYSTEMERROR:
return new SystemErrorException();
case RUNTIMEINCONSISTENCY:
return new RuntimeInconsistencyException();
case DATAINCONSISTENCY:
return new DataInconsistencyException();
case CONNECTIONLOSS:
return new ConnectionLossException();
case MARSHALLINGERROR:
return new MarshallingErrorException();
case UNIMPLEMENTED:
return new UnimplementedException();
case OPERATIONTIMEOUT:
return new OperationTimeoutException();
case NEWCONFIGNOQUORUM:
return new NewConfigNoQuorum();
case RECONFIGINPROGRESS:
return new ReconfigInProgress();
case BADARGUMENTS:
return new BadArgumentsException();
case APIERROR:
return new APIErrorException();
case NONODE:
return new NoNodeException();
case NOAUTH:
return new NoAuthException();
case BADVERSION:
return new BadVersionException();
case NOCHILDRENFOREPHEMERALS:
return new NoChildrenForEphemeralsException();
case NODEEXISTS:
return new NodeExistsException();
case INVALIDACL:
return new InvalidACLException();
case AUTHFAILED:
return new AuthFailedException();
case NOTEMPTY:
return new NotEmptyException();
case SESSIONEXPIRED:
return new SessionExpiredException();
case INVALIDCALLBACK:
return new InvalidCallbackException();
case SESSIONMOVED:
return new SessionMovedException();
case NOTREADONLY:
return new NotReadOnlyException();
case EPHEMERALONLOCALSESSION:
return new EphemeralOnLocalSessionException();
case NOWATCHER:
return new NoWatcherException();
case RECONFIGDISABLED:
return new ReconfigDisabledException();
case SESSIONCLOSEDREQUIRESASLAUTH:
return new SessionClosedRequireAuthException();
case REQUESTTIMEOUT:
return new RequestTimeoutException();
case QUOTAEXCEEDED:
return new QuotaExceededException();
case THROTTLEDOP:
return new ThrottledOpException();
case OK:
default:
throw new IllegalArgumentException("Invalid exception code:" + code.code);
}
}
/**
* Set the code for this exception
* @param code error code
* @deprecated deprecated in 3.1.0, exceptions should be immutable, this
* method should not be used
*/
@Deprecated
public void setCode(int code) {
this.code = Code.get(code);
}
/** This interface contains the original static final int constants
* which have now been replaced with an enumeration in Code. Do not
* reference this class directly, if necessary (legacy code) continue
* to access the constants through Code.
* Note: an interface is used here due to the fact that enums cannot
* reference constants defined within the same enum as said constants
* are considered initialized _after_ the enum itself. By using an
* interface as a super type this allows the deprecated constants to
* be initialized first and referenced when constructing the enums. I
* didn't want to have constants declared twice. This
* interface should be private, but it's declared public to enable
* javadoc to include in the user API spec.
*/
@SuppressWarnings("DeprecatedIsStillUsed") // still used in Code - kept until 4.0
@Deprecated
@InterfaceAudience.Public
public interface CodeDeprecated {
/**
* @deprecated deprecated in 3.1.0, use {@link Code#OK} instead
*/
@Deprecated
int Ok = 0;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#SYSTEMERROR} instead
*/
@Deprecated
int SystemError = -1;
/**
* @deprecated deprecated in 3.1.0, use
* {@link Code#RUNTIMEINCONSISTENCY} instead
*/
@Deprecated
int RuntimeInconsistency = -2;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#DATAINCONSISTENCY}
* instead
*/
@Deprecated
int DataInconsistency = -3;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#CONNECTIONLOSS}
* instead
*/
@Deprecated
int ConnectionLoss = -4;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#MARSHALLINGERROR}
* instead
*/
@Deprecated
int MarshallingError = -5;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#UNIMPLEMENTED}
* instead
*/
@Deprecated
int Unimplemented = -6;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#OPERATIONTIMEOUT}
* instead
*/
@Deprecated
int OperationTimeout = -7;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#BADARGUMENTS}
* instead
*/
@Deprecated
int BadArguments = -8;
@Deprecated
int UnknownSession = -12;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#NEWCONFIGNOQUORUM}
* instead
*/
@Deprecated
int NewConfigNoQuorum = -13;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#RECONFIGINPROGRESS}
* instead
*/
@Deprecated
int ReconfigInProgress = -14;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#APIERROR} instead
*/
@Deprecated
int APIError = -100;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#NONODE} instead
*/
@Deprecated
int NoNode = -101;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#NOAUTH} instead
*/
@Deprecated
int NoAuth = -102;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#BADVERSION} instead
*/
@Deprecated
int BadVersion = -103;
/**
* @deprecated deprecated in 3.1.0, use
* {@link Code#NOCHILDRENFOREPHEMERALS}
* instead
*/
@Deprecated
int NoChildrenForEphemerals = -108;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#NODEEXISTS} instead
*/
@Deprecated
int NodeExists = -110;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#NOTEMPTY} instead
*/
@Deprecated
int NotEmpty = -111;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#SESSIONEXPIRED} instead
*/
@Deprecated
int SessionExpired = -112;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#INVALIDCALLBACK}
* instead
*/
@Deprecated
int InvalidCallback = -113;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#INVALIDACL} instead
*/
@Deprecated
int InvalidACL = -114;
/**
* @deprecated deprecated in 3.1.0, use {@link Code#AUTHFAILED} instead
*/
@Deprecated
int AuthFailed = -115;
// This value will be used directly in {@link CODE#SESSIONMOVED}
// public static final int SessionMoved = -118;
@Deprecated
int EphemeralOnLocalSession = -120;
}
/** Codes which represent the various KeeperException
* types. This enum replaces the deprecated earlier static final int
* constants. The old, deprecated, values are in "camel case" while the new
* enum values are in all CAPS.
*/
@InterfaceAudience.Public
public enum Code implements CodeDeprecated {
/** Everything is OK */
OK(Ok),
/** System and server-side errors.
* This is never thrown by the server, it shouldn't be used other than
* to indicate a range. Specifically error codes greater than this
* value, but lesser than {@link #APIERROR}, are system errors.
*/
SYSTEMERROR(SystemError),
/** A runtime inconsistency was found */
RUNTIMEINCONSISTENCY(RuntimeInconsistency),
/** A data inconsistency was found */
DATAINCONSISTENCY(DataInconsistency),
/** Connection to the server has been lost */
CONNECTIONLOSS(ConnectionLoss),
/** Error while marshalling or unmarshalling data */
MARSHALLINGERROR(MarshallingError),
/** Operation is unimplemented */
UNIMPLEMENTED(Unimplemented),
/** Operation timeout */
OPERATIONTIMEOUT(OperationTimeout),
/** Invalid arguments */
BADARGUMENTS(BadArguments),
/** No quorum of new config is connected and up-to-date with the leader of last commmitted config - try
* invoking reconfiguration after new servers are connected and synced */
NEWCONFIGNOQUORUM(NewConfigNoQuorum),
/** Another reconfiguration is in progress -- concurrent reconfigs not supported (yet) */
RECONFIGINPROGRESS(ReconfigInProgress),
/** Unknown session (internal server use only) */
UNKNOWNSESSION(UnknownSession),
/** API errors.
* This is never thrown by the server, it shouldn't be used other than
* to indicate a range. Specifically error codes greater than this
* value are API errors (while values less than this indicate a
* {@link #SYSTEMERROR}).
*/
APIERROR(APIError),
/** Node does not exist */
NONODE(NoNode),
/** Not authenticated */
NOAUTH(NoAuth),
/** Version conflict
In case of reconfiguration: reconfig requested from config version X but last seen config has a different version Y */
BADVERSION(BadVersion),
/** Ephemeral nodes may not have children */
NOCHILDRENFOREPHEMERALS(NoChildrenForEphemerals),
/** The node already exists */
NODEEXISTS(NodeExists),
/** The node has children */
NOTEMPTY(NotEmpty),
/** The session has been expired by the server */
SESSIONEXPIRED(SessionExpired),
/** Invalid callback specified */
INVALIDCALLBACK(InvalidCallback),
/** Invalid ACL specified */
INVALIDACL(InvalidACL),
/** Client authentication failed */
AUTHFAILED(AuthFailed),
/** Session moved to another server, so operation is ignored */
SESSIONMOVED(-118),
/** State-changing request is passed to read-only server */
NOTREADONLY(-119),
/** Attempt to create ephemeral node on a local session */
EPHEMERALONLOCALSESSION(EphemeralOnLocalSession),
/** Attempts to remove a non-existing watcher */
NOWATCHER(-121),
/** Request not completed within max allowed time.*/
REQUESTTIMEOUT(-122),
/** Attempts to perform a reconfiguration operation when reconfiguration feature is disabled. */
RECONFIGDISABLED(-123),
/** The session has been closed by server because server requires client to do authentication
* with configured authentication scheme at the server, but client is not configured with
* required authentication scheme or configured but authentication failed
* (i.e. wrong credential used.). */
SESSIONCLOSEDREQUIRESASLAUTH(-124),
/** Exceeded the quota that was set on the path.*/
QUOTAEXCEEDED(-125),
/** Operation was throttled and not executed at all. This error code indicates that zookeeper server
* is under heavy load and can't process incoming requests at full speed; please retry with back off.
*/
THROTTLEDOP (-127);
private static final Map<Integer, Code> lookup = new HashMap<>();
static {
for (Code c : EnumSet.allOf(Code.class)) {
lookup.put(c.code, c);
}
}
private final int code;
Code(int code) {
this.code = code;
}
/**
* Get the int value for a particular Code.
* @return error code as integer
*/
public int intValue() {
return code;
}
/**
* Get the Code value for a particular integer error code
* @param code int error code
* @return Code value corresponding to specified int code, if null throws IllegalArgumentException
*/
public static Code get(int code) {
Code codeVal = lookup.get(code);
if (codeVal == null) {
throw new IllegalArgumentException("The current client version cannot lookup this code:" + code);
}
return codeVal;
}
}
static String getCodeMessage(Code code) {
switch (code) {
case OK:
return "ok";
case SYSTEMERROR:
return "SystemError";
case RUNTIMEINCONSISTENCY:
return "RuntimeInconsistency";
case DATAINCONSISTENCY:
return "DataInconsistency";
case CONNECTIONLOSS:
return "ConnectionLoss";
case MARSHALLINGERROR:
return "MarshallingError";
case NEWCONFIGNOQUORUM:
return "NewConfigNoQuorum";
case RECONFIGINPROGRESS:
return "ReconfigInProgress";
case UNIMPLEMENTED:
return "Unimplemented";
case OPERATIONTIMEOUT:
return "OperationTimeout";
case BADARGUMENTS:
return "BadArguments";
case APIERROR:
return "APIError";
case NONODE:
return "NoNode";
case NOAUTH:
return "NoAuth";
case BADVERSION:
return "BadVersion";
case NOCHILDRENFOREPHEMERALS:
return "NoChildrenForEphemerals";
case NODEEXISTS:
return "NodeExists";
case INVALIDACL:
return "InvalidACL";
case AUTHFAILED:
return "AuthFailed";
case NOTEMPTY:
return "Directory not empty";
case SESSIONEXPIRED:
return "Session expired";
case INVALIDCALLBACK:
return "Invalid callback";
case SESSIONMOVED:
return "Session moved";
case NOTREADONLY:
return "Not a read-only call";
case EPHEMERALONLOCALSESSION:
return "Ephemeral node on local session";
case NOWATCHER:
return "No such watcher";
case RECONFIGDISABLED:
return "Reconfig is disabled";
case SESSIONCLOSEDREQUIRESASLAUTH:
return "Session closed because client failed to authenticate";
case QUOTAEXCEEDED:
return "Quota has exceeded";
case THROTTLEDOP:
return "Op throttled due to high load";
default:
return "Unknown error " + code;
}
}
private Code code;
private String path;
public KeeperException(Code code) {
this.code = code;
}
KeeperException(Code code, String path) {
this.code = code;
this.path = path;
}
/**
* Read the error code for this exception
* @return the error code for this exception
* @deprecated deprecated in 3.1.0, use {@link #code()} instead
*/
@Deprecated
public int getCode() {
return code.code;
}
/**
* Read the error Code for this exception
* @return the error Code for this exception
*/
public Code code() {
return code;
}
/**
* Read the path for this exception
* @return the path associated with this error, null if none
*/
public String getPath() {
return path;
}
@Override
public String getMessage() {
if (path == null || path.isEmpty()) {
return "KeeperErrorCode = " + getCodeMessage(code);
}
return "KeeperErrorCode = " + getCodeMessage(code) + " for " + path;
}
void setMultiResults(List<OpResult> results) {
this.results = results;
}
/**
* If this exception was thrown by a multi-request then the (partial) results
* and error codes can be retrieved using this getter.
* @return A copy of the list of results from the operations in the multi-request.
*
* @since 3.4.0
*
*/
public List<OpResult> getResults() {
return results != null ? new ArrayList<OpResult>(results) : null;
}
/**
* @see Code#APIERROR
*/
@InterfaceAudience.Public
public static class APIErrorException extends KeeperException {
public APIErrorException() {
super(Code.APIERROR);
}
}
/**
* @see Code#AUTHFAILED
*/
@InterfaceAudience.Public
public static class AuthFailedException extends KeeperException {
public AuthFailedException() {
super(Code.AUTHFAILED);
}
}
/**
* @see Code#BADARGUMENTS
*/
@InterfaceAudience.Public
public static class BadArgumentsException extends KeeperException {
public BadArgumentsException() {
super(Code.BADARGUMENTS);
}
public BadArgumentsException(String path) {
super(Code.BADARGUMENTS, path);
}
}
/**
* @see Code#BADVERSION
*/
@InterfaceAudience.Public
public static class BadVersionException extends KeeperException {
public BadVersionException() {
super(Code.BADVERSION);
}
public BadVersionException(String path) {
super(Code.BADVERSION, path);
}
}
/**
* @see Code#CONNECTIONLOSS
*/
@InterfaceAudience.Public
public static class ConnectionLossException extends KeeperException {
public ConnectionLossException() {
super(Code.CONNECTIONLOSS);
}
}
/**
* @see Code#DATAINCONSISTENCY
*/
@InterfaceAudience.Public
public static class DataInconsistencyException extends KeeperException {
public DataInconsistencyException() {
super(Code.DATAINCONSISTENCY);
}
}
/**
* @see Code#INVALIDACL
*/
@InterfaceAudience.Public
public static class InvalidACLException extends KeeperException {
public InvalidACLException() {
super(Code.INVALIDACL);
}
public InvalidACLException(String path) {
super(Code.INVALIDACL, path);
}
}
/**
* @see Code#INVALIDCALLBACK
*/
@InterfaceAudience.Public
public static class InvalidCallbackException extends KeeperException {
public InvalidCallbackException() {
super(Code.INVALIDCALLBACK);
}
}
/**
* @see Code#MARSHALLINGERROR
*/
@InterfaceAudience.Public
public static class MarshallingErrorException extends KeeperException {
public MarshallingErrorException() {
super(Code.MARSHALLINGERROR);
}
}
/**
* @see Code#NOAUTH
*/
@InterfaceAudience.Public
public static class NoAuthException extends KeeperException {
public NoAuthException() {
super(Code.NOAUTH);
}
}
/**
* @see Code#NEWCONFIGNOQUORUM
*/
@InterfaceAudience.Public
public static class NewConfigNoQuorum extends KeeperException {
public NewConfigNoQuorum() {
super(Code.NEWCONFIGNOQUORUM);
}
}
/**
* @see Code#RECONFIGINPROGRESS
*/
@InterfaceAudience.Public
public static class ReconfigInProgress extends KeeperException {
public ReconfigInProgress() {
super(Code.RECONFIGINPROGRESS);
}
}
/**
* @see Code#NOCHILDRENFOREPHEMERALS
*/
@InterfaceAudience.Public
public static class NoChildrenForEphemeralsException extends KeeperException {
public NoChildrenForEphemeralsException() {
super(Code.NOCHILDRENFOREPHEMERALS);
}
public NoChildrenForEphemeralsException(String path) {
super(Code.NOCHILDRENFOREPHEMERALS, path);
}
}
/**
* @see Code#NODEEXISTS
*/
@InterfaceAudience.Public
public static class NodeExistsException extends KeeperException {
public NodeExistsException() {
super(Code.NODEEXISTS);
}
public NodeExistsException(String path) {
super(Code.NODEEXISTS, path);
}
}
/**
* @see Code#NONODE
*/
@InterfaceAudience.Public
public static class NoNodeException extends KeeperException {
public NoNodeException() {
super(Code.NONODE);
}
public NoNodeException(String path) {
super(Code.NONODE, path);
}
}
/**
* @see Code#NOTEMPTY
*/
@InterfaceAudience.Public
public static class NotEmptyException extends KeeperException {
public NotEmptyException() {
super(Code.NOTEMPTY);
}
public NotEmptyException(String path) {
super(Code.NOTEMPTY, path);
}
}
/**
* @see Code#OPERATIONTIMEOUT
*/
@InterfaceAudience.Public
public static class OperationTimeoutException extends KeeperException {
public OperationTimeoutException() {
super(Code.OPERATIONTIMEOUT);
}
}
/**
* @see Code#RUNTIMEINCONSISTENCY
*/
@InterfaceAudience.Public
public static class RuntimeInconsistencyException extends KeeperException {
public RuntimeInconsistencyException() {
super(Code.RUNTIMEINCONSISTENCY);
}
}
/**
* @see Code#SESSIONEXPIRED
*/
@InterfaceAudience.Public
public static class SessionExpiredException extends KeeperException {
public SessionExpiredException() {
super(Code.SESSIONEXPIRED);
}
}
/**
* @see Code#UNKNOWNSESSION
*/
@InterfaceAudience.Public
public static class UnknownSessionException extends KeeperException {
public UnknownSessionException() {
super(Code.UNKNOWNSESSION);
}
}
/**
* @see Code#SESSIONMOVED
*/
@InterfaceAudience.Public
public static class SessionMovedException extends KeeperException {
public SessionMovedException() {
super(Code.SESSIONMOVED);
}
}
/**
* @see Code#NOTREADONLY
*/
@InterfaceAudience.Public
public static class NotReadOnlyException extends KeeperException {
public NotReadOnlyException() {
super(Code.NOTREADONLY);
}
}
/**
* @see Code#EPHEMERALONLOCALSESSION
*/
@InterfaceAudience.Public
public static class EphemeralOnLocalSessionException extends KeeperException {
public EphemeralOnLocalSessionException() {
super(Code.EPHEMERALONLOCALSESSION);
}
}
/**
* @see Code#SYSTEMERROR
*/
@InterfaceAudience.Public
public static class SystemErrorException extends KeeperException {
public SystemErrorException() {
super(Code.SYSTEMERROR);
}
}
/**
* @see Code#UNIMPLEMENTED
*/
@InterfaceAudience.Public
public static class UnimplementedException extends KeeperException {
public UnimplementedException() {
super(Code.UNIMPLEMENTED);
}
}
/**
* @see Code#NOWATCHER
*/
@InterfaceAudience.Public
public static class NoWatcherException extends KeeperException {
public NoWatcherException() {
super(Code.NOWATCHER);
}
public NoWatcherException(String path) {
super(Code.NOWATCHER, path);
}
}
/**
* @see Code#RECONFIGDISABLED
*/
@InterfaceAudience.Public
public static class ReconfigDisabledException extends KeeperException {
public ReconfigDisabledException() {
super(Code.RECONFIGDISABLED);
}
public ReconfigDisabledException(String path) {
super(Code.RECONFIGDISABLED, path);
}
}
/**
* @see Code#SESSIONCLOSEDREQUIRESASLAUTH
*/
public static class SessionClosedRequireAuthException extends KeeperException {
public SessionClosedRequireAuthException() {
super(Code.SESSIONCLOSEDREQUIRESASLAUTH);
}
public SessionClosedRequireAuthException(String path) {
super(Code.SESSIONCLOSEDREQUIRESASLAUTH, path);
}
}
/**
* @see Code#REQUESTTIMEOUT
*/
public static class RequestTimeoutException extends KeeperException {
public RequestTimeoutException() {
super(Code.REQUESTTIMEOUT);
}
}
/**
* @see Code#QUOTAEXCEEDED
*/
@InterfaceAudience.Public
public static class QuotaExceededException extends KeeperException {
public QuotaExceededException() {
super(Code.QUOTAEXCEEDED);
}
public QuotaExceededException(String path) {
super(Code.QUOTAEXCEEDED, path);
}
}
/**
* @see Code#THROTTLEDOP
*/
public static class ThrottledOpException extends KeeperException {
public ThrottledOpException() {
super(Code.THROTTLEDOP);
}
}
}