/src/frontend/org/voltdb/exceptions/SerializableException.java
https://github.com/VoltDB/voltdb · Java · 283 lines · 184 code · 26 blank · 73 comment · 8 complexity · 908653f73a0a09cf8fde7650a2ce0f03 MD5 · raw file
- /* This file is part of VoltDB.
- * Copyright (C) 2008-2022 Volt Active Data Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with VoltDB. If not, see <http://www.gnu.org/licenses/>.
- */
- package org.voltdb.exceptions;
- import java.io.PrintStream;
- import java.io.PrintWriter;
- import java.io.StringWriter;
- import java.io.UnsupportedEncodingException;
- import java.nio.ByteBuffer;
- import org.json_voltpatches.JSONString;
- import org.json_voltpatches.JSONStringer;
- import org.voltdb.ClientResponseImpl;
- import org.voltdb.VoltProcedure;
- import org.voltdb.client.ClientResponse;
- /**
- * Base class for runtime exceptions that can be serialized to ByteBuffers without involving Java's
- * serialization mechanism
- *
- */
- public class SerializableException extends VoltProcedure.VoltAbortException implements JSONString {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- /**
- * Storage for the detailed message describing the error that generated this exception
- */
- private final String m_message;
- /**
- * Enum correlating the integer ordinals that are serialized as the type of an exception
- * with the class that deserializes that type.
- *
- */
- protected enum SerializableExceptions {
- None() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return null;
- }
- },
- EEException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new EEException(b);
- }
- },
- SQLException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new SQLException(b);
- }
- },
- ConstraintFailureException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new ConstraintFailureException(b);
- }
- },
- InterruptException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new InterruptException(b);
- }
- },
- TransactionRestartException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new TransactionRestartException(b);
- }
- },
- TransactionTerminationException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new TransactionTerminationException(b);
- }
- },
- SpecifiedException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new SpecifiedException(b);
- }
- },
- GenericSerializableException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new SerializableException(b);
- }
- },
- MispartitionedException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new MispartitionedException(b);
- }
- },
- ReplicatedTableException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new ReplicatedTableException(b);
- }
- },
- DrTableNotFoundException() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new DRTableNotFoundException(b);
- }
- },
- InvalidMessage() {
- @Override
- protected SerializableException deserializeException(ByteBuffer b) {
- return new InvalidMessageException(b);
- }
- };
- abstract protected SerializableException deserializeException(ByteBuffer b);
- }
- public SerializableException() {
- m_message = null;
- }
- public SerializableException(String message) {
- m_message = message;
- }
- public SerializableException(Throwable t) {
- final StringWriter sw = new StringWriter();
- final PrintWriter pw = new PrintWriter(sw);
- t.printStackTrace(pw);
- pw.flush();
- m_message = sw.toString();
- }
- public SerializableException(ByteBuffer b) {
- final int messageLength = b.getInt();
- final byte messageBytes[] = new byte[messageLength];
- b.get(messageBytes);
- try {
- m_message = new String(messageBytes, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * Get the detailed message describing the error that generated this exception
- */
- @Override
- public String getMessage() { return m_message; }
- /**
- * Override this method if the ClientResponse sent back must contain
- * result rows with additional information.
- *
- * @param cr
- */
- public void setClientResponseResults(ClientResponseImpl cr) {
- // Does nothing by default
- }
- /**
- * Number of bytes necessary to store the serialized representation of this exception
- * @return Number of bytes
- */
- public int getSerializedSize() {
- // sizes: as near as I can tell,
- // 5 is sizeof(int) for buffer length and sizeof(byte) for exception type
- // 4 is sizeof(int) for message string length
- if (m_message == null) {
- return 5 + 4 + p_getSerializedSize();
- }
- return 5 + 4 + m_message.getBytes().length + p_getSerializedSize();//one byte ordinal and 4 byte length
- }
- /**
- * Method for subclasses to implement that returns the number of bytes necessary to store
- * subclass data
- * @return Number of bytes necessary to store subclass data
- */
- protected int p_getSerializedSize() {
- return 0;
- }
- /**
- * Serialize this exception to the supplied byte buffer
- * @param b ByteBuffer to serialize this exception to
- */
- public void serializeToBuffer(ByteBuffer b) {
- assert(getSerializedSize() <= b.remaining());
- b.putInt(getSerializedSize() - 4);
- b.put((byte)getExceptionType().ordinal());
- if (m_message != null) {
- final byte messageBytes[] = m_message.getBytes();
- b.putInt(messageBytes.length);
- b.put(messageBytes);
- } else {
- b.putInt(0);
- }
- p_serializeToBuffer(b);
- }
- /**
- * Method for subclasses to implement that serializes the subclass's contents to
- * the ByteBuffer
- * @param b ByteBuffer to serialize the subclass contents to
- */
- protected void p_serializeToBuffer(ByteBuffer b) {}
- /**
- * Method for subclasses to specify what constant from the SerializableExceptions enum
- * is defined for this type of exception
- * @return Type of exception
- */
- protected SerializableExceptions getExceptionType() {
- return SerializableExceptions.GenericSerializableException;
- }
- /**
- * Deserialize an exception (if any) from the ByteBuffer
- * @param b ByteBuffer containing the exception to be deserialized
- * @return A deserialized exception if one was serialized or null
- */
- public static SerializableException deserializeFromBuffer(ByteBuffer b) {
- final int length = b.getInt();
- if (length == 0) {
- return null;
- }
- final int ordinal = b.get();
- assert (ordinal != SerializableExceptions.None.ordinal());
- return SerializableExceptions.values()[ordinal].deserializeException(b);
- }
- @Override
- public byte getClientResponseStatus() {
- return ClientResponse.UNEXPECTED_FAILURE;
- }
- @Override
- public void printStackTrace(PrintStream s) {
- s.print(getMessage());
- }
- @Override
- public void printStackTrace(PrintWriter p) {
- p.print(getMessage());
- }
- @Override
- public String toJSONString() {
- try {
- JSONStringer js = new JSONStringer();
- js.object();
- js.keySymbolValuePair("type", getExceptionType().ordinal());
- js.keySymbolValuePair("message", m_message);
- js.endObject();
- return js.toString();
- }
- catch (Exception e) {
- return "{ error: \"Unable to serialize exception.\" }";
- }
- }
- }