org.voltdb.ClientResponseImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.voltdb.ClientResponseImpl.java

Source

/* This file is part of VoltDB.
 * Copyright (C) 2008-2010 VoltDB L.L.C.
 *
 * VoltDB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VoltDB 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.voltdb;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;

import org.apache.commons.collections15.map.ListOrderedMap;
import org.voltdb.client.ClientResponse;
import org.voltdb.exceptions.SerializableException;
import org.voltdb.messaging.FastDeserializer;
import org.voltdb.messaging.FastSerializable;
import org.voltdb.messaging.FastSerializer;

import edu.brown.hstore.HStoreConstants;
import edu.brown.hstore.Hstoreservice.Status;
import edu.brown.utils.StringUtil;

/**
 * Packages up the data to be sent back to the client as a stored
 * procedure response in one FastSerialziable object.
 *
 */
public class ClientResponseImpl implements FastSerializable, ClientResponse {
    private boolean setProperly = false;
    private Status status;
    private String statusString = null;
    private byte appStatus = Byte.MIN_VALUE;
    private String appStatusString = null;
    private VoltTable[] results = HStoreConstants.EMPTY_RESULT;

    private int clusterRoundTripTime = -1;
    private int clientRoundTripTime = -1;
    private SerializableException m_exception = null;

    // PAVLO
    private long txn_id;
    private int requestCounter = -1;
    private boolean throttle = false;
    private boolean singlepartition = false;
    private int basePartition = -1;
    private int restartCounter = 0;

    /** opaque data optionally provided by and returned to the client */
    private long clientHandle = -1;

    public ClientResponseImpl() {
    }

    /**
     * Used in the successful procedure invocation case.
     * @param client_handle TODO
     * @param status
     * @param results
     * @param extra
     */
    public ClientResponseImpl(long txn_id, long client_handle, int basePartition, Status status, byte appStatus,
            String appStatusString, VoltTable[] results, String statusString) {
        this(txn_id, client_handle, basePartition, status, appStatus, appStatusString, results, statusString, null);
    }

    /**
     * Another constructor for test and error responses
     * @param client_handle
     * @param status
     * @param results
     * @param extra
     */
    public ClientResponseImpl(long txn_id, long client_handle, int basePartition, Status status,
            VoltTable[] results, String statusString) {
        this(txn_id, client_handle, basePartition, status, Byte.MIN_VALUE, null, results, statusString, null);
    }

    /**
     * And another....
     * @param status
     * @param results
     * @param extra
     * @param e
     */
    public ClientResponseImpl(long txn_id, long client_handle, int basePartition, Status status,
            VoltTable[] results, String statusString, SerializableException e) {
        this(txn_id, client_handle, basePartition, status, Byte.MIN_VALUE, null, results, statusString, e);
    }

    /**
     * Use this when generating an error response in VoltProcedure
     * @param status
     * @param results
     * @param extra
     * @param e
     */
    public ClientResponseImpl(long txn_id, int basePartition, Status status, byte appStatus, String appStatusString,
            VoltTable results[], String extra, SerializableException e) {
        this(txn_id, -1, basePartition, status, appStatus, appStatusString, results, extra, e);
    }

    public ClientResponseImpl(long txn_id, long client_handle, int basePartition, Status status, byte appStatus,
            String appStatusString, VoltTable[] results, String statusString, SerializableException e) {
        this.init(txn_id, client_handle, basePartition, status, appStatus, appStatusString, results, statusString,
                e);
    }

    public void init(Long txn_id, long client_handle, int basePartition, Status status, VoltTable[] results,
            String statusString, SerializableException e) {
        this.init(txn_id, client_handle, basePartition, status, Byte.MIN_VALUE, null, results, statusString, e);
    }

    public void init(Long txn_id, long client_handle, int basePartition, Status status, byte appStatus,
            String appStatusString, VoltTable[] results, String statusString, SerializableException e) {
        this.txn_id = txn_id.longValue();
        this.clientHandle = client_handle;
        this.basePartition = basePartition;
        this.appStatus = appStatus;
        this.appStatusString = appStatusString;
        setResults(status, results, statusString, e);
    }

    @Override
    public boolean isInitialized() {
        return (this.txn_id != -1);
    }

    @Override
    public void finish() {
        this.txn_id = -1;
        this.clientHandle = -1;
        this.status = null;
        this.results = null;
        this.restartCounter = 0;
    }

    // ----------------------------------------------------------------------------
    // SPECIAL BYTEBUFFER MODIFIERS
    // ----------------------------------------------------------------------------

    /**
     * Set the server timestamp marker without deserializing it first
     * @param arr
     * @param flag
     */
    public static void setServerTimestamp(ByteBuffer b, int val) {
        b.putInt(1, val);
    }

    /**
     * Set the client handle without deserializing it first
     * @param b
     * @param handle
     */
    public static void setClientHandle(ByteBuffer b, long handle) {
        b.putLong(13, handle); // 1 + 4 + 8 
    }

    /**
     * Mark the throttle flag in the byte array without deserializing it first
     * @param arr
     * @param flag
     */
    public static void setThrottleFlag(ByteBuffer b, boolean flag) {
        b.put(22, (byte) (flag ? 1 : 0)); // 1 + 4 + 8 + 8 + 1 = 22 
    }

    /**
     * Set the base partition for the client response without deserializing it
     * @param arr
     * @param flag
     */
    public static void setBasePartition(ByteBuffer b, int basePartition) {
        b.putInt(22, basePartition); // 1 + 4 + 8 + 8 + 1 + 1 = 23 
    }

    /**
     * Set the status without deserializing it first
     * @param arr
     * @param flag
     */
    public static void setStatus(ByteBuffer b, Status status) {
        b.put(23, (byte) status.ordinal()); // 1 + 4 + 8 + 8 + 1 + 1 + 4 = 27 
    }

    // ----------------------------------------------------------------------------

    private void setResults(Status status, VoltTable[] results, String statusString) {
        assert results != null;
        for (VoltTable result : results) {
            // null values are not permitted in results. If there is one, it will cause an
            // exception in writeExternal. This throws the exception sooner.
            assert result != null;
        }

        this.status = status;
        this.results = results;
        this.statusString = statusString;
        this.setProperly = true;
    }

    private void setResults(Status status, VoltTable[] results, String extra, SerializableException e) {
        m_exception = e;
        setResults(status, results, extra);
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    @Override
    public boolean getThrottleFlag() {
        return (this.throttle);
    }

    public void setThrottleFlag(boolean val) {
        this.throttle = val;
    }

    @Override
    public int getRequestCounter() {
        return this.requestCounter;
    }

    /**
     * Set the internal request counter
     */
    public void setRequestCounter(int val) {
        this.requestCounter = val;
    }

    @Override
    public int getBasePartition() {
        return (this.basePartition);
    }

    public void setBasePartition(int val) {
        this.basePartition = val;
    }

    @Override
    public boolean isSinglePartition() {
        return singlepartition;
    }

    public void setSinglePartition(boolean val) {
        this.singlepartition = val;
    }

    @Override
    public Status getStatus() {
        return status;
    }

    public VoltTable[] getResults() {
        return results;
    }

    @Override
    public int getResultsSize() {
        int ret = 0;
        for (VoltTable vt : this.results) {
            ret += vt.getUnderlyingBufferSize();
        } // FOR
        return ret;
    }

    public String getStatusString() {
        return statusString;
    }

    public void setClientHandle(long aHandle) {
        clientHandle = aHandle;
    }

    public long getClientHandle() {
        return clientHandle;
    }

    public SerializableException getException() {
        return m_exception;
    }

    @Override
    public long getTransactionId() {
        return (this.txn_id);
    }

    @Override
    public void readExternal(FastDeserializer in) throws IOException {
        in.readByte();//Skip version byte
        requestCounter = in.readInt();
        txn_id = in.readLong();
        clientHandle = in.readLong();
        singlepartition = in.readBoolean();
        throttle = in.readBoolean();
        basePartition = in.readInt();

        byte presentFields = in.readByte();
        status = Status.valueOf(in.readByte());
        if ((presentFields & (1 << 5)) != 0) {
            statusString = in.readString();
        } else {
            statusString = null;
        }
        appStatus = in.readByte();
        if ((presentFields & (1 << 7)) != 0) {
            appStatusString = in.readString();
        } else {
            appStatusString = null;
        }
        clusterRoundTripTime = in.readInt();
        if ((presentFields & (1 << 6)) != 0) {
            m_exception = SerializableException.deserializeFromBuffer(in.buffer());
        } else {
            m_exception = null;
        }
        results = (VoltTable[]) in.readArray(VoltTable.class);
        setProperly = true;
    }

    @Override
    public void writeExternal(FastSerializer out) throws IOException {
        assert setProperly;
        out.writeByte(0);//version
        out.writeInt(requestCounter);
        out.writeLong(txn_id);
        out.writeLong(clientHandle);
        out.writeBoolean(singlepartition);
        out.writeBoolean(throttle);
        out.writeInt(basePartition);

        byte presentFields = 0;
        if (appStatusString != null) {
            presentFields |= 1 << 7;
        }
        if (m_exception != null) {
            presentFields |= 1 << 6;
        }
        if (statusString != null) {
            presentFields |= 1 << 5;
        }
        out.writeByte(presentFields);
        out.write((byte) status.ordinal());
        if (statusString != null) {
            out.writeString(statusString);
        }
        out.write(appStatus);
        if (appStatusString != null) {
            out.writeString(appStatusString);
        }
        out.writeInt(clusterRoundTripTime);
        if (m_exception != null) {
            final ByteBuffer b = ByteBuffer.allocate(m_exception.getSerializedSize());
            m_exception.serializeToBuffer(b);
            out.write(b.array());
        }
        out.writeArray(results);
    }

    @Override
    public int getClusterRoundtrip() {
        return clusterRoundTripTime;
    }

    public void setClusterRoundtrip(int time) {
        clusterRoundTripTime = time;
    }

    @Override
    public int getClientRoundtrip() {
        return clientRoundTripTime;
    }

    public void setClientRoundtrip(int time) {
        clientRoundTripTime = time;
    }

    @Override
    public byte getAppStatus() {
        return appStatus;
    }

    @Override
    public String getAppStatusString() {
        return appStatusString;
    }

    @Override
    public int getRestartCounter() {
        return restartCounter;
    }

    public void setRestartCounter(int restarts) {
        restartCounter = restarts;
    }

    @Override
    public String toString() {
        Map<String, Object> m = new ListOrderedMap<String, Object>();
        m.put("Status", this.status
                + (this.statusString == null || this.statusString.isEmpty() ? "" : " / " + this.statusString));
        m.put("Handle", this.clientHandle);
        m.put("RequestCounter", this.requestCounter);
        m.put("Throttle", this.throttle);
        m.put("SinglePartition", this.singlepartition);
        m.put("BasePartition", this.basePartition);
        m.put("Exception", m_exception);

        if (this.clientRoundTripTime > 0) {
            m.put("Client RoundTrip Time", this.clientRoundTripTime + " ms");
        }
        if (this.clusterRoundTripTime > 0) {
            m.put("Cluster RoundTrip Time", this.clusterRoundTripTime + " ms");
        }

        Map<String, Object> inner = new ListOrderedMap<String, Object>();
        for (int i = 0; i < results.length; i++) {
            inner.put(String.format("[%d]", i), results[i].toString());
        }
        m.put("Results", inner);

        return String.format("ClientResponse[#%d]\n%s", this.txn_id, StringUtil.formatMaps(m));
    }

}