com.sleepycat.client.BdbServerConnection.java Source code

Java tutorial

Introduction

Here is the source code for com.sleepycat.client.BdbServerConnection.java

Source

/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2002, 2016 Oracle and/or its affiliates.  All rights reserved.
 *
 * $Id$
 */

package com.sleepycat.client;

import com.sleepycat.thrift.BdbService;
import com.sleepycat.thrift.TEnvironment;
import com.sleepycat.thrift.TProtocolVersionTestResult;
import com.sleepycat.thrift.dbConstants;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TIOStreamTransport;
import org.apache.thrift.transport.TSSLTransportFactory;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

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

/**
 * A connection with a specific BDB server.
 * <p>
 * BdbServerConnection is not thread-safe. Objects created from a connection
 * use the connection internally, therefore they are not thread-safe either. A
 * connection together with all objects created from it should only be accessed
 * from a single thread. For example, a connection, an environment handle
 * opened from it and a database handle opened from the environment handle, all
 * three objects should be accessed from the same thread. It is an error to
 * access the environment handle and the database handle from different
 * threads.
 */
public class BdbServerConnection implements RemoteCallHelper, AutoCloseable {
    /** The server's host URL. */
    private final String host;

    /** The server's listening port. */
    private final int port;

    /** The client instance. */
    private BdbService.Client client;

    private BdbServerConnection(String host, int port) {
        this.host = Objects.requireNonNull(host, "host is null.");
        this.port = Objects.requireNonNull(port, "port is null.");
    }

    /**
     * For unit test only.
     *
     * @param clientIn the input stream
     * @param clientOut the out stream
     */
    BdbServerConnection(InputStream clientIn, OutputStream clientOut) {
        this.host = "test";
        this.port = 0;
        TProtocol protocol = new TCompactProtocol(new TIOStreamTransport(clientIn, clientOut));
        this.client = new BdbService.Client(protocol);
    }

    /**
     * Open a new connection to the specified BDB server.
     *
     * @param host the server's host URL
     * @param port the server's listening port
     * @return a new connection
     * @throws BdbConnectionException if an error occurred while connecting to
     * the server
     * @throws SDatabaseException if any error occurs
     */
    public static BdbServerConnection connect(String host, int port) throws SDatabaseException {
        return connectSsl(host, port, null, 0);
    }

    /**
     * Open a new SSL connection to the specified BDB server.
     *
     * @param host the server's host URL
     * @param port the server's listening port
     * @param sslConfig the SSL configuration
     * @param timeout the timeout in milliseconds for each remote request, zero
     * as an infinite timeout
     * @return a new connection
     * @throws BdbConnectionException if an error occurred while connecting to
     * the server
     * @throws SDatabaseException if any error occurs
     */
    public static BdbServerConnection connectSsl(String host, int port, SslConfig sslConfig, int timeout)
            throws SDatabaseException {
        try {
            BdbServerConnection connection = new BdbServerConnection(host, port);
            connection.open(sslConfig, timeout);
            return connection;
        } catch (TTransportException e) {
            String msg = "Failed to connect to '" + host + ":" + port + "'";
            throw new BdbConnectionException(msg, e);
        }
    }

    private void open(SslConfig sslConfig, int timeout) throws TTransportException {
        TTransport transport;
        if (sslConfig == null) {
            TSocket socket = new TSocket(this.host, this.port);
            transport = new TFramedTransport(socket);
            transport.open();
        } else {
            transport = TSSLTransportFactory.getClientSocket(this.host, this.port, timeout,
                    sslConfig.getParameters());
        }

        TProtocol protocol = new TCompactProtocol(transport);
        this.client = new BdbService.Client(protocol);

        TProtocolVersionTestResult testResult = remoteCall(
                () -> this.client.isProtocolVersionSupported(dbConstants.PROTOCOL_VERSION));
        if (!testResult.isSupported()) {
            throw new BdbConnectionException(
                    "Driver is not compatible with the server. The "
                            + "server requires drivers with protocol version: " + testResult.serverProtocolVersion,
                    null);
        }
    }

    /**
     * Return a {@link BdbServerAdmin} which can be used to perform
     * administrative operations on the connected server.
     *
     * @return a BdbServerAdmin
     */
    public BdbServerAdmin adminService() {
        return new BdbServerAdmin(this.client);
    }

    /**
     * Open a remote environment and return an environment handle.
     *
     * @param home the environment's home directory. The directory must
     * specified as a relative path
     * @param config the environment attributes. If null, system default
     * attributes are used
     * @return an environment handle
     * @throws IOException if the environment does not exist or cannot be
     * accessed
     * @throws SResourceInUseException if the environment is being recovered or
     * deleted
     * @throws SDatabaseException if any error occurs
     */
    public SEnvironment openEnvironment(String home, SEnvironmentConfig config)
            throws IOException, SDatabaseException {
        return remoteCallWithIOException(() -> {
            TEnvironment env = this.client.openEnvironment(home, ThriftWrapper.nullSafeGet(config));
            return new SEnvironment(env, home, this.client);
        });
    }

    /**
     * Close this connection.
     * <p>
     * After closing this connection, all objects created from this connection
     * must be discarded.
     */
    public void close() {
        this.client.getInputProtocol().getTransport().close();
    }
}