Author: szetszwo Date: Wed Oct 19 21:44:29 2011 New Revision: 1186512 URL: http://svn.apache.org/viewvc?rev=1186512&view=rev Log: svn merge -c 1186509 from branch-0.20-security for HDFS-2453.
Added: hadoop/common/branches/branch-0.20-security-205/src/test/org/apache/hadoop/hdfs/TestByteRangeInputStream.java - copied unchanged from r1186509, hadoop/common/branches/branch-0.20-security/src/test/org/apache/hadoop/hdfs/TestByteRangeInputStream.java Modified: hadoop/common/branches/branch-0.20-security-205/ (props changed) hadoop/common/branches/branch-0.20-security-205/CHANGES.txt (contents, props changed) hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/ByteRangeInputStream.java hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/server/datanode/web/resources/DatanodeWebHdfsMethods.java hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/WebHdfsFileSystem.java hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/resources/ExceptionHandler.java hadoop/common/branches/branch-0.20-security-205/src/test/org/apache/hadoop/hdfs/web/TestWebHdfsFileSystemContract.java Propchange: hadoop/common/branches/branch-0.20-security-205/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Wed Oct 19 21:44:29 2011 @@ -1,6 +1,6 @@ /hadoop/common/branches/branch-0.20:826138,826568,829987,831184,833001,880632,898713,909245,909723,960946,990003,1044225 /hadoop/common/branches/branch-0.20-append:955380,955398,955448,956329 -/hadoop/common/branches/branch-0.20-security:1170042,1170087,1170997,1171137,1171380,1171613,1171891,1171905,1172184,1172188,1172190,1172192,1173470,1174471,1175114,1176179,1176720,1177907,1179036,1179171,1179519,1179857,1183086,1183101,1183176,1183556 +/hadoop/common/branches/branch-0.20-security:1170042,1170087,1170997,1171137,1171380,1171613,1171891,1171905,1172184,1172188,1172190,1172192,1173470,1174471,1175114,1176179,1176720,1177907,1179036,1179171,1179519,1179857,1183086,1183101,1183176,1183556,1186509 /hadoop/common/branches/branch-0.20-security-203:1096071,1097011,1097249,1097269,1097281,1097966,1098816,1098819,1098823,1098827,1098832,1098839,1098854,1098863,1099088,1099191,1099324,1099330,1099333,1102071,1128115 /hadoop/common/branches/branch-0.20-security-204:1128390,1147228,1148069,1149316,1154413 /hadoop/core/branches/branch-0.19:713112 Modified: hadoop/common/branches/branch-0.20-security-205/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-205/CHANGES.txt?rev=1186512&r1=1186511&r2=1186512&view=diff ============================================================================== --- hadoop/common/branches/branch-0.20-security-205/CHANGES.txt (original) +++ hadoop/common/branches/branch-0.20-security-205/CHANGES.txt Wed Oct 19 21:44:29 2011 @@ -18,6 +18,10 @@ Release 0.20.205.1 - unreleased file or creating a file without specifying the replication parameter. (szetszwo) + HDFS-2453. Fix http response code for partial content in webhdfs, added + getDefaultBlockSize() and getDefaultReplication() in WebHdfsFileSystem + and cleared content type in ExceptionHandler. (szetszwo) + Release 0.20.205.0 - 2011.10.06 NEW FEATURES Propchange: hadoop/common/branches/branch-0.20-security-205/CHANGES.txt ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Wed Oct 19 21:44:29 2011 @@ -1,6 +1,6 @@ /hadoop/common/branches/branch-0.20/CHANGES.txt:826138,826568,829987,831184,833001,880632,898713,909245,909723,960946,990003,1044225 /hadoop/common/branches/branch-0.20-append/CHANGES.txt:955380,955398,955448,956329 -/hadoop/common/branches/branch-0.20-security/CHANGES.txt:1170042,1170087,1170997,1171137,1171181,1171380,1171613,1171891,1171905,1172184,1172188,1172190,1172192,1173470,1173843,1174326,1174471,1174476,1174482,1175114,1176179,1176182,1176270,1176276,1176675,1176720,1177031,1177036,1177098,1177101,1177907,1178074,1179036,1179171,1179471,1179519,1179713,1179722,1179857,1179919,1183086,1183101,1183176,1183556 +/hadoop/common/branches/branch-0.20-security/CHANGES.txt:1170042,1170087,1170997,1171137,1171181,1171380,1171613,1171891,1171905,1172184,1172188,1172190,1172192,1173470,1173843,1174326,1174471,1174476,1174482,1175114,1176179,1176182,1176270,1176276,1176675,1176720,1177031,1177036,1177098,1177101,1177907,1178074,1179036,1179171,1179471,1179519,1179713,1179722,1179857,1179919,1183086,1183101,1183176,1183556,1186509 /hadoop/common/branches/branch-0.20-security-203/CHANGES.txt:1096071,1097011,1097249,1097269,1097281,1097966,1098816,1098819,1098823,1098827,1098832,1098839,1098854,1098863,1099088,1099191,1099324,1099330,1099333,1102071,1128115 /hadoop/common/branches/branch-0.20-security-204/CHANGES.txt:1128390,1147228,1148069,1149316,1154413,1159730,1161741 /hadoop/core/branches/branch-0.18/CHANGES.txt:727226 Modified: hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/ByteRangeInputStream.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/ByteRangeInputStream.java?rev=1186512&r1=1186511&r2=1186512&view=diff ============================================================================== --- hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/ByteRangeInputStream.java (original) +++ hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/ByteRangeInputStream.java Wed Oct 19 21:44:29 2011 @@ -22,10 +22,13 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; +import java.net.MalformedURLException; import java.net.URL; +import java.util.StringTokenizer; import org.apache.hadoop.fs.FSInputStream; import org.apache.hadoop.hdfs.server.namenode.StreamFile; +import org.apache.hadoop.hdfs.web.resources.OffsetParam; /** * To support HTTP byte streams, a new connection to an HTTP server needs to be @@ -42,6 +45,8 @@ public class ByteRangeInputStream extend */ static class URLOpener { protected URL url; + /** The url with offset parameter */ + private URL offsetUrl; public URLOpener(URL u) { url = u; @@ -54,12 +59,55 @@ public class ByteRangeInputStream extend public URL getURL() { return url; } - - public HttpURLConnection openConnection() throws IOException { - return (HttpURLConnection)url.openConnection(); + + HttpURLConnection openConnection() throws IOException { + return (HttpURLConnection)offsetUrl.openConnection(); + } + + private HttpURLConnection openConnection(final long offset) throws IOException { + offsetUrl = offset == 0L? url: new URL(url + "&" + new OffsetParam(offset)); + final HttpURLConnection conn = openConnection(); + conn.setRequestMethod("GET"); + if (offset != 0L) { + conn.setRequestProperty("Range", "bytes=" + offset + "-"); + } + return conn; } } + static private final String OFFSET_PARAM_PREFIX = OffsetParam.NAME + "="; + + /** Remove offset parameter, if there is any, from the url */ + static URL removeOffsetParam(final URL url) throws MalformedURLException { + String query = url.getQuery(); + if (query == null) { + return url; + } + final String lower = query.toLowerCase(); + if (!lower.startsWith(OFFSET_PARAM_PREFIX) + && !lower.contains("&" + OFFSET_PARAM_PREFIX)) { + return url; + } + + //rebuild query + StringBuilder b = null; + for(final StringTokenizer st = new StringTokenizer(query, "&"); + st.hasMoreTokens();) { + final String token = st.nextToken(); + if (!token.toLowerCase().startsWith(OFFSET_PARAM_PREFIX)) { + if (b == null) { + b = new StringBuilder("?").append(token); + } else { + b.append('&').append(token); + } + } + } + query = b == null? "": b.toString(); + + final String urlStr = url.toString(); + return new URL(urlStr.substring(0, urlStr.indexOf('?')) + query); + } + enum StreamStatus { NORMAL, SEEK } @@ -95,12 +143,8 @@ public class ByteRangeInputStream extend final URLOpener opener = (resolvedURL.getURL() == null) ? originalURL : resolvedURL; - final HttpURLConnection connection = opener.openConnection(); + final HttpURLConnection connection = opener.openConnection(startPos); try { - connection.setRequestMethod("GET"); - if (startPos != 0) { - connection.setRequestProperty("Range", "bytes="+startPos+"-"); - } connection.connect(); final String cl = connection.getHeaderField(StreamFile.CONTENT_LENGTH); filelength = (cl == null) ? -1 : Long.parseLong(cl); @@ -125,7 +169,7 @@ public class ByteRangeInputStream extend throw new IOException("HTTP_OK expected, received " + respCode); } - resolvedURL.setURL(connection.getURL()); + resolvedURL.setURL(removeOffsetParam(connection.getURL())); status = StreamStatus.NORMAL; } Modified: hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/server/datanode/web/resources/DatanodeWebHdfsMethods.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/server/datanode/web/resources/DatanodeWebHdfsMethods.java?rev=1186512&r1=1186511&r2=1186512&view=diff ============================================================================== --- hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/server/datanode/web/resources/DatanodeWebHdfsMethods.java (original) +++ hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/server/datanode/web/resources/DatanodeWebHdfsMethods.java Wed Oct 19 21:44:29 2011 @@ -100,7 +100,7 @@ public class DatanodeWebHdfsMethods { final ReplicationParam replication, @QueryParam(BlockSizeParam.NAME) @DefaultValue(BlockSizeParam.DEFAULT) final BlockSizeParam blockSize - ) throws IOException, URISyntaxException, InterruptedException { + ) throws IOException, InterruptedException { if (LOG.isTraceEnabled()) { LOG.trace(op + ": " + path + ", ugi=" + ugi @@ -156,7 +156,7 @@ public class DatanodeWebHdfsMethods { final PostOpParam op, @QueryParam(BufferSizeParam.NAME) @DefaultValue(BufferSizeParam.DEFAULT) final BufferSizeParam bufferSize - ) throws IOException, URISyntaxException, InterruptedException { + ) throws IOException, InterruptedException { if (LOG.isTraceEnabled()) { LOG.trace(op + ": " + path + ", ugi=" + ugi @@ -209,7 +209,7 @@ public class DatanodeWebHdfsMethods { final LengthParam length, @QueryParam(BufferSizeParam.NAME) @DefaultValue(BufferSizeParam.DEFAULT) final BufferSizeParam bufferSize - ) throws IOException, URISyntaxException, InterruptedException { + ) throws IOException, InterruptedException { if (LOG.isTraceEnabled()) { LOG.trace(op + ": " + path + ", ugi=" + ugi @@ -248,7 +248,11 @@ public class DatanodeWebHdfsMethods { } } }; - return Response.ok(streaming).type(MediaType.APPLICATION_OCTET_STREAM).build(); + + final int status = offset.getValue() == 0? + HttpServletResponse.SC_OK: HttpServletResponse.SC_PARTIAL_CONTENT; + return Response.status(status).entity(streaming).type( + MediaType.APPLICATION_OCTET_STREAM).build(); } case GETFILECHECKSUM: { Modified: hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/WebHdfsFileSystem.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/WebHdfsFileSystem.java?rev=1186512&r1=1186511&r2=1186512&view=diff ============================================================================== --- hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/WebHdfsFileSystem.java (original) +++ hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/WebHdfsFileSystem.java Wed Oct 19 21:44:29 2011 @@ -31,6 +31,8 @@ import java.net.URL; import java.security.PrivilegedExceptionAction; import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.BlockLocation; import org.apache.hadoop.fs.ContentSummary; @@ -45,6 +47,7 @@ import org.apache.hadoop.hdfs.ByteRangeI import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.DFSUtil; import org.apache.hadoop.hdfs.protocol.DSQuotaExceededException; +import org.apache.hadoop.hdfs.protocol.FSConstants; import org.apache.hadoop.hdfs.protocol.HdfsFileStatus; import org.apache.hadoop.hdfs.protocol.NSQuotaExceededException; import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier; @@ -91,6 +94,7 @@ import org.mortbay.util.ajax.JSON; /** A FileSystem for HDFS over the web. */ public class WebHdfsFileSystem extends FileSystem implements DelegationTokenRenewer.Renewable { + public static final Log LOG = LogFactory.getLog(WebHdfsFileSystem.class); /** File System URI: {SCHEME}://namenode:port/path/to/file */ public static final String SCHEME = "webhdfs"; /** Http URI: http://namenode:port/{PATH_PREFIX}/path/to/file */ @@ -413,6 +417,17 @@ public class WebHdfsFileSystem extends F run(op, p, new ModificationTimeParam(mtime), new AccessTimeParam(atime)); } + @Override + public long getDefaultBlockSize() { + return getConf().getLong("dfs.block.size", FSConstants.DEFAULT_BLOCK_SIZE); + } + + @Override + public short getDefaultReplication() { + return (short)getConf().getInt(DFSConfigKeys.DFS_REPLICATION_KEY, + DFSConfigKeys.DFS_REPLICATION_DEFAULT); + } + private FSDataOutputStream write(final HttpOpParam.Op op, final HttpURLConnection conn, final int bufferSize) throws IOException { return new FSDataOutputStream(new BufferedOutputStream( Modified: hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/resources/ExceptionHandler.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/resources/ExceptionHandler.java?rev=1186512&r1=1186511&r2=1186512&view=diff ============================================================================== --- hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/resources/ExceptionHandler.java (original) +++ hadoop/common/branches/branch-0.20-security-205/src/hdfs/org/apache/hadoop/hdfs/web/resources/ExceptionHandler.java Wed Oct 19 21:44:29 2011 @@ -20,6 +20,8 @@ package org.apache.hadoop.hdfs.web.resou import java.io.FileNotFoundException; import java.io.IOException; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; @@ -36,12 +38,17 @@ import com.sun.jersey.api.ParamException public class ExceptionHandler implements ExceptionMapper<Exception> { public static final Log LOG = LogFactory.getLog(ExceptionHandler.class); + private @Context HttpServletResponse response; + @Override public Response toResponse(Exception e) { if (LOG.isTraceEnabled()) { LOG.trace("GOT EXCEPITION", e); } + //clear content type + response.setContentType(null); + //Convert exception if (e instanceof ParamException) { final ParamException paramexception = (ParamException)e; Modified: hadoop/common/branches/branch-0.20-security-205/src/test/org/apache/hadoop/hdfs/web/TestWebHdfsFileSystemContract.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-205/src/test/org/apache/hadoop/hdfs/web/TestWebHdfsFileSystemContract.java?rev=1186512&r1=1186511&r2=1186512&view=diff ============================================================================== --- hadoop/common/branches/branch-0.20-security-205/src/test/org/apache/hadoop/hdfs/web/TestWebHdfsFileSystemContract.java (original) +++ hadoop/common/branches/branch-0.20-security-205/src/test/org/apache/hadoop/hdfs/web/TestWebHdfsFileSystemContract.java Wed Oct 19 21:44:29 2011 @@ -129,6 +129,7 @@ public class TestWebHdfsFileSystemContra //For WebHdfsFileSystem, //disable testListStatusReturnsNullForNonExistentFile //and add testListStatusThrowsExceptionForNonExistentFile below. + @Override public void testListStatusReturnsNullForNonExistentFile() {} public void testListStatusThrowsExceptionForNonExistentFile() throws Exception { @@ -140,6 +141,8 @@ public class TestWebHdfsFileSystemContra } } + //the following are new tests (i.e. not over-riding the super class methods) + public void testGetFileBlockLocations() throws IOException { final String f = "/test/testGetFileBlockLocations"; final Path p = path(f); @@ -192,4 +195,45 @@ public class TestWebHdfsFileSystemContra WebHdfsFileSystem.LOG.info("This is expected.", fnfe); } } + + public void testSeek() throws IOException { + final Path p = new Path("/test/testSeek"); + createFile(p); + + final int one_third = data.length/3; + final int two_third = one_third*2; + + { //test seek + final int offset = one_third; + final int len = data.length - offset; + final byte[] buf = new byte[len]; + + final FSDataInputStream in = fs.open(p); + in.seek(offset); + + //read all remaining data + in.readFully(buf); + in.close(); + + for (int i = 0; i < buf.length; i++) { + assertEquals("Position " + i + ", offset=" + offset + ", length=" + len, + data[i + offset], buf[i]); + } + } + + { //test position read (read the data after the two_third location) + final int offset = two_third; + final int len = data.length - offset; + final byte[] buf = new byte[len]; + + final FSDataInputStream in = fs.open(p); + in.readFully(offset, buf); + in.close(); + + for (int i = 0; i < buf.length; i++) { + assertEquals("Position " + i + ", offset=" + offset + ", length=" + len, + data[i + offset], buf[i]); + } + } + } }