All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.basho.riak.client.api.RiakClient Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2013 Basho Technologies Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.basho.riak.client.api;

import com.basho.riak.client.core.RiakCluster;
import com.basho.riak.client.core.RiakFuture;
import com.basho.riak.client.core.RiakNode;
import com.basho.riak.client.core.util.HostAndPort;

import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 
 * The client used to perform operations on Riak.
 * 

* The core of the Java client models a Riak cluster: *

* *

*

* The easiest way to get started with the client API is using one of the static * methods provided to instantiate and start the client: *

*
 * {@code
 * RiakClient client =
 *     RiakClient.newClient("192.168.1.1","192.168.1.2","192.168.1.3"); } 
* * Note that the Riak Java client uses the Riak Protocol Buffers API exclusively. *

* For more complex configurations you will instantiate one or more {@link com.basho.riak.client.core.RiakNode}s * and build a {@link com.basho.riak.client.core.RiakCluster} to supply to the * RiakClient constructor. *

*
 * {@code
 * RiakNode.Builder builder = new RiakNode.Builder();
 * builder.withMinConnections(10);
 * builder.withMaxConnections(50);
 *
 * List addresses = new LinkedList();
 * addresses.add("192.168.1.1");
 * addresses.add("192.168.1.2");
 * addresses.add("192.168.1.3");
 *
 * List nodes = RiakNode.Builder.buildNodes(builder, addresses);
 * RiakCluster cluster = new RiakCluster.Builder(nodes).build();
 * cluster.start();
 * RiakClient client = new RiakClient(cluster); }
*

* Once you have a client, {@literal RiakCommand}s from the {@literal com.basho.riak.client.api.commands.*} * packages are built then executed by the client: *

 * {@code
 * Namespace ns = new Namespace("default","my_bucket");
 * Location loc = new Location(ns, "my_key");
 * FetchValue fv = new FetchValue.Builder(loc).build();
 * FetchValue.Response response = client.execute(fv);
 * RiakObject obj = response.getValue(RiakObject.class);}
*

*

* You can also execute all {@literal RiakCommand}s asynchronously. A * {@link RiakFuture} for the operation is immediately returned: *

 * {@code
 * Namespace ns = new Namespace("default","my_bucket");
 * Location loc = new Location(ns, "my_key");
 * FetchValue fv = new FetchValue.Builder(loc).build();
 * RiakFuture future = client.executeAsync(fv);
 * future.await();
 * if (future.isSuccess())
 * {
 *     FetchValue.Response response = future.getNow();
 *     RiakObject obj = response.getValue(RiakObject.class);
 *     ...
 * }
 * else
 * {
 *     Throwable error = future.cause();
 *     ...
 * }}
*

*

*

RiakCommand subclasses

*

Fetching, storing and deleting objects

*
    *
  • {@link com.basho.riak.client.api.commands.kv.FetchValue}
  • *
  • {@link com.basho.riak.client.api.commands.kv.MultiFetch}
  • *
  • {@link com.basho.riak.client.api.commands.kv.StoreValue}
  • *
  • {@link com.basho.riak.client.api.commands.kv.UpdateValue}
  • *
  • {@link com.basho.riak.client.api.commands.kv.DeleteValue}
  • *
*

Listing keys in a namespace

*
  • {@link com.basho.riak.client.api.commands.kv.ListKeys}
*

Secondary index (2i) commands

*
    *
  • {@link com.basho.riak.client.api.commands.indexes.RawIndexQuery}
  • *
  • {@link com.basho.riak.client.api.commands.indexes.BinIndexQuery}
  • *
  • {@link com.basho.riak.client.api.commands.indexes.IntIndexQuery}
  • *
  • {@link com.basho.riak.client.api.commands.indexes.BigIntIndexQuery}
  • *
*

Fetching and storing datatypes (CRDTs)

*
    *
  • {@link com.basho.riak.client.api.commands.datatypes.FetchCounter}
  • *
  • {@link com.basho.riak.client.api.commands.datatypes.FetchSet}
  • *
  • {@link com.basho.riak.client.api.commands.datatypes.FetchMap}
  • *
  • {@link com.basho.riak.client.api.commands.datatypes.UpdateCounter}
  • *
  • {@link com.basho.riak.client.api.commands.datatypes.UpdateSet}
  • *
  • {@link com.basho.riak.client.api.commands.datatypes.UpdateMap}
  • *
*

Querying and modifying buckets

*
    *
  • {@link com.basho.riak.client.api.commands.buckets.FetchBucketProperties}
  • *
  • {@link com.basho.riak.client.api.commands.buckets.StoreBucketProperties}
  • *
  • {@link com.basho.riak.client.api.commands.buckets.ListBuckets}
  • *
*

Search commands

*
    *
  • {@link com.basho.riak.client.api.commands.search.Search}
  • *
  • {@link com.basho.riak.client.api.commands.search.FetchIndex}
  • *
  • {@link com.basho.riak.client.api.commands.search.StoreIndex}
  • *
  • {@link com.basho.riak.client.api.commands.search.DeleteIndex}
  • *
  • {@link com.basho.riak.client.api.commands.search.FetchSchema}
  • *
  • {@link com.basho.riak.client.api.commands.search.StoreSchema}
  • *
*

Map-Reduce

*
    *
  • {@link com.basho.riak.client.api.commands.mapreduce.BucketMapReduce}
  • *
  • {@link com.basho.riak.client.api.commands.mapreduce.BucketKeyMapReduce}
  • *
  • {@link com.basho.riak.client.api.commands.mapreduce.IndexMapReduce}
  • *
  • {@link com.basho.riak.client.api.commands.mapreduce.SearchMapReduce}
  • *
* @author Dave Rusek * @author Brian Roach * @author Alex Moore * @author Sergey Galkin * @since 2.0 */ public class RiakClient { private final RiakCluster cluster; /** * Create a new RiakClient to perform operations on the given cluster. *

* The RiakClient provides a user API on top of the client core. Once * instantiated, commands are submitted to it for execution on Riak. *

* @param cluster the started RiakCluster to use. */ public RiakClient(RiakCluster cluster) { this.cluster = cluster; } /** * Static factory method to create a new client instance. * This method produces a client that connects to 127.0.0.1 on the default * protocol buffers port (8087). * * @return a new client instance. * @throws UnknownHostException */ public static RiakClient newClient() throws UnknownHostException { RiakNode.Builder builder = new RiakNode.Builder() .withMinConnections(10); RiakCluster cluster = new RiakCluster.Builder(builder.build()).build(); cluster.start(); return new RiakClient(cluster); } /** * Static factory method to create a new client instance. * This method produces a client connected to the supplied addresses on * the supplied port. * @param remoteAddresses a list of IP addresses or hostnames * @param port the (protocol buffers) port to connect to on the supplied hosts. * @return a new client instance * @throws UnknownHostException if a supplied hostname cannot be resolved. */ public static RiakClient newClient(int port, String... remoteAddresses) throws UnknownHostException { return newClient(port, Arrays.asList(remoteAddresses)); } /** * Static factory method to create a new client instance. * This method produces a client connected to the supplied addresses on * the default (protocol buffers) port (8087). * @param remoteAddresses a list of IP addresses or hostnames * @return a new client instance * @throws UnknownHostException if a supplied hostname cannot be resolved. */ public static RiakClient newClient(List remoteAddresses) throws UnknownHostException { return newClient(RiakNode.Builder.DEFAULT_REMOTE_PORT, remoteAddresses); } /** * Static factory method to create a new client instance. * This method produces a client connected to the supplied addresses on * the default (protocol buffers) port (8087). * @param remoteAddresses a list of IP addresses or hostnames * @return a new client instance * @throws UnknownHostException if a supplied hostname cannot be resolved. */ public static RiakClient newClient(String... remoteAddresses) throws UnknownHostException { return newClient(RiakNode.Builder.DEFAULT_REMOTE_PORT, Arrays.asList(remoteAddresses)); } /** * Static factory method to create a new client instance. * This method produces a client connected to the supplied addresses on * the supplied port. * @param remoteAddresses a list of IP addresses or hostnames * @param port the (protocol buffers) port to connect to on the supplied hosts. * @return a new client instance * @throws UnknownHostException if a supplied hostname cannot be resolved. */ public static RiakClient newClient(int port, List remoteAddresses) throws UnknownHostException { RiakNode.Builder builder = createDefaultNodeBuilder() .withRemotePort(port); return newClient(builder, remoteAddresses); } /** * Static factory method to create a new client instance. * This method produces a client connected to the supplied addresses. * @param addresses one or more addresses to connect to. * @return a new RiakClient instance. * @throws java.net.UnknownHostException if a supplied hostname cannot be resolved. */ public static RiakClient newClient(InetSocketAddress... addresses) throws UnknownHostException { final List remoteAddresses = new ArrayList<>(addresses.length); for (InetSocketAddress addy : addresses) { remoteAddresses.add( String.format("%s:%s", addy.getHostName(), addy.getPort()) ); } return newClient(createDefaultNodeBuilder(), remoteAddresses); } /** * Static factory method to create a new client instance. * This method produces a client connected to the supplied addresses and containing the {@link RiakNode}s * that will be build by using provided builder. * @param addresses one or more addresses to connect to. * @return a new RiakClient instance. * @throws java.net.UnknownHostException if a supplied hostname cannot be resolved. * @since 2.0.3 * @see com.basho.riak.client.core.RiakCluster.Builder#RiakCluster.Builder(RiakNode.Builder, List) */ // NB: IntelliJ will see the above @see statement as invalid, but it's correct: https://bugs.openjdk.java.net/browse/JDK-8031625 public static RiakClient newClient(RiakNode.Builder nodeBuilder, List addresses) throws UnknownHostException { final RiakCluster cluster = new RiakCluster.Builder(nodeBuilder, addresses).build(); cluster.start(); return new RiakClient(cluster); } /** * Static factory method to create a new client instance. * * @since 2.0.3 * @see #newClient(RiakNode.Builder, List) */ public static RiakClient newClient(RiakNode.Builder nodeBuilder, String... addresses) throws UnknownHostException { return newClient(nodeBuilder, Arrays.asList(addresses)); } /** * Static factory method to create a new client instance. * * @since 2.0.6 */ public static RiakClient newClient(Collection hosts) throws UnknownHostException { return newClient(hosts, createDefaultNodeBuilder()); } /** * Static factory method to create a new client instance. * * @since 2.0.6 */ public static RiakClient newClient(Collection hosts, RiakNode.Builder nodeBuilder) throws UnknownHostException { final RiakCluster cluster = new RiakCluster.Builder(hosts, nodeBuilder).build(); cluster.start(); return new RiakClient(cluster); } /** * * @since 2.0.3 */ public static RiakNode.Builder createDefaultNodeBuilder() { return new RiakNode.Builder() .withMinConnections(10); } /** * Execute a RiakCommand synchronously. *

* Calling this method causes the client to execute the provided RiakCommand synchronously. * It will block until the operation completes then either return the response * on success or throw an exception on failure. *

* * @param command * The RiakCommand to execute. * @param * The RiakCommand's return type. * @param The RiakCommand's query info type. * @return a response from Riak. * @throws ExecutionException if the command fails for any reason. * @throws InterruptedException */ public T execute(RiakCommand command) throws ExecutionException, InterruptedException { return command.execute(cluster); } /** * Execute a RiakCommand synchronously with a specified client timeout. *

* Calling this method causes the client to execute the provided RiakCommand synchronously. * It will block until the operation completes or up to the given timeout. * It will either return the response on success or throw an * exception on failure. * Note: Using this timeout is different that setting a timeout on the command * itself using the timeout() method of the command's associated builder. * The command timeout is a Riak-side timeout value. This timeout is client-side. *

* * @param command * The RiakCommand to execute. * @param timeout the amount of time to wait before returning an exception * @param unit the unit of time. * @param * The RiakCommand's return type. * @param * The RiakCommand's query info type. * @return a response from Riak. * @throws ExecutionException * if the command fails for any reason. * @throws InterruptedException * @throws TimeoutException * if the call to execute the command did not finish within the time limit */ public T execute(RiakCommand command, long timeout, TimeUnit unit) throws ExecutionException, InterruptedException, TimeoutException { return command.execute(cluster, timeout, unit); } /** * Execute a RiakCommand asynchronously. *

* Calling this method causes the client to execute the provided RiakCommand * asynchronously. It will immediately return a RiakFuture that contains the * running operation. * @param RiakCommand's return type. * @param The RiakCommand's query info type. * @param command The RiakCommand to execute. * @return a RiakFuture for the operation. * @see RiakFuture */ public RiakFuture executeAsync(RiakCommand command) { return command.executeAsync(cluster); } /** * Execute a StreamableRiakCommand asynchronously, and stream the results back before * the command {@link RiakFuture#isDone() is done}. *

* Calling this method causes the client to execute the provided * StreamableRiakCommand asynchronously. * It will immediately return a RiakFuture that contains an * immediately available result (via {@link RiakFuture#get()}) that * data will be streamed to. * The RiakFuture will also keep track of the overall operation's progress * with the {@link RiakFuture#isDone}, etc methods. *

*

* Because the consumer thread will poll for new results, it is advisable to check the * consumer thread's interrupted status via * {@link Thread#isInterrupted() Thread.currentThread().isInterrupted() }, as the result * iterator will not propagate an InterruptedException, but it will set the Thread's * interrupted flag. *

* @param StreamableRiakCommand's immediate return type, available before the command/operation is complete. * @param The RiakCommand's query info type. * @param command The RiakCommand to execute. * @param timeoutMS The polling timeout in milliseconds for each result chunk. * If the timeout is reached it will try again, instead of blocking indefinitely. * If the value is too small (less than the average chunk arrival time), the * result iterator will essentially busy wait. * If the timeout is too large (much greater than the average chunk arrival time), * the result iterator can block the consuming thread from seeing the done() * status until the timeout is reached. * @return a RiakFuture for the operation * @since 2.1.0 * @see RiakFuture */ public RiakFuture executeAsyncStreaming(StreamableRiakCommand command, int timeoutMS) { return command.executeAsyncStreaming(cluster, timeoutMS); } /** * Shut down the client and the underlying RiakCluster. *

* The underlying client core (RiakCluster) uses a number of threads as * does Netty. Calling this method will shut down all those threads cleanly. * Failure to do so may prevent your application from exiting. *

* @return a future that will complete when shutdown */ public Future shutdown() { return cluster.shutdown(); } /** * Get the RiakCluster being used by this client. *

* Allows for adding/removing nodes, etc. *

* @return The RiakCluster instance being used by this client. */ public RiakCluster getRiakCluster() { return cluster; } /** * Cleans up any Thread-Local variables after shutdown. * This operation is useful when you are in a container environment, and you * do not want to leave the thread local variables in the threads you do not manage. * Call this method when your application is being unloaded from the container, after * all {@link RiakNode}, {@link RiakCluster}, and {@link com.basho.riak.client.api.RiakClient} * objects are in the shutdown state. */ public void cleanup() { cluster.cleanup(); } }