Minor update to HDFS-2110.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1141416 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ad95cb1f0d
commit
8851db12a1
|
@ -70,9 +70,8 @@ import org.xml.sax.XMLReader;
|
|||
import org.xml.sax.helpers.DefaultHandler;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
|
||||
|
||||
/** An implementation of a protocol for accessing filesystems over HTTP.
|
||||
/**
|
||||
* An implementation of a protocol for accessing filesystems over HTTP.
|
||||
* The following implementation provides a limited, read-only interface
|
||||
* to a filesystem over HTTP.
|
||||
* @see org.apache.hadoop.hdfs.server.namenode.ListPathsServlet
|
||||
|
@ -314,7 +313,7 @@ public class HftpFileSystem extends FileSystem {
|
|||
try {
|
||||
connection.setRequestMethod("GET");
|
||||
connection.connect();
|
||||
} catch(IOException ioe) {
|
||||
} catch (IOException ioe) {
|
||||
throwIOExceptionFromConnection(connection, ioe);
|
||||
}
|
||||
return connection;
|
||||
|
|
|
@ -117,7 +117,7 @@ public class FileDataServlet extends DfsServlet {
|
|||
.getParameter(JspHelper.DELEGATION_PARAMETER_NAME);
|
||||
|
||||
HdfsFileStatus info = nn.getFileInfo(path);
|
||||
if ((info != null) && !info.isDir()) {
|
||||
if (info != null && !info.isDir()) {
|
||||
try {
|
||||
response.sendRedirect(createUri(path, info, ugi, nn, request,
|
||||
delegationToken).toURL().toString());
|
||||
|
|
|
@ -48,7 +48,7 @@ public class StreamFile extends DfsServlet {
|
|||
|
||||
public static final String CONTENT_LENGTH = "Content-Length";
|
||||
|
||||
/** getting a client for connecting to dfs */
|
||||
/* Return a DFS client to use to make the given HTTP request */
|
||||
protected DFSClient getDFSClient(HttpServletRequest request)
|
||||
throws IOException, InterruptedException {
|
||||
final Configuration conf =
|
||||
|
@ -59,6 +59,7 @@ public class StreamFile extends DfsServlet {
|
|||
return DatanodeJspHelper.getDFSClient(request, datanode, conf, ugi);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
final String path = request.getPathInfo() != null ?
|
||||
|
@ -71,9 +72,10 @@ public class StreamFile extends DfsServlet {
|
|||
return;
|
||||
}
|
||||
|
||||
Enumeration<?> reqRanges = request.getHeaders("Range");
|
||||
if (reqRanges != null && !reqRanges.hasMoreElements())
|
||||
Enumeration<String> reqRanges = request.getHeaders("Range");
|
||||
if (reqRanges != null && !reqRanges.hasMoreElements()) {
|
||||
reqRanges = null;
|
||||
}
|
||||
|
||||
DFSClient dfs;
|
||||
try {
|
||||
|
@ -89,29 +91,24 @@ public class StreamFile extends DfsServlet {
|
|||
|
||||
try {
|
||||
if (reqRanges != null) {
|
||||
List<?> ranges = InclusiveByteRange.satisfiableRanges(reqRanges,
|
||||
fileLen);
|
||||
StreamFile.sendPartialData(in, os, response, fileLen, ranges);
|
||||
List<InclusiveByteRange> ranges =
|
||||
InclusiveByteRange.satisfiableRanges(reqRanges, fileLen);
|
||||
StreamFile.sendPartialData(in, os, response, fileLen, ranges, true);
|
||||
} else {
|
||||
// No ranges, so send entire file
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" +
|
||||
filename + "\"");
|
||||
response.setContentType("application/octet-stream");
|
||||
response.setHeader(CONTENT_LENGTH, "" + fileLen);
|
||||
StreamFile.copyFromOffset(in, os, 0L, fileLen);
|
||||
StreamFile.copyFromOffset(in, os, 0L, fileLen, true);
|
||||
}
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("response.isCommitted()=" + response.isCommitted(), e);
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
try {
|
||||
in.close();
|
||||
os.close();
|
||||
} finally {
|
||||
dfs.close();
|
||||
}
|
||||
dfs.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,13 +122,15 @@ public class StreamFile extends DfsServlet {
|
|||
* @param response http response to use
|
||||
* @param contentLength for the response header
|
||||
* @param ranges to write to respond with
|
||||
* @param close whether to close the streams
|
||||
* @throws IOException on error sending the response
|
||||
*/
|
||||
static void sendPartialData(FSInputStream in,
|
||||
OutputStream out,
|
||||
HttpServletResponse response,
|
||||
long contentLength,
|
||||
List<?> ranges)
|
||||
List<InclusiveByteRange> ranges,
|
||||
boolean close)
|
||||
throws IOException {
|
||||
if (ranges == null || ranges.size() != 1) {
|
||||
response.setContentLength(0);
|
||||
|
@ -139,22 +138,21 @@ public class StreamFile extends DfsServlet {
|
|||
response.setHeader("Content-Range",
|
||||
InclusiveByteRange.to416HeaderRangeString(contentLength));
|
||||
} else {
|
||||
InclusiveByteRange singleSatisfiableRange =
|
||||
(InclusiveByteRange)ranges.get(0);
|
||||
InclusiveByteRange singleSatisfiableRange = ranges.get(0);
|
||||
long singleLength = singleSatisfiableRange.getSize(contentLength);
|
||||
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
||||
response.setHeader("Content-Range",
|
||||
singleSatisfiableRange.toHeaderRangeString(contentLength));
|
||||
copyFromOffset(in, out,
|
||||
singleSatisfiableRange.getFirst(contentLength),
|
||||
singleLength);
|
||||
singleLength, close);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy count bytes at the given offset from one stream to another */
|
||||
static void copyFromOffset(FSInputStream in, OutputStream out, long offset,
|
||||
long count) throws IOException {
|
||||
long count, boolean close) throws IOException {
|
||||
in.seek(offset);
|
||||
IOUtils.copyBytes(in, out, count);
|
||||
IOUtils.copyBytes(in, out, count, close);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ public class TestByteRangeInputStream {
|
|||
is.seek(101);
|
||||
is.read();
|
||||
|
||||
assertNull("Seek to 101 should not result in another request", null);
|
||||
assertNull("Seek to 101 should not result in another request", r.getMsg());
|
||||
|
||||
r.setMsg(null);
|
||||
is.seek(2500);
|
||||
|
|
|
@ -28,7 +28,8 @@ import java.util.Vector;
|
|||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.apache.hadoop.fs.FSInputStream;
|
||||
import org.mortbay.jetty.InclusiveByteRange;
|
||||
|
@ -186,8 +187,7 @@ class MockHttpServletResponse implements HttpServletResponse {
|
|||
}
|
||||
|
||||
|
||||
|
||||
public class TestStreamFile extends TestCase {
|
||||
public class TestStreamFile {
|
||||
|
||||
// return an array matching the output of mockfsinputstream
|
||||
private static byte[] getOutputArray(int start, int count) {
|
||||
|
@ -200,6 +200,7 @@ public class TestStreamFile extends TestCase {
|
|||
return a;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteTo() throws IOException, InterruptedException {
|
||||
|
||||
FSInputStream fsin = new MockFSInputStream();
|
||||
|
@ -219,7 +220,7 @@ public class TestStreamFile extends TestCase {
|
|||
assertTrue("Pairs array must be even", pairs.length % 2 == 0);
|
||||
|
||||
for (int i = 0; i < pairs.length; i+=2) {
|
||||
StreamFile.copyFromOffset(fsin, os, pairs[i], pairs[i+1]);
|
||||
StreamFile.copyFromOffset(fsin, os, pairs[i], pairs[i+1], false);
|
||||
assertArrayEquals("Reading " + pairs[i+1]
|
||||
+ " bytes from offset " + pairs[i],
|
||||
getOutputArray(pairs[i], pairs[i+1]),
|
||||
|
@ -228,22 +229,24 @@ public class TestStreamFile extends TestCase {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private List<?> strToRanges(String s, int contentLength) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<InclusiveByteRange> strToRanges(String s, int contentLength) {
|
||||
List<String> l = Arrays.asList(new String[]{"bytes="+s});
|
||||
Enumeration<?> e = (new Vector<String>(l)).elements();
|
||||
return InclusiveByteRange.satisfiableRanges(e, contentLength);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendPartialData() throws IOException, InterruptedException {
|
||||
FSInputStream in = new MockFSInputStream();
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
|
||||
// test if multiple ranges, then 416
|
||||
{
|
||||
List<?> ranges = strToRanges("0-,10-300", 500);
|
||||
List<InclusiveByteRange> ranges = strToRanges("0-,10-300", 500);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
StreamFile.sendPartialData(in, os, response, 500, ranges);
|
||||
StreamFile.sendPartialData(in, os, response, 500, ranges, false);
|
||||
assertEquals("Multiple ranges should result in a 416 error",
|
||||
416, response.getStatus());
|
||||
}
|
||||
|
@ -252,16 +255,16 @@ public class TestStreamFile extends TestCase {
|
|||
{
|
||||
os.reset();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
StreamFile.sendPartialData(in, os, response, 500, null);
|
||||
StreamFile.sendPartialData(in, os, response, 500, null, false);
|
||||
assertEquals("No ranges should result in a 416 error",
|
||||
416, response.getStatus());
|
||||
}
|
||||
|
||||
// test if invalid single range (out of bounds), then 416
|
||||
{
|
||||
List<?> ranges = strToRanges("600-800", 500);
|
||||
List<InclusiveByteRange> ranges = strToRanges("600-800", 500);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
StreamFile.sendPartialData(in, os, response, 500, ranges);
|
||||
StreamFile.sendPartialData(in, os, response, 500, ranges, false);
|
||||
assertEquals("Single (but invalid) range should result in a 416",
|
||||
416, response.getStatus());
|
||||
}
|
||||
|
@ -269,9 +272,9 @@ public class TestStreamFile extends TestCase {
|
|||
|
||||
// test if one (valid) range, then 206
|
||||
{
|
||||
List<?> ranges = strToRanges("100-300", 500);
|
||||
List<InclusiveByteRange> ranges = strToRanges("100-300", 500);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
StreamFile.sendPartialData(in, os, response, 500, ranges);
|
||||
StreamFile.sendPartialData(in, os, response, 500, ranges, false);
|
||||
assertEquals("Single (valid) range should result in a 206",
|
||||
206, response.getStatus());
|
||||
assertArrayEquals("Byte range from 100-300",
|
||||
|
|
Loading…
Reference in New Issue