/* 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.client; import java.io.IOException; import java.net.UnknownHostException; import org.voltdb.StoredProcedureInvocationHints; import org.voltdb.VoltTable; import edu.brown.profilers.ProfileMeasurement; /** * <p> * A <code>Client</code> that connects to one or more nodes in a volt cluster * and provides methods for invoking stored procedures and receiving * responses. Client applications that are resource constrained (memory, CPU) or high performance * (process hundreds of thousands of transactions per second) will want to pay attention to the hints that * can be provided via * {@link ClientFactory#createClient(int, int[], boolean, StatsUploaderSettings)} and * {@link #callProcedure(ProcedureCallback, int, String, Object...)}. * Most Client applications will not need to generate enough load for these optimizations to matter. * </p> * * <p> * A stored procedure invocation contains approximately 24 bytes of data per * invocation plus the serialized sized of the procedure name and any parameters. The size of any specific procedure * and parameter set can be calculated using * {@link #calculateInvocationSerializedSize(String, Object...) calculateInvocationSerializedSize}. This method * serializes the invocation and returns the serialized size and is computationally intensive and not suitable * for use on a per invocation basis. * </p> * * <p> * The expected serialized message size parameter provided to * {@link ClientFactory#createClient(int, int[], boolean, StatsUploaderSettings) createClient} * determines the default size of the initial memory allocation used when serializing stored procedure invocations. * If the initial allocation is insufficient then the allocation is doubled necessitating an extra allocation and copy * If the allocation is excessively small it may be doubled and copied several times when serializing large * parameter sets. * </p> * * <p> * {@link #callProcedure(ProcedureCallback, int, String, Object...)} allows the initial allocation to be hinted on a * per procedure invocation basis. This is useful when an application invokes procedures where the size can vary * significantly between invocations or procedures. * </p> * * <p> * The <code>Client</code> performs aggressive memory pooling of {@link java.nio.DirectByteBuffer DirectByteBuffers}. The pool * contains arenas with buffers that are sized to powers of 2 from 2^4 to 2^18. Java does not reliably * garbage collect {@link java.nio.DirectByteBuffer DirectByteBuffers} so the pool never returns a buffer to the * heap. The <code>maxArenaSizes</code> array passed to * {@link ClientFactory#createClient(int, int[], boolean, StatsUploaderSettings)} can be used * to specify the maximum size each arena will be allowed to grow to. The client will continue to function even * if the an arena is no longer able to grow. It will fall back to using slower * {@link java.nio.HeapByteBuffer HeapByteBuffers} for serializing invocations. * </p> */ public interface Client { /** * Create a connection to another VoltDB node. * @param host hostname or IP address of the host to connect to * @param port the port number that the host is listening on * @throws UnknownHostException * @throws IOException */ public void createConnection(String host, int port) throws UnknownHostException, IOException; /** * Create a connection to another VoltDB node. * @param siteId TODO * @param host hostname or IP address of the host to connect to * @param port TODO * @param username Username to authorize. Username is ignored if authentication is disabled. * @param password Password to authenticate. Password is ignored if authentication is disabled. * @throws UnknownHostException * @throws IOException */ public void createConnection(Integer siteId, String host, int port, String username, String password) throws UnknownHostException, IOException; /** * Synchronously invoke a procedure. Blocks until a result is available. A {@link ProcCallException} * is thrown if the response is anything other then success. * @param procName <code>class</code> name (not qualified by package) of the procedure to execute. * @param parameters vararg list of procedure's parameter values. * @return array of VoltTable results. * @throws org.voltdb.client.ProcCallException * @throws NoConnectionsException */ public ClientResponse callProcedure(String procName, Object... parameters) throws IOException, NoConnectionsException, ProcCallException; /** * Synchronously invoke a procedure. Blocks until a result is available. A {@link ProcCallException} * is thrown if the response is anything other then success. * @param procName <code>class</code> name (not qualified by package) of the procedure to execute. * @param hints Extra information about what the transaction will do. * @param parameters vararg list of procedure's parameter values. * @return array of VoltTable results. * @throws org.voltdb.client.ProcCallException * @throws NoConnectionsException */ public ClientResponse callProcedure(String procName, StoredProcedureInvocationHints hints, Object... parameters) throws IOException, NoConnectionsException, ProcCallException; /** * Asynchronously invoke a procedure. Does not guarantee that the invocation is actually queued. If there * is backpressure on all connections to the cluster then the invocation will not be queued. Check the return value * to determine if queuing actually took place. * @param callback ProcedureCallback that will be invoked with procedure results. * @param procName class name (not qualified by package) of the procedure to execute. * @param parameters vararg list of procedure's parameter values. * @return <code>true</code> if the procedure was queued and <code>false</code> otherwise */ public boolean callProcedure(ProcedureCallback callback, String procName, Object... parameters) throws IOException, NoConnectionsException; /** * Asynchronously invoke a procedure. Does not guarantee that the invocation is actually queued. If there * is backpressure on all connections to the cluster then the invocation will not be queued. Check the return value * to determine if queuing actually took place. * @param callback ProcedureCallback that will be invoked with procedure results. * @param procName class name (not qualified by package) of the procedure to execute. * @param hints Extra information about what the transaction will do. * @param parameters vararg list of procedure's parameter values. * @return <code>true</code> if the procedure was queued and <code>false</code> otherwise */ public boolean callProcedure(ProcedureCallback callback, String procName, StoredProcedureInvocationHints hints, Object... parameters) throws IOException, NoConnectionsException; /** * Asynchronously invoke a procedure. Does not guarantee that the invocation is actually queued. If there * is backpressure on all connections to the cluster then the invocation will not be queued. Check the return value * to determine if queuing actually took place. An opportunity is provided to hint what the size of the invocation * will be once serialized. This is used to perform more efficient memory allocation and serialization. The size * of an invocation can be calculated using {@link #calculateInvocationSerializedSize(String, Object...)}. * Only Clients that are resource constrained or expect to process hundreds of thousands of txns/sec will benefit * from accurately determining the serialized size of message. * @param callback ProcedureCallback that will be invoked with procedure results. * @param procName class name (not qualified by package) of the procedure to execute. * @param parameters vararg list of procedure's parameter values. * @param expectedSerializedSize A hint indicating the size the procedure invocation is expected to be * once serialized. Allocations are done in powers of two. * @return <code>true</code> if the procedure was queued and <code>false</code> otherwise */ public boolean callProcedure( ProcedureCallback callback, int expectedSerializedSize, String procName, StoredProcedureInvocationHints hints, Object... parameters) throws IOException, NoConnectionsException; /** * Calculate the size of a stored procedure invocation once it is serialized. This is computationally intensive * as the invocation is serialized as part of the calculation. * @param procName class name (not qualified by package) of the procedure to execute. * @param parameters vararg list of procedure's parameter values. * @return The size of the invocation once serialized */ public int calculateInvocationSerializedSize(String procName, Object... parameters); /** * Block the current thread until all queued stored procedure invocations have received responses * or there are no more connections to the cluster * @throws NoConnectionsException */ public void drain() throws NoConnectionsException, InterruptedException; /** * Shutdown the {@link Client} closing all network connections and release all memory resources. * Failing to call this method before the {@link Client} is garbage collected can generate errors because * <code>finalization</code> is used to detect resource leaks. A client cannot be used once it has * been closed. * @throws InterruptedException */ public void close() throws InterruptedException; /** * Add to the list of listeners that will be notified of events * @param listener Listener to register */ public void addClientStatusListener(ClientStatusListener listener); /** * Remove listener so that it will no longer be notified of events * @param listener Listener to unregister * @return <code>true</code> if the listener was removed and <code>false</code> if it wasn't registered */ public boolean removeClientStatusListener(ClientStatusListener listener); /** * Blocks the current thread until there is no more backpressure or there are no more connections * to the database * @throws InterruptedException */ public void backpressureBarrier() throws InterruptedException; /** * Get IO stats for each connection as well as globally * @return Table containing IO stats */ public VoltTable getIOStats(); /** * Get IO stats for each connection as well as globally counting since the last * time this method was called. Don't call this interval version * if the client API is uploading stats via JDBC, it messes up the counters * @return Table containing IO states */ public VoltTable getIOStatsInterval(); /** * Get procedure invocation counts and round trip time stats for each connection * @return Table containing procedure stats */ public VoltTable getProcedureStats(); /** * Get procedure invocation counts and round trip time stats for each connection * since the last time this method was called. Don't call this interval version * if the client API is uploading stats via JDBC, it messes up the counters * @return Table containing procedure stats */ public VoltTable getProcedureStatsInterval(); public ProfileMeasurement getQueueTime(); /** * Get an identifier for the cluster that this client is currently connected to. * Will be null if the client has not been connected * @return An array of a Long and Integer containing the millisecond timestamp when the cluster was * started and the leader address */ public Object[] getInstanceId(); /** * Retrieve the build string that was provided by the server on logon * @return Volt server build string */ public String getBuildString(); /** * The default behavior for queuing of asynchronous procedure invocations is to block until * it is possible to queue the invocation. If blocking is set to false callProcedure will always return * immediately if it is not possible to queue the procedure invocation due to backpressure. * @param blocking */ void configureBlocking(boolean blocking); /** * Whether callProcedure will return immediately if a an async procedure invocation could not be queued * due to backpressure * @return true if callProcedure will block until backpressure ceases and false otherwise */ boolean blocking(); }