Permalink
Browse files

Added documentation.

  • Loading branch information...
1 parent 108c448 commit 4008155f4a6829421233e4bf264b987f76604fd1 Alex Feinberg committed Dec 15, 2009
Showing with 105 additions and 73 deletions.
  1. +105 −73 src/java/voldemort/client/protocol/admin/AdminClient.java
@@ -59,9 +59,10 @@
import com.google.protobuf.Message;
/**
- * Protocol buffers implementation for
- * {@link voldemort.client.protocol.admin.AdminClientOLD} *
- *
+ * AdminClient is intended for administrative functionality that is useful and often needed, but should be used
+ * sparingly (if at all) at the application level. Some of the uses of AdminClient include the extraction of data,
+ * backups, bulk loads as well as the (presently in development) rebalancing feature.
+ *
* @author afeinberg,bbansal
*/
public class AdminClient {
@@ -71,16 +72,21 @@
private final SocketPool pool;
private final NetworkClassLoader networkClassLoader;
private static final ClusterMapper clusterMapper = new ClusterMapper();
- private static final StoreDefinitionsMapper storeMapper = new StoreDefinitionsMapper();
+ private static final StoreDefinitionsMapper storeMapper = new StoreDefinitionsMapper();
// Parameters for exponential back off
private static final long INITIAL_DELAY = 250; // Initial delay
- private static final long MAX_DELAY = 1000 * 60; // Stop doing exponential
- // back off once delay
- // reaches this
+ private static final long MAX_DELAY = 1000 * 60; // Stop doing exponential back off once we're waiting this long
private Cluster cluster;
+ /**
+ * Create an instance of Admin Client given a cluster-wide bootstrap URL. In this case,
+ * we will obtain the cluster metadata by contacting the boostrap node.
+ *
+ * @param bootstrapURL URL pointing to the boostrap node
+ * @param config Configuration for a Voldemort client (not specific to Admin API)
+ */
public AdminClient(String bootstrapURL, ClientConfig config) {
this.cluster = getClusterFromBootstrapURL(bootstrapURL, config);
this.errorMapper = new ErrorCodeMapper();
@@ -89,6 +95,12 @@ public AdminClient(String bootstrapURL, ClientConfig config) {
.getContextClassLoader());
}
+ /**
+ * Create an instance of Admin Client given the metadata in a cluster object.
+ *
+ * @param cluster Initialized cluster object, describing the nodes we wish to contact
+ * @param config Configuration for a Voldemort client (not specific to Admin API)
+ */
public AdminClient(Cluster cluster, ClientConfig config) {
this.cluster = cluster;
this.errorMapper = new ErrorCodeMapper();
@@ -116,7 +128,7 @@ private SocketPool createSocketPool(ClientConfig config) {
config.getSocketBufferSize());
}
- protected <T extends Message.Builder> T sendAndReceive(int nodeId, Message message, T builder) {
+ private <T extends Message.Builder> T sendAndReceive(int nodeId, Message message, T builder) {
Node node = this.getCluster().getNodeById(nodeId);
SocketDestination destination = new SocketDestination(node.getHost(),
node.getAdminPort(),
@@ -139,16 +151,23 @@ private SocketPool createSocketPool(ClientConfig config) {
}
/**
- * update Entries at (remote) node with all entries in iterator for passed
- * storeName
+ * Update key/value entries for a specific store on a remote node given an iterator of the entries.
+ * The entries are <em>streamed</em> from the client to the server:
+ * <ol>
+ * <li>Client performs a handshake with the server (sending in the update entries request with a
+ * store name and a {@link VoldemortFilter} instance.</li>
+ * <li>While {@param entryIterator} has entries, the client will keep sending the updates one after
+ * another to the server, buffering the data, without waiting for a response from the server.</li>
+ * <li>After iteration is complete, send an end of stream message, force a flush of the buffer, check the
+ * response on the server to check if a {@link VoldemortException} has occured.</li>
+ * </ol>
*
- * @param nodeId
- * @param storeName
- * @param entryIterator
+ * @param nodeId Id of the remote node (where we wish to update the entries)
+ * @param storeName Store name for the entries
+ * @param entryIterator Iterator of key-value pairs for the entries
* @param filter: <imp>Do not Update entries filtered out (returned false)
* from the {@link VoldemortFilter} implementation</imp>
* @throws VoldemortException
- * @throws IOException
*/
public void updateEntries(int nodeId,
String storeName,
@@ -228,7 +247,7 @@ private void initiateFetchRequest(DataOutputStream outputStream,
}
- VAdminProto.FetchPartitionEntriesResponse responseFromStream(DataInputStream inputStream,
+ private VAdminProto.FetchPartitionEntriesResponse responseFromStream(DataInputStream inputStream,
int size) throws IOException {
byte[] input = new byte[size];
ByteUtils.read(inputStream, input);
@@ -239,15 +258,20 @@ private void initiateFetchRequest(DataOutputStream outputStream,
}
/**
- * streaming API to get all entries belonging to any of the partition in the
- * input List.
+ * Fetch all key/value entries belong to the partitions listed from the server to the client. Just like
+ * {@link AdminClient#updateEntries}, this is a streaming API. The server keeps sending the messages as it's
+ * iterating over the data. Once iteration has finished, the server sends an "end of stream" marker and flushes its
+ * buffer. A response indicating a {@link VoldemortException} may be sent at any time during the process.
+ *
+ * Entries are being streamed <em>as the iteration happens</em>; that is, the whole result set is <b>not</b>
+ * buffered in memory.
*
- * @param nodeId
- * @param storeName
- * @param partitionList
+ * @param nodeId Id of the node to fetch from
+ * @param storeName Name of the store
+ * @param partitionList List of the partitions
* @param filter: <imp>Do not fetch entries filtered out (returned false)
* from the {@link VoldemortFilter} implementation</imp>
- * @return
+ * @return An iterator which allows entries to be streamed as they're being iterated over.
* @throws VoldemortException
*/
public Iterator<Pair<ByteArray, Versioned<byte[]>>> fetchPartitionEntries(int nodeId,
@@ -304,14 +328,13 @@ private void initiateFetchRequest(DataOutputStream outputStream,
}
/**
- * streaming API to get a list of all the keys that belong to any of the
- * partitions in the input list
- *
- * @param nodeId
- * @param storeName
- * @param partitionList
- * @param filter
- * @return
+ * Identical to {@link AdminClient#fetchPartitionEntries} but will <em>only fetch the keys</em>
+ *
+ * @param nodeId See documentation for {@link AdminClient#fetchPartitionEntries}
+ * @param storeName See documentation for {@link AdminClient#fetchPartitionEntries}
+ * @param partitionList See documentation for {@link AdminClient#fetchPartitionEntries}
+ * @param filter See documentation for {@link AdminClient#fetchPartitionEntries}
+ * @return See documentation for {@link AdminClient#fetchPartitionEntries}
*/
public Iterator<ByteArray> fetchPartitionKeys(int nodeId,
String storeName,
@@ -364,7 +387,19 @@ public ByteArray computeNext() {
}
/**
- * Pipe fetch from donorNode and update stealerNode in streaming mode.
+ * Update entries in a list of partitions on one node as we're streaming them from another. This is
+ * a background operation (see {@link voldemort.server.protocol.admin.AsyncOperation} that runs on the node on
+ * which the updates are performed (the "stealer" node). See {@link AdminClient#updateEntries} for
+ * more informaiton on the "streaming" mode.
+ *
+ * @param donorNodeId Node <em>from</em> which the partitions are to be streamed.
+ * @param stealerNodeId Node <em>to</em> which the partitions are to be streamed.
+ * @param storeName Name of the store to stream.
+ * @param stealList List of partitions to stream.
+ * @param filter <imp>Do not stream entries filtered out (returned false)
+ * from the {@link VoldemortFilter} implementation</imp>.
+ * @return The value of the {@link voldemort.server.protocol.admin.AsyncOperation} created on stealerNodeId which
+ * is performing the operation.
*/
public int fetchAndUpdateStreams(int donorNodeId,
int stealerNodeId,
@@ -398,6 +433,14 @@ public int fetchAndUpdateStreams(int donorNodeId,
return response.getRequestId();
}
+ /**
+ * Get the status of an {@link voldemort.server.protocol.admin.AsyncOperation} which is running on nodeId. If
+ * The operation is complete, then the operation will be removed from a list of currently running operations.
+ *
+ * @param nodeId Id on which the operation is running
+ * @param requestId Id of the operation itself
+ * @return The status of the operation
+ */
public AsyncOperationStatus getAsyncRequestStatus(int nodeId, int requestId) {
VAdminProto.AsyncOperationStatusRequest asyncRequest = VAdminProto.AsyncOperationStatusRequest.newBuilder()
.setRequestId(requestId)
@@ -431,15 +474,16 @@ public AsyncOperationStatus getAsyncRequestStatus(int nodeId, int requestId) {
}
/**
- * Delete all Entries at (remote) node for partitions in partitionList
+ * Delete all entries in store storeName on (remote) node nodeId which are specified in the list of
+ * partitions (partitionList).
*
- * @param nodeId
- * @param storeName
- * @param partitionList
+ * @param nodeId Node on which the entries to be deleted
+ * @param storeName Name of the store holding the entries
+ * @param partitionList List of partitions to delete.
* @param filter: <imp>Do not Delete entries filtered out (returned false)
* from the {@link VoldemortFilter} implementation</imp>
* @throws VoldemortException
- * @throws IOException
+ * @return Number of partitions deleted
*/
public int deletePartitions(int nodeId,
String storeName,
@@ -489,14 +533,13 @@ public void stop() {
/**
* Wait for a task to finish completion, using exponential backoff to poll
- * the task completion status
+ * the task completion status.
*
* @param nodeId Id of the node to poll
* @param requestId Id of the request to check
* @param maxWait Maximum time we'll keep checking a request until we give
* up
- * @param timeUnit Unit in which
- * @param maxWait is expressed
+ * @param timeUnit Unit in which maxWait is expressed.
* @throws VoldemortException if task failed to finish in specified maxWait
* time.
*/
@@ -508,9 +551,10 @@ public void waitForCompletion(int nodeId, int requestId, long maxWait, TimeUnit
AsyncOperationStatus status = getAsyncRequestStatus(nodeId, requestId);
if(status.isComplete())
return;
- if(delay < MAX_DELAY)
- // keep doubling the wait period until we rach maxDelay
+ if(delay < MAX_DELAY) {
+ // keep doubling the wait period until we reach maxDelay
delay <<= 2;
+ }
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
@@ -521,14 +565,15 @@ public void waitForCompletion(int nodeId, int requestId, long maxWait, TimeUnit
+ maxWait + " " + timeUnit.toString());
}
- /* Helper functions */
/**
- * update metadata at remote node.
+ * Update metadata on a remote node. Metadata includes information about cluster geometry,
+ * the stores available, the present state of the cluster. See {@link voldemort.store.metadata.MetadataStore}
+ * for more information.
*
- * @param remoteNodeId
- * @param key
- * @param value
+ * @param remoteNodeId Id of the node
+ * @param key Metadata key to update
+ * @param value Value for the metadata key
*/
public void updateRemoteMetadata(int remoteNodeId, String key, Versioned<String> value) {
ByteArray keyBytes = new ByteArray(ByteUtils.getBytes(key, "UTF-8"));
@@ -551,11 +596,11 @@ public void updateRemoteMetadata(int remoteNodeId, String key, Versioned<String>
}
/**
- * get metadata from remote node.
+ * Get the metadata on a remote node. See {@link AdminClient#updateRemoteMetadata)} for more documentation.
*
- * @param remoteNodeId
- * @param key
- * @return
+ * @param remoteNodeId See {@link AdminClient#updateRemoteMetadata)} for documentation.
+ * @param key See {@link AdminClient#updateRemoteMetadata)} for documentation.
+ * @return Metadata with its associated {@link voldemort.versioning.Version}
*/
public Versioned<String> getRemoteMetadata(int remoteNodeId, String key) {
ByteArray keyBytes = new ByteArray(ByteUtils.getBytes(key, "UTF-8"));
@@ -577,10 +622,10 @@ public void updateRemoteMetadata(int remoteNodeId, String key, Versioned<String>
}
/**
- * update cluster information on a remote node.
+ * Update the cluster information {@link MetadataStore#CLUSTER_KEY} on a remote node.
*
- * @param nodeId
- * @param cluster
+ * @param nodeId Id of the remote node
+ * @param cluster The new cluster object
* @throws VoldemortException
*/
public void updateRemoteCluster(int nodeId, Cluster cluster) throws VoldemortException {
@@ -594,10 +639,10 @@ public void updateRemoteCluster(int nodeId, Cluster cluster) throws VoldemortExc
}
/**
- * get cluster information from a remote node.
+ * Get the cluster information from a remote node.
*
- * @param nodeId
- * @return
+ * @param nodeId Node to retrieve information from
+ * @return A cluster object with its {@link voldemort.versioning.Version}
* @throws VoldemortException
*/
public Versioned<Cluster> getRemoteCluster(int nodeId) throws VoldemortException {
@@ -608,11 +653,7 @@ public void updateRemoteCluster(int nodeId, Cluster cluster) throws VoldemortExc
}
/**
- * update store definitions on remote node.
- *
- * @param nodeId
- * @param storesList
- * @throws VoldemortException
+ * Update the store definitions on a remote node.
*/
public void updateRemoteStoreDefList(int nodeId, List<StoreDefinition> storesList)
throws VoldemortException {
@@ -626,11 +667,7 @@ public void updateRemoteStoreDefList(int nodeId, List<StoreDefinition> storesLis
}
/**
- * get store definitions from a remote node.
- *
- * @param nodeId
- * @return
- * @throws VoldemortException
+ * Retrieve the store definitions from a remote node.
*/
public Versioned<List<StoreDefinition>> getRemoteStoreDefList(int nodeId)
throws VoldemortException {
@@ -640,10 +677,7 @@ public void updateRemoteStoreDefList(int nodeId, List<StoreDefinition> storesLis
}
/**
- * update serverState on a remote node.
- *
- * @param nodeId
- * @param state
+ * Update the server state ({@link voldemort.store.metadata.MetadataStore.VoldemortState}) on a remote node.
*/
public void updateRemoteServerState(int nodeId, MetadataStore.VoldemortState state) {
VectorClock oldClock = (VectorClock) getRemoteServerState(nodeId).getVersion();
@@ -655,10 +689,8 @@ public void updateRemoteServerState(int nodeId, MetadataStore.VoldemortState sta
}
/**
- * get serverState from a remoteNode.
- *
- * @param nodeId
- * @return
+ * Retrieve the server state ({@link voldemort.store.metadata.MetadataStore.VoldemortState} from
+ * a remote node.
*/
public Versioned<VoldemortState> getRemoteServerState(int nodeId) {
Versioned<String> value = getRemoteMetadata(nodeId, MetadataStore.SERVER_STATE_KEY);

0 comments on commit 4008155

Please sign in to comment.