|
@@ -18,65 +18,98 @@ package org.apache.hadoop.dfs;
|
|
|
import java.io.*;
|
|
|
|
|
|
/**********************************************************************
|
|
|
- * Protocol that an DFS client uses to communicate with the NameNode.
|
|
|
- * It's used to manipulate the namespace, and obtain datanode info.
|
|
|
+ * ClientProtocol is used by a piece of DFS user code to communicate
|
|
|
+ * with the NameNode. User code can manipulate the directory namespace,
|
|
|
+ * as well as open/close file streams, etc.
|
|
|
*
|
|
|
* @author Mike Cafarella
|
|
|
**********************************************************************/
|
|
|
interface ClientProtocol {
|
|
|
|
|
|
+ ///////////////////////////////////////
|
|
|
+ // File contents
|
|
|
+ ///////////////////////////////////////
|
|
|
/**
|
|
|
- * Open an existing file. Get back block and datanode info
|
|
|
+ * Open an existing file, at the given name. Returns block
|
|
|
+ * and DataNode info. The client will then have to contact
|
|
|
+ * each indicated DataNode to obtain the actual data. There
|
|
|
+ * is no need to call close() or any other function after
|
|
|
+ * calling open().
|
|
|
*/
|
|
|
public LocatedBlock[] open(String src) throws IOException;
|
|
|
|
|
|
/**
|
|
|
- * Create a new file. Get back block and datanode info
|
|
|
+ * Create a new file. Get back block and datanode info,
|
|
|
+ * which describes where the first block should be written.
|
|
|
+ *
|
|
|
+ * Successfully calling this method prevents any other
|
|
|
+ * client from creating a file under the given name, but
|
|
|
+ * the caller must invoke complete() for the file to be
|
|
|
+ * added to the filesystem.
|
|
|
+ *
|
|
|
+ * Blocks have a maximum size. Clients that intend to
|
|
|
+ * create multi-block files must also use reportWrittenBlock()
|
|
|
+ * and addBlock().
|
|
|
*/
|
|
|
public LocatedBlock create(String src, String clientName, boolean overwrite) throws IOException;
|
|
|
|
|
|
/**
|
|
|
- * The client wants to write an additional block to the indicated
|
|
|
- * filename (which must currently be open for writing). Return
|
|
|
- * block and datanode info. A null response means the caller
|
|
|
- * should attempt the call again.
|
|
|
+ * A client that has written a block of data can report completion
|
|
|
+ * back to the NameNode with reportWrittenBlock(). Clients cannot
|
|
|
+ * obtain an additional block until the previous one has either been
|
|
|
+ * reported as written or abandoned.
|
|
|
*/
|
|
|
- public LocatedBlock addBlock(String src) throws IOException;
|
|
|
+ public void reportWrittenBlock(LocatedBlock b) throws IOException;
|
|
|
|
|
|
/**
|
|
|
- * The client wants to report a block it has just successfully
|
|
|
- * written to one or more datanodes. Client-written blocks are
|
|
|
- * always reported by the client, not by the datanode.
|
|
|
+ * If the client has not yet called reportWrittenBlock(), it can
|
|
|
+ * give up on it by calling abandonBlock(). The client can then
|
|
|
+ * either obtain a new block, or complete or abandon the file.
|
|
|
+ *
|
|
|
+ * Any partial writes to the block will be garbage-collected.
|
|
|
*/
|
|
|
- public void reportWrittenBlock(LocatedBlock b) throws IOException;
|
|
|
+ public void abandonBlock(Block b, String src) throws IOException;
|
|
|
|
|
|
/**
|
|
|
- * The client wants to abandon writing to the indicated block,
|
|
|
- * part of the indicated (currently-open) filename.
|
|
|
+ * A client that wants to write an additional block to the
|
|
|
+ * indicated filename (which must currently be open for writing)
|
|
|
+ * should call addBlock().
|
|
|
+ *
|
|
|
+ * addBlock() returns block and datanode info, just like the initial
|
|
|
+ * call to create().
|
|
|
+ *
|
|
|
+ * A null response means the NameNode could not allocate a block,
|
|
|
+ * and that the caller should try again.
|
|
|
*/
|
|
|
- public void abandonBlock(Block b, String src) throws IOException;
|
|
|
+ public LocatedBlock addBlock(String src) throws IOException;
|
|
|
|
|
|
/**
|
|
|
- * The client wants to abandon writing to the current file, and
|
|
|
- * let anyone else grab it.
|
|
|
+ * A client that wants to abandon writing to the current file
|
|
|
+ * should call abandonFileInProgress(). After this call, any
|
|
|
+ * client can call create() to obtain the filename.
|
|
|
+ *
|
|
|
+ * Any blocks that have been written for the file will be
|
|
|
+ * garbage-collected.
|
|
|
*/
|
|
|
public void abandonFileInProgress(String src) throws IOException;
|
|
|
|
|
|
/**
|
|
|
* The client is done writing data to the given filename, and would
|
|
|
- * like to complete it. Returns whether the file has been closed
|
|
|
- * correctly (true) or whether caller should try again (false).
|
|
|
- * (Because the namenode is waiting for a block to complete).
|
|
|
+ * like to complete it.
|
|
|
+ *
|
|
|
+ * The function returns whether the file has been closed successfully.
|
|
|
+ * If the function returns false, the caller should try again.
|
|
|
+ *
|
|
|
+ * A call to complete() will not return true until all the file's
|
|
|
+ * blocks have been replicated the minimum number of times. Thus,
|
|
|
+ * DataNode failures may cause a client to call complete() several
|
|
|
+ * times before succeeding.
|
|
|
*/
|
|
|
public boolean complete(String src, String clientName) throws IOException;
|
|
|
-
|
|
|
- /**
|
|
|
- * The client wants to read the indicated filename at a certain offset.
|
|
|
- * Return a list of hostnames where the data can be found. (Return
|
|
|
- * a set of hostnames for every block.)
|
|
|
- */
|
|
|
- public String[][] getHints(String src, long start, long len) throws IOException;
|
|
|
|
|
|
+ ///////////////////////////////////////
|
|
|
+ // Namespace management
|
|
|
+ ///////////////////////////////////////
|
|
|
/**
|
|
|
* Rename an item in the fs namespace
|
|
|
*/
|
|
@@ -104,36 +137,71 @@ interface ClientProtocol {
|
|
|
public boolean mkdirs(String src) throws IOException;
|
|
|
|
|
|
/**
|
|
|
- * The client is trying to obtain a lock. Return whether the lock has
|
|
|
- * been seized correctly (true), or whether the client should try again
|
|
|
- * (false).
|
|
|
+ * Get a listing of the indicated directory
|
|
|
*/
|
|
|
- public boolean obtainLock(String src, String clientName, boolean exclusive) throws IOException;
|
|
|
+ public DFSFileInfo[] getListing(String src) throws IOException;
|
|
|
|
|
|
+ ///////////////////////////////////////
|
|
|
+ // System issues and management
|
|
|
+ ///////////////////////////////////////
|
|
|
/**
|
|
|
- * The client wants to release a held lock. Return whether the lock was
|
|
|
- * correctly released (true), or whether the client should wait and try the
|
|
|
- * call again (false).
|
|
|
+ * getHints() returns a list of hostnames that store data for
|
|
|
+ * a specific file region. It returns a set of hostnames for
|
|
|
+ * every block within the indicated region.
|
|
|
+ *
|
|
|
+ * This function is very useful when writing code that considers
|
|
|
+ * data-placement when performing operations. For example, the
|
|
|
+ * MapReduce system tries to schedule tasks on the same machines
|
|
|
+ * as the data-block the task processes.
|
|
|
*/
|
|
|
- public boolean releaseLock(String src, String clientName) throws IOException;
|
|
|
+ public String[][] getHints(String src, long start, long len) throws IOException;
|
|
|
+ /**
|
|
|
+ * obtainLock() is used for lock managemnet. It returns true if
|
|
|
+ * the lock has been seized correctly. It returns false if the
|
|
|
+ * lock could not be obtained, and the client should try again.
|
|
|
+ *
|
|
|
+ * Locking is a part of most filesystems and is useful for a
|
|
|
+ * number of inter-process synchronization tasks.
|
|
|
+ */
|
|
|
+ public boolean obtainLock(String src, String clientName, boolean exclusive) throws IOException;
|
|
|
|
|
|
/**
|
|
|
- * The client machine wants to obtain a lease
|
|
|
+ * releaseLock() is called if the client would like to release
|
|
|
+ * a held lock. It returns true if the lock is correctly released.
|
|
|
+ * It returns false if the client should wait and try again.
|
|
|
*/
|
|
|
- public void renewLease(String clientName) throws IOException;
|
|
|
+ public boolean releaseLock(String src, String clientName) throws IOException;
|
|
|
|
|
|
/**
|
|
|
- * Get a listing of the indicated directory
|
|
|
+ * Client programs can cause stateful changes in the NameNode
|
|
|
+ * that affect other clients. A client may obtain a file and
|
|
|
+ * neither abandon nor complete it. A client might hold a series
|
|
|
+ * of locks that prevent other clients from proceeding.
|
|
|
+ * Clearly, it would be bad if a client held a bunch of locks
|
|
|
+ * that it never gave up. This can happen easily if the client
|
|
|
+ * dies unexpectedly.
|
|
|
+ *
|
|
|
+ * So, the NameNode will revoke the locks and live file-creates
|
|
|
+ * for clients that it thinks have died. A client tells the
|
|
|
+ * NameNode that it is still alive by periodically calling
|
|
|
+ * renewLease(). If a certain amount of time passes since
|
|
|
+ * the last call to renewLease(), the NameNode assumes the
|
|
|
+ * client has died.
|
|
|
*/
|
|
|
- public DFSFileInfo[] getListing(String src) throws IOException;
|
|
|
+ public void renewLease(String clientName) throws IOException;
|
|
|
|
|
|
/**
|
|
|
* Get a set of statistics about the filesystem.
|
|
|
+ * Right now, only two values are returned.
|
|
|
+ * [0] contains the total storage capacity of the system,
|
|
|
+ * in bytes.
|
|
|
+ * [1] contains the available storage of the system, in bytes.
|
|
|
*/
|
|
|
public long[] getStats() throws IOException;
|
|
|
|
|
|
/**
|
|
|
* Get a full report on the system's current datanodes.
|
|
|
+ * One DatanodeInfo object is returned for each DataNode.
|
|
|
*/
|
|
|
public DatanodeInfo[] getDatanodeReport() throws IOException;
|
|
|
}
|