Package com.caringo.client

Source Code of com.caringo.client.ScspClient

package com.caringo.client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpVersion;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.util.IdleConnectionTimeoutThread;

import com.caringo.client.CAStorSDKVersion;
import com.caringo.client.locate.Locator;
import com.caringo.client.locate.StaticLocator;
import com.caringo.client.request.ScspRequestHandler;
import com.caringo.client.request.LocatorRedirectHandler;

/**
* Main interface for initiating a connection to a CAStor cluster and creating or executing SCSP commands. The constructor provides
* initial configuration of the SCSP API.<br>
* <br>
* All command methods should only be called when the factory is running (after a successful <code>start</code> and before a
* <code>stop</code>).<br>
* Example:<br>
*
* <pre>
* {@code
*   ScspClient client = new ScspClient("cas.caringo.com", 80, 8, 4);
*  client.start();
*  ScspNodeInfo command = client.createNodeInfoCommand();
*  client.execute();
*  //more commands..
*  factory.stop();
* }
* </pre>
*
* <br>
* Command object vs. execution method interfaces<br>
* <br>
* ScspClient provides methods for creating command objects that can execute SCSP commands and for direct execution of the same
* commands. For each command object, there is an equivalent ScspClient execution method.
* <p>
* For example, the following two pieces of code are equivalent:
*
* <pre>
* {@code
* void doInfo(ScspClient client, String uuid) {
*    ScspResponse response = client.info(uuid);
*    System.out.println(response.toString());
* }}
* </pre>
*
* and<br>
*
* <pre>
* {@code
* void doInfo(ScspClient client, String uuid) {
*    ScspInfo infoCommand = client.createInfoCommand(uuid);
*    ScspResponse response = infoCommand.execute();
*    System.out.println(response.toString());
* }
* }
* </pre>
*
* <p>
* Mutable vs. Non-mutable methods<br>
* <br>
* This API provides separate execution interfaces for CAStor anchor streams and regular streams. The anchor stream commands contain
* 'Mutable' in their method names. <br>
* <p>
* Validate mode<br>
* If <code>setValidating(true)</code> is called, all execution methods (<code>write</code>, <code>read</code>, etc.)
* will validate their arguments instead of executing requests to CAStor. <br>
* <p>
* The <code>Path</code> Parameter<br>
* The <code>path</code> parameter to the <code>ScspClient</code> execution methods and the <code>path</code> property in <code>ScspCommand</code>
* can be used to specify the Remote Cluster Name for <code>ScspProxy</code> remote proxy features; for named object names, including bucket
* and object names; and for uuids. Note that the <code>uuid</code> parameter is deprecated in this release and will be removed altogether
* in the next release or the one following - please use the <code>path</code> parameter and property instead.
* <br>
* Copyright (c) 2009 by Caringo, Inc. -- All rights reserved<br>
* This is free software, distributed under the terms of the New BSD license.<br>
* See the LICENSE.txt file included in this archive.<br>
* <br>
*
* @author pray
* @created September 20, 2009
* @id ${Id}
*/

public class ScspClient {

    private static final int DEFAULT_MAX_RETRIES = 5;
    private static final int DEFAULT_MAX_POOL_SIZE = 50;

    private static final String DEFAULT_USER_AGENT = "CAStor Client java/" + CAStorSDKVersion.CAStorSDKVersion;
    private static final int CM_IDLE_TIMEOUT = 60 * 1000; // HttpConnectionManager idle timeout - 1 minute
    private static final int CM_REAP_PERIOD = 60 * 1000; // HttpConnectionManager reaper retry period - 1 minute
    private static final int LOCATOR_RETRY_TIMEOUT = 0; // StaticLocator pool retry timeout - 10 minutes
    private static final int CONNECTION_TIMEOUT = 60 * 1000; // Request activity timeout - 1 minute
    private static final HttpClientParams CLIENT_PARAMS = new HttpClientParams();
    private static final int MAX_REDIRECTS = 10;
   
    public static final int DEFAULT_EXTERNAL_TIMEOUT = 300; // Socket timeout (non-connection) for connections made from a 305 redirect

    public static final String CASTOR_ADMIN_AGENT = "CAStorAdminAgent/1.0";
    public static final String UserAgent = DEFAULT_USER_AGENT;

    static {
        CLIENT_PARAMS.setParameter("http.connection.timeout", CONNECTION_TIMEOUT);
        CLIENT_PARAMS.setParameter(HttpClientParams.SO_TIMEOUT, CONNECTION_TIMEOUT);
        CLIENT_PARAMS.setParameter(HttpClientParams.MAX_REDIRECTS, MAX_REDIRECTS); // this should never be used since we're
        // explicitly handling redirects
        CLIENT_PARAMS.setParameter(HttpClientParams.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
        CLIENT_PARAMS.setParameter(HttpClientParams.USE_EXPECT_CONTINUE, true);
        CLIENT_PARAMS.setParameter(HttpClientParams.USER_AGENT, DEFAULT_USER_AGENT);
        CLIENT_PARAMS.setParameter(HttpClientParams.WARN_EXTRA_INPUT, true);
        CLIENT_PARAMS.setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
    }

    private HttpConnectionManager connMgr;
    private HttpConnectionManager externalConnMgr;
    private IdleConnectionTimeoutThread connReaper;
    private LocatorRedirectHandler locator;
    private boolean validating;
    private int maxRetries = DEFAULT_MAX_RETRIES;
    private int maxPoolSize = DEFAULT_MAX_POOL_SIZE;
    private String userAgent = DEFAULT_USER_AGENT;
    private int connectionTimeout;
    private int poolTimeout;
    private String hostHeaderValue;
    private int externalTimeout = DEFAULT_EXTERNAL_TIMEOUT;

    /**
     * Construct command factory and configure the communication settings.
     *
     * @param hosts -
     *            Array of CAStor hosts as IP addressses or host names. Typically this is a single value identifying an initial node
     *            in the CAStor cluster.
     * @param port -
     *            Port number for talking to CAStor cluter. Typically 80.
     * @param maxConnectionPoolSize -
     *            Size of connection pool. Basically, the connectionPoolSize indicates how many simultaneous open connections should
     *            be allowed.
     * @param maxRetries -
     *            Maximum number of times to retry a command on communication or server failure.
     */
    public ScspClient(String[] hosts, int port, int maxConnectionPoolSize, int maxRetries) {
        this.locator = new LocatorRedirectHandler(new StaticLocator(hosts, port, LOCATOR_RETRY_TIMEOUT));
        this.maxPoolSize = maxConnectionPoolSize;
        this.maxRetries = maxRetries;
        this.validating = false;
        this.connectionTimeout = CONNECTION_TIMEOUT;
        this.poolTimeout = CM_IDLE_TIMEOUT;
    }

    /**
     * Construct command factory and configure the communication settings along with timeouts.
     *
     * @param hosts -
     *            Array of CAStor hosts as IP addressses or host names. Typically this is a single value identifying an initial node
     *            in the CAStor cluster.
     * @param port -
     *            Port number for talking to CAStor cluter. Typically 80.
     * @param maxConnectionPoolSize -
     *            Size of connection pool. Basically, the connectionPoolSize indicates how many simultaneous open connections should
     *            be allowed.
     * @param maxRetries -
     *            Maximum number of times to retry a command on communication or server failure.
     * @param connectionTimeout -
     *            Idle timeout for a request in seconds.
     * @param poolTimeout -
     *            The amount of time seconds an idle connection will be stored for reuse.
     * @param locatorRetryTimeout -
     *            The number of seconds after a node is found dead that it will be retried.
     */
    public ScspClient(String[] hosts, int port, int maxConnectionPoolSize, int maxRetries, int connectionTimeout, int poolTimeout, int locatorRetryTimeout) {
        this.locator = new LocatorRedirectHandler(new StaticLocator(hosts, port, locatorRetryTimeout));
        this.maxPoolSize = maxConnectionPoolSize;
        this.maxRetries = maxRetries;
        this.validating = false;
        this.connectionTimeout = connectionTimeout * 1000;
        this.poolTimeout = poolTimeout * 1000;
        CLIENT_PARAMS.setParameter(HttpClientParams.SO_TIMEOUT, this.connectionTimeout);
        CLIENT_PARAMS.setParameter("http.connection.timeout", this.connectionTimeout);
    }

    /**
     * Construct command factory and configure the communication settings along with timeouts.
     *
     * @param locator -
     *            A host Locator to use for lookup CAStor node addresses.
     * @param port -
     *            Port number for talking to CAStor cluter. Typically 80.
     * @param maxConnectionPoolSize -
     *            Size of connection pool. Basically, the connectionPoolSize indicates how many simultaneous open connections should
     *            be allowed.
     * @param maxRetries -
     *            Maximum number of times to retry a command on communication or server failure.
     * @param connectionTimeout -
     *            Idle timeout for a request in seconds.
     * @param poolTimeout -
     *            The amount of time seconds an idle connection will be stored for reuse.
     */
    public ScspClient(Locator locator, int port, int maxConnectionPoolSize, int maxRetries, int connectionTimeout, int poolTimeout) {
        this.locator = new LocatorRedirectHandler(locator);
        this.maxPoolSize = maxConnectionPoolSize;
        this.maxRetries = maxRetries;
        this.validating = false;
        this.connectionTimeout = connectionTimeout * 1000;
        this.poolTimeout = poolTimeout * 1000;
        CLIENT_PARAMS.setParameter(HttpClientParams.SO_TIMEOUT, this.connectionTimeout);
        CLIENT_PARAMS.setParameter("http.connection.timeout", this.connectionTimeout);
    }

    /**
     * Start the factory.
     *
     * @throws IOException -
     *             Indicates something went wrong when trying to set up connection to CAStor.
     */
    public void start() throws IOException {
        if (!isStarted()) {
            locator.start();
        }
       
        if (connMgr == null) {
            connMgr = new MultiThreadedHttpConnectionManager();
           
            HttpConnectionManagerParams params = connMgr.getParams();
            params.setMaxTotalConnections(maxPoolSize);
            params.setDefaultMaxConnectionsPerHost(maxPoolSize); // we don't need to restrict this, like a browser would
            connMgr.setParams(params);
        }
           
        if (externalConnMgr == null) {
            externalConnMgr = new MultiThreadedHttpConnectionManager();
           
            HttpConnectionManagerParams extParams = externalConnMgr.getParams();
            extParams.setMaxTotalConnections(maxPoolSize);
            extParams.setDefaultMaxConnectionsPerHost(maxPoolSize); // we don't need to restrict this, like a browser would
            externalConnMgr.setParams(extParams);
        }
       
        if ((connMgr != null) && (externalConnMgr != null)) {
            if (connReaper == null) {
                connReaper = new IdleConnectionTimeoutThread();
               
                connReaper.setConnectionTimeout(poolTimeout);
                connReaper.setTimeoutInterval(CM_REAP_PERIOD);

                connReaper.addConnectionManager(connMgr);
                connReaper.addConnectionManager(externalConnMgr);
                connReaper.start();
            }
        }
    }

    /**
     * Stop the interface and close all the connections.
     */
    public void stop() {
        connReaper.shutdown();
        connMgr.closeIdleConnections(1);
        externalConnMgr.closeIdleConnections(1);
        locator.stop();
        connReaper = null;
        connMgr = null;
        externalConnMgr = null;
    }

    /**
     * Create a <code>ScspWrite</code> with an input stream and length.
     *
     * @param inputStream -
     *            Stream to read stream data from for writing to CAStor.
     * @param inputStreamLength -
     *            Length of the input stream.
     * @return The write command ready to execute.
     */
    public ScspWrite createWriteCommand(InputStream inputStream, long inputStreamLength) {

        return new ScspWrite(getClient(), inputStream, inputStreamLength);
    }

    /**
     * Create a <code>ScspRead</code> with a CAStor stream UUID and output stream.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to read.
     * @param outputStream -
     *            Stream to write data read from CAStor.
     * @return The read command ready to execute.
     */
    public ScspRead createReadCommand(String UUID, OutputStream outputStream) {
        return new ScspRead(getClient(), UUID, outputStream);
    }

    /**
     * Create a <code>ScspInfo</code> with a CAStor stream UUID.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to retrieve info for.
     * @return The read command ready to execute.
     */
    public ScspInfo createInfoCommand(String UUID) {
        return new ScspInfo(getClient(), UUID);
    }
   
    /**
     * Create a <code>ScspAggregateInfo</code> with a CAStor stream UUID and output stream.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to read.
     * @param outputStream -
     *            Stream to write data read from CAStor.
     * @return The read command ready to execute.
     */
    public ScspAggregateInfo createAggregateInfoCommand(String UUID, OutputStream outputStream) {
        return new ScspAggregateInfo(getClient(), UUID, outputStream);
    }
   
    /**
     * Create a <code>ScspDeleteCommand</code> with a CAStor stream UUID.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to delete.
     * @return The delete command ready to execute.
     */
    public ScspDelete createDeleteCommand(String UUID) {
        return new ScspDelete(getClient(), UUID);
    }

    // Mutable (anchor stream) commands

    /**
     * Create a <code>ScspCopyCommand</code> with an initial UUID.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor anchor stream to update.
     * @return The update command ready to execute.
     */
    public ScspCopy createCopyCommand(String UUID) {
        return new ScspCopy(getClient(), UUID);
    }

    /**
     * Create a <code>ScspUpdateCommand</code> with an initial UUID, input stream, and length.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor anchor stream to update.
     * @param inputStream -
     *            Stream to read stream data from for writing to CAStor.
     * @param inputStreamLength -
     *            Length of the input stream.
     * @return The update command ready to execute.
     */
    public ScspUpdate createUpdateCommand(String UUID, InputStream inputStream, long inputStreamLength) {
        return new ScspUpdate(getClient(), UUID, inputStream, inputStreamLength);
    }

    /**
     * Create a <code>ScspAppendCommand</code> with an initial UUID, input stream, and length.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor anchor stream to append to.
     * @param inputStream -
     *            Stream to read stream data from for writing to CAStor.
     * @param inputStreamLength -
     *            Length of the input stream.
     * @return The update command ready to execute.
     */
    public ScspAppend createAppendCommand(String UUID, InputStream inputStream, long inputStreamLength) {
        return new ScspAppend(getClient(), UUID, inputStream, inputStreamLength);
    }

    // Non-stream commands
    /**
     * Create a <code>ScspNodeInfoCommand</code>.
     *
     * @return The node info command ready to execute.
     */
    public ScspNodeStatus createNodeStatusCommand() {
        return new ScspNodeStatus(getClient());
    }

    // direct execution (non-command) interface

    /**
     * Execute or validate a normal (non-mutable) SCSP write command with an input stream and length, query args, and headers.
     *
     * @param path -
     *         Resource path.
     * @param input -
     *            Stream containing data to to write to CAStor.
     * @param inputStreamLength -
     *            Length of the input stream.
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse write(String path, InputStream input, long inputStreamLength, ScspQueryArgs queryArgs, ScspHeaders headers)
            throws ScspExecutionException {
        ScspWrite wc = createWriteCommand(input, inputStreamLength);
        wc.setPath(path);
        wc.setQueryArgs(queryArgs);
        wc.setHeaders(headers);
        if (validating) {
            return validateCommand(wc);
        } else {
            return wc.execute();
        }
    }

    /**
     * Execute or validate a normal (non-mutable) SCSP read command with a stream path, an output stream, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of CAStor stream to read.
     * @param path -
     *         Resource path.
     * @param output -
     *            Stream to write data read from CAStor.
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse read(String UUID, String path, OutputStream output, ScspQueryArgs queryArgs, ScspHeaders headers)
            throws ScspExecutionException {
        ScspRead rc = createReadCommand(UUID, output);
        rc.setPath(path);
        rc.setQueryArgs(queryArgs);
        rc.setHeaders(headers);
        if (validating) {
            return validateCommand(rc);
        } else {
            return rc.execute();
        }
    }

    /**
     * Execute or validate a normal (non-mutable) SCSP info command with a stream path, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to retrieve info for.
     * @param path -
     *         Resource path.
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse info(String UUID, String path, ScspQueryArgs queryArgs, ScspHeaders headers) throws ScspExecutionException {
        ScspInfo ic = createInfoCommand(UUID);
        ic.setPath(path);
        ic.setQueryArgs(queryArgs);
        ic.setHeaders(headers);
        if (validating) {
            return validateCommand(ic);
        } else {
            return ic.execute();
        }
    }

    /**
     * Execute or validate a normal (non-mutable) SCSP delete command with a stream path, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to delete.
     * @param path -
     *         Resource path.
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse delete(String UUID, String path, ScspQueryArgs queryArgs, ScspHeaders headers) throws ScspExecutionException {
        ScspDelete dc = createDeleteCommand(UUID);
        dc.setPath(path);
        dc.setQueryArgs(queryArgs);
        dc.setHeaders(headers);
        if (validating) {
            return validateCommand(dc);
        } else {
            return dc.execute();
        }
    }

    /**
     * Execute or validate an anchor (mutable) stream SCSP write command with an input stream and length, query args, and headers.
     *
     * @param path -
     *         Resource path.
     * @param input -
     *            Stream containing the data to write to CAStor.
     * @param inputStreamLength -
     *            Length of the input stream.
     * @param queryArgs -
     *            queryArgs to pass to execution
     * @param headers -
     *            headers to pass to execution
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse writeMutable(String path, InputStream input, long inputStreamLength, ScspQueryArgs queryArgs, ScspHeaders headers)
            throws ScspExecutionException {
     
        ScspWrite wc = createWriteCommand(input, inputStreamLength);
        wc.setPath(path);
        wc.setHeaders(headers);
       
        if (validating) {
            return validateMutable(wc, queryArgs);
        } else {
            return executeMutable(wc, queryArgs);
        }
    }

    /**
     * Execute or validate an anchor (mutable) SCSP read command with a stream path, an output stream, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of CAStor stream to read.
     * @param path -
     *         Resource path.
     * @param output -
     *            Stream to write data read from CAStor.
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse readMutable(String UUID, String path, OutputStream output, ScspQueryArgs queryArgs, ScspHeaders headers)
            throws ScspExecutionException {
     
        ScspRead rc = createReadCommand(UUID, output);
        rc.setPath(path);
        rc.setHeaders(headers);
       
        if (validating) {
            return validateMutable(rc, queryArgs);
        } else {
            return executeMutable(rc, queryArgs);
        }
    }

    /**
     * Execute or validate an anchor (mutable) stream SCSP info command with a stream path, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to retrieve info for.
     * @param path -
     *         Resource path.
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse infoMutable(String UUID, String path, ScspQueryArgs queryArgs, ScspHeaders headers) throws ScspExecutionException {
       
      ScspInfo ic = createInfoCommand(UUID);
        ic.setPath(path);
        ic.setHeaders(headers);
       
        if (validating) {
            return validateMutable(ic, queryArgs);
        } else {
            return executeMutable(ic, queryArgs);
        }
    }

    /**
     * Execute or validate an anchor (mutable) stream SCSP delete command with a stream path, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to delete.
     * @param path -
     *         Resource path.
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse deleteMutable(String UUID, String path, ScspQueryArgs queryArgs, ScspHeaders headers) throws ScspExecutionException {
        ScspDelete dc = createDeleteCommand(UUID);
        dc.setPath(path);
        dc.setHeaders(headers);
       
        if (validating) {
            return validateMutable(dc, queryArgs);
        } else {
            return executeMutable(dc, queryArgs);
        }
    }

    /**
     * Execute or validate a SCSP append command with a stream path, an input stream and length, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to append to.
     * @param path -
     *         Resource path.
     * @param inputStream -
     *            Stream containing the data to write to CAStor.
     * @param inputStreamLength -
     *            Length of the input stream.
     * @param queryArgs -
     *            queryArgs to pass to execution
     * @param headers -
     *            headers to pass to execution
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse appendMutable(String UUID, String path, InputStream inputStream, long inputStreamLength, ScspQueryArgs queryArgs,
            ScspHeaders headers) throws ScspExecutionException {
       
      ScspAppend ac = createAppendCommand(UUID, inputStream, inputStreamLength);
        ac.setPath(path);
        ac.setHeaders(headers);
       
        if (validating) {
            return validateMutable(ac, queryArgs);
        } else {
            return executeMutable(ac, queryArgs);
        }
    }

    /**
     * Execute or validate a SCSP update command with a stream path, an input stream and length, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to udpate.
     * @param path -
     *         Resource path.
     * @param inputStream -
     *            Stream containing the data to write to CAStor.
     * @param inputStreamLength -
     *            Length of the input stream.
     * @param queryArgs -
     *            queryArgs to pass to execution
     * @param headers -
     *            headers to pass to execution
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse updateMutable(String UUID, String path, InputStream inputStream, long inputStreamLength, ScspQueryArgs queryArgs,
            ScspHeaders headers) throws ScspExecutionException {
       
      ScspUpdate uc = createUpdateCommand(UUID, inputStream, inputStreamLength);
        uc.setPath(path);
        uc.setHeaders(headers);
       
        if (validating) {
            return validateMutable(uc, queryArgs);
        } else {
            return executeMutable(uc, queryArgs);
        }
    }

    /**
     * Execute or validate a SCSP copy command with a stream path, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to copy.
     * @param path -
     *         Resource path.
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse copyMutable(String UUID, String path, ScspQueryArgs queryArgs, ScspHeaders headers) throws ScspExecutionException {
       
      ScspCopy cc = createCopyCommand(UUID);
        cc.setPath(path);
        cc.setHeaders(headers);
       
        if (validating) {
            return validateMutable(cc, queryArgs);
        } else {
            return executeMutable(cc, queryArgs);
        }
    }

    /**
     * Execute or validate an SCSP info command to retrieve cluster status with query args and headers.
     *
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse nodeStatus(ScspQueryArgs queryArgs, ScspHeaders headers) throws ScspExecutionException {
        ScspNodeStatus nsc = createNodeStatusCommand();
        nsc.setQueryArgs(queryArgs);
        nsc.setHeaders(headers);
        if (validating) {
            return validateCommand(nsc);
        } else {
            return nsc.execute();
        }

    }

    /**
     * Execute or validate an SCSP GET command for a manifest stream with a stream path, query args, and headers.
     *
     * @param UUID -
     *            (Deprecated) The UUID of the CAStor stream to retrieve info for.
     * @param path -
     *         Resource path.
     * @param output -
     *            Stream to write data read from CAStor.
     * @param queryArgs -
     *            queryArgs to pass to execution.
     * @param headers -
     *            headers to pass to execution.
     * @return If isValidating, response with <code>ScspResultCode</code> set to ScspRCSuccess if headers and query args are valid
     *         for this command or ScspRCFailure otherwise. If not isValidating, response returned from CAStor.
     * @throws ScspExecutionException
     */
    public ScspResponse aggregateInfo(String UUID, String path, OutputStream output, ScspQueryArgs queryArgs, ScspHeaders headers) throws ScspExecutionException {
        ScspAggregateInfo ic = createAggregateInfoCommand(UUID, output);
        ic.setPath(path);
        ic.setQueryArgs(queryArgs);
        ic.setHeaders(headers);
        if (validating) {
            return validateCommand(ic);
        } else {
            return ic.execute();
        }
    }
   
    /**
     * Set the user agent to pass in HTTP requests to CAStor.
     *
     * @param userAgent -
     *            the user agent to pass to CAStor.
     */
    public void setUserAgent(String userAgent) {
        this.userAgent = userAgent;
        CLIENT_PARAMS.setParameter(HttpClientParams.USER_AGENT, userAgent);
    }

    /**
     * Get the user agent.
     *
     * @return the user agent.
     */
    public String getUserAgent() {
        return userAgent;
    }

    /**
     * Set the default Host header value to pass in HTTP requests to CAStor.
     * This value will be used only if no other Host header has been specified.
     *
     * @param hostHeaderValue -
     *            the Host header value to pass to CAStor.
     */
    public void setHostHeaderValue(String hostHeaderValue) {
        this.hostHeaderValue = hostHeaderValue;
        CLIENT_PARAMS.setVirtualHost(hostHeaderValue);
    }

    /**
     * Get the default value of the Host header (if previously specified)
   *
   * @return the defaul value of the Host header
   */
    public String getHostHeaderValue() {
        return hostHeaderValue;
    }

    /**
     * Set the idle timeout for requests resulting from a 305, in seconds.
     *
     * @param externalTimeout -
     *            the post-305 idle timeout
     */
    public void setExternalTimeout(int externalTimeout) {
        this.externalTimeout = externalTimeout;
    }

    /**
     * Get idle timeout for requests resulting from a 305, in seconds.
     *
     * @return the post-305 idle timeout
     */
    public int getExternalTimeout() {
        return this.externalTimeout;
    }
   
    /**
     * Has <code>start</code> been successfully called without an intervening <code>stop</code>?
     *
     * @return - Whether <code>start</code> has been called.
     */
    public boolean isStarted() {
        return (connMgr != null) && (externalConnMgr != null) && (connReaper != null);
    }

    /**
     * Return whether this is in Validation mode.
     *
     * @return - validating
     */
    public boolean isValidating() {
        return validating;
    }

    /**
     * Set validation mode
     *
     * @param validating -
     *            Turn on validation if true.
     */
    public void setValidating(boolean validating) {
        this.validating = validating;
    }

    // validate a command and build the correct result code
    //
    private ScspResponse validateCommand(ScspCommand command) {
        boolean valid = command.validate();
        return new ScspResponse(valid ? ScspResponse.ScspResultCode.ScspRCSuccess : ScspResponse.ScspResultCode.ScspRCFailure, 0,
                "", new ScspHeaders(), "",0);
    }

    // build an HttpClient and request handler for executing a command. This glues the underlying HttpClient and request handler
    // interface to the Scsp interfaces.
    private ScspRequestHandler getClient() {
        if (!this.isStarted()) {
            throw new IllegalStateException("ClientFactory " + this + " has not been started.");
        }
       
        HttpClient client = new HttpClient(new HttpClientParams(CLIENT_PARAMS));
       
        client.setHttpConnectionManager(connMgr);
        return new ScspRequestHandler(client, locator, maxRetries, this.externalTimeout, externalConnMgr);
    }

    // Execute one of the Mutable commands, automatically supplying the required alias query argument
    // while not polluting the ScspQueryArgs passed into the command
    //
    private ScspResponse executeMutable(ScspCommand command, ScspQueryArgs queryArgs) throws ScspExecutionException {
        if (null == queryArgs) {
            queryArgs = new ScspQueryArgs();
        }
       
      HashMap<String,String> argsMap = queryArgs.getArgList();
      ScspQueryArgs commandArgs = new ScspQueryArgs();
      commandArgs.setValue("alias", "yes");
      commandArgs.addAll(argsMap);
      command.setQueryArgs(commandArgs);
      return command.execute();
    }
   
    // Validate one of the Mutable commands, automatically supplying the required alias query argument
    // while not polluting the ScspQueryArgs passed into the command
    //
    private ScspResponse validateMutable(ScspCommand command, ScspQueryArgs queryArgs) {
        if (null == queryArgs) {
            queryArgs = new ScspQueryArgs();
        }
       
      HashMap<String,String> argsMap = queryArgs.getArgList();
      ScspQueryArgs commandArgs = new ScspQueryArgs();
      commandArgs.setValue("alias", "yes");
      commandArgs.addAll(argsMap);
      command.setQueryArgs(commandArgs);
      return validateCommand(command);
    }

}
TOP

Related Classes of com.caringo.client.ScspClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.