browseBlock.jsp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. <%@ page
  2. contentType="text/html; charset=UTF-8"
  3. import="javax.servlet.*"
  4. import="javax.servlet.http.*"
  5. import="java.io.*"
  6. import="java.util.*"
  7. import="java.net.*"
  8. import="org.apache.hadoop.hdfs.*"
  9. import="org.apache.hadoop.hdfs.server.namenode.*"
  10. import="org.apache.hadoop.hdfs.server.datanode.*"
  11. import="org.apache.hadoop.hdfs.server.common.*"
  12. import="org.apache.hadoop.hdfs.protocol.*"
  13. import="org.apache.hadoop.io.*"
  14. import="org.apache.hadoop.conf.*"
  15. import="org.apache.hadoop.net.DNS"
  16. import="org.apache.hadoop.security.token.Token"
  17. import="org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier"
  18. import="org.apache.hadoop.hdfs.security.token.block.BlockTokenSecretManager"
  19. import="org.apache.hadoop.security.UserGroupInformation"
  20. import="org.apache.hadoop.util.*"
  21. import="org.apache.hadoop.http.HtmlQuoting"
  22. import="java.text.DateFormat"
  23. %>
  24. <%!
  25. static JspHelper jspHelper = new JspHelper();
  26. public void generateFileDetails(JspWriter out, HttpServletRequest req,
  27. Configuration conf
  28. ) throws IOException, InterruptedException {
  29. int chunkSizeToView = 0;
  30. long startOffset = 0;
  31. int datanodePort;
  32. String blockIdStr = null;
  33. long currBlockId = 0;
  34. blockIdStr = req.getParameter("blockId");
  35. if (blockIdStr == null) {
  36. out.print("Invalid input (blockId absent)");
  37. return;
  38. }
  39. currBlockId = Long.parseLong(blockIdStr);
  40. String datanodePortStr = req.getParameter("datanodePort");
  41. if (datanodePortStr == null) {
  42. out.print("Invalid input (datanodePort absent)");
  43. return;
  44. }
  45. datanodePort = Integer.parseInt(datanodePortStr);
  46. String namenodeInfoPortStr = req.getParameter("namenodeInfoPort");
  47. int namenodeInfoPort = -1;
  48. if (namenodeInfoPortStr != null)
  49. namenodeInfoPort = Integer.parseInt(namenodeInfoPortStr);
  50. String chunkSizeToViewStr = req.getParameter("chunkSizeToView");
  51. if (chunkSizeToViewStr != null &&
  52. Integer.parseInt(chunkSizeToViewStr) > 0) {
  53. chunkSizeToView = Integer.parseInt(chunkSizeToViewStr);
  54. } else {
  55. chunkSizeToView = JspHelper.getDefaultChunkSize(conf);
  56. }
  57. String startOffsetStr = req.getParameter("startOffset");
  58. if (startOffsetStr == null || Long.parseLong(startOffsetStr) < 0)
  59. startOffset = 0;
  60. else startOffset = Long.parseLong(startOffsetStr);
  61. String filename = HtmlQuoting.unquoteHtmlChars(req.getParameter("filename"));
  62. if (filename == null || filename.length() == 0) {
  63. out.print("Invalid input");
  64. return;
  65. }
  66. String blockSizeStr = req.getParameter("blockSize");
  67. long blockSize = 0;
  68. if (blockSizeStr == null || blockSizeStr.length() == 0) {
  69. out.print("Invalid input");
  70. return;
  71. }
  72. blockSize = Long.parseLong(blockSizeStr);
  73. String tokenString = req.getParameter(JspHelper.DELEGATION_PARAMETER_NAME);
  74. UserGroupInformation ugi = JspHelper.getUGI(req, conf);
  75. DFSClient dfs = JspHelper.getDFSClient(ugi, jspHelper.nameNodeAddr, conf);
  76. List<LocatedBlock> blocks =
  77. dfs.namenode.getBlockLocations(filename, 0, Long.MAX_VALUE).getLocatedBlocks();
  78. //Add the various links for looking at the file contents
  79. //URL for downloading the full file
  80. String downloadUrl = "http://" + req.getServerName() + ":" +
  81. + req.getServerPort() + "/streamFile"
  82. + URLEncoder.encode(filename, "UTF-8")
  83. + "?" + JspHelper.DELEGATION_PARAMETER_NAME
  84. + "=" + tokenString;
  85. out.print("<a name=\"viewOptions\"></a>");
  86. out.print("<a href=\"" + downloadUrl + "\">Download this file</a><br>");
  87. DatanodeInfo chosenNode;
  88. //URL for TAIL
  89. LocatedBlock lastBlk = blocks.get(blocks.size() - 1);
  90. long blockId = lastBlk.getBlock().getBlockId();
  91. try {
  92. chosenNode = jspHelper.bestNode(lastBlk);
  93. } catch (IOException e) {
  94. out.print(e.toString());
  95. dfs.close();
  96. return;
  97. }
  98. String fqdn =
  99. InetAddress.getByName(chosenNode.getHost()).getCanonicalHostName();
  100. String tailUrl = "http://" + fqdn + ":" +
  101. chosenNode.getInfoPort() +
  102. "/tail.jsp?filename=" + URLEncoder.encode(filename, "UTF-8") +
  103. "&namenodeInfoPort=" + namenodeInfoPort +
  104. "&chunkSizeToView=" + chunkSizeToView +
  105. "&referrer=" +
  106. URLEncoder.encode(req.getRequestURL() + "?" + req.getQueryString(),
  107. "UTF-8") +
  108. JspHelper.getDelegationTokenUrlParam(tokenString);
  109. out.print("<a href=\"" + tailUrl + "\">Tail this file</a><br>");
  110. out.print("<form action=\"/browseBlock.jsp\" method=GET>");
  111. out.print("<b>Chunk size to view (in bytes, up to file's DFS block size): </b>");
  112. out.print("<input type=\"hidden\" name=\"blockId\" value=\"" + currBlockId +
  113. "\">");
  114. out.print("<input type=\"hidden\" name=\"blockSize\" value=\"" +
  115. blockSize + "\">");
  116. out.print("<input type=\"hidden\" name=\"startOffset\" value=\"" +
  117. startOffset + "\">");
  118. out.print("<input type=\"hidden\" name=\"filename\" value=\"" + filename +
  119. "\">");
  120. out.print("<input type=\"hidden\" name=\"datanodePort\" value=\"" +
  121. datanodePort+ "\">");
  122. out.print("<input type=\"hidden\" name=\"namenodeInfoPort\" value=\"" +
  123. namenodeInfoPort + "\">");
  124. out.print("<input type=\"text\" name=\"chunkSizeToView\" value=" +
  125. chunkSizeToView + " size=10 maxlength=10>");
  126. out.print("&nbsp;&nbsp;<input type=\"submit\" name=\"submit\" value=\"Refresh\">");
  127. out.print("</form>");
  128. out.print("<hr>");
  129. out.print("<a name=\"blockDetails\"></a>");
  130. out.print("<B>Total number of blocks: "+blocks.size()+"</B><br>");
  131. //generate a table and dump the info
  132. out.println("\n<table>");
  133. for (LocatedBlock cur : blocks) {
  134. out.print("<tr>");
  135. blockId = cur.getBlock().getBlockId();
  136. blockSize = cur.getBlock().getNumBytes();
  137. String blk = "blk_" + Long.toString(blockId);
  138. out.print("<td>"+Long.toString(blockId)+":</td>");
  139. DatanodeInfo[] locs = cur.getLocations();
  140. for(int j=0; j<locs.length; j++) {
  141. String datanodeAddr = locs[j].getName();
  142. datanodePort = Integer.parseInt(datanodeAddr.substring(
  143. datanodeAddr.indexOf(':') + 1,
  144. datanodeAddr.length()));
  145. fqdn = InetAddress.getByName(locs[j].getHost()).getCanonicalHostName();
  146. String blockUrl = "http://"+ fqdn + ":" +
  147. locs[j].getInfoPort() +
  148. "/browseBlock.jsp?blockId=" + Long.toString(blockId) +
  149. "&blockSize=" + blockSize +
  150. "&filename=" + URLEncoder.encode(filename, "UTF-8") +
  151. "&datanodePort=" + datanodePort +
  152. "&genstamp=" + cur.getBlock().getGenerationStamp() +
  153. "&namenodeInfoPort=" + namenodeInfoPort +
  154. "&chunkSizeToView=" + chunkSizeToView;
  155. out.print("<td>&nbsp</td>"
  156. + "<td><a href=\"" + blockUrl + "\">" + datanodeAddr + "</a></td>");
  157. }
  158. out.println("</tr>");
  159. }
  160. out.println("</table>");
  161. out.print("<hr>");
  162. String namenodeHost = jspHelper.nameNodeAddr.getHostName();
  163. out.print("<br><a href=\"http://" +
  164. InetAddress.getByName(namenodeHost).getCanonicalHostName() + ":" +
  165. namenodeInfoPort + "/dfshealth.jsp\">Go back to DFS home</a>");
  166. dfs.close();
  167. }
  168. public void generateFileChunks(JspWriter out, HttpServletRequest req,
  169. Configuration conf
  170. ) throws IOException, InterruptedException {
  171. long startOffset = 0;
  172. int datanodePort = 0;
  173. int chunkSizeToView = 0;
  174. String namenodeInfoPortStr = req.getParameter("namenodeInfoPort");
  175. int namenodeInfoPort = -1;
  176. if (namenodeInfoPortStr != null)
  177. namenodeInfoPort = Integer.parseInt(namenodeInfoPortStr);
  178. String filename = HtmlQuoting.unquoteHtmlChars(req.getParameter("filename"));
  179. if (filename == null) {
  180. out.print("Invalid input (filename absent)");
  181. return;
  182. }
  183. String blockIdStr = null;
  184. long blockId = 0;
  185. blockIdStr = req.getParameter("blockId");
  186. if (blockIdStr == null) {
  187. out.print("Invalid input (blockId absent)");
  188. return;
  189. }
  190. blockId = Long.parseLong(blockIdStr);
  191. String tokenString = req.getParameter(JspHelper.DELEGATION_PARAMETER_NAME);
  192. UserGroupInformation ugi = JspHelper.getUGI(req, conf);
  193. final DFSClient dfs = JspHelper.getDFSClient(ugi, jspHelper.nameNodeAddr,
  194. conf);
  195. Token<BlockTokenIdentifier> accessToken = BlockTokenSecretManager.DUMMY_TOKEN;
  196. if (conf
  197. .getBoolean(DFSConfigKeys.DFS_BLOCK_ACCESS_TOKEN_ENABLE_KEY, false)) {
  198. List<LocatedBlock> blks = dfs.namenode.getBlockLocations(filename, 0,
  199. Long.MAX_VALUE).getLocatedBlocks();
  200. if (blks == null || blks.size() == 0) {
  201. out.print("Can't locate file blocks");
  202. dfs.close();
  203. return;
  204. }
  205. for (int i = 0; i < blks.size(); i++) {
  206. if (blks.get(i).getBlock().getBlockId() == blockId) {
  207. accessToken = blks.get(i).getBlockToken();
  208. break;
  209. }
  210. }
  211. }
  212. String blockGenStamp = null;
  213. long genStamp = 0;
  214. blockGenStamp = req.getParameter("genstamp");
  215. if (blockGenStamp == null) {
  216. out.print("Invalid input (genstamp absent)");
  217. return;
  218. }
  219. genStamp = Long.parseLong(blockGenStamp);
  220. String blockSizeStr;
  221. long blockSize = 0;
  222. blockSizeStr = req.getParameter("blockSize");
  223. if (blockSizeStr == null) {
  224. out.print("Invalid input (blockSize absent)");
  225. return;
  226. }
  227. blockSize = Long.parseLong(blockSizeStr);
  228. String chunkSizeToViewStr = req.getParameter("chunkSizeToView");
  229. if (chunkSizeToViewStr != null && Integer.parseInt(chunkSizeToViewStr) > 0)
  230. chunkSizeToView = Integer.parseInt(chunkSizeToViewStr);
  231. else chunkSizeToView = JspHelper.getDefaultChunkSize(conf);
  232. String startOffsetStr = req.getParameter("startOffset");
  233. if (startOffsetStr == null || Long.parseLong(startOffsetStr) < 0)
  234. startOffset = 0;
  235. else startOffset = Long.parseLong(startOffsetStr);
  236. String datanodePortStr = req.getParameter("datanodePort");
  237. if (datanodePortStr == null) {
  238. out.print("Invalid input (datanodePort absent)");
  239. return;
  240. }
  241. datanodePort = Integer.parseInt(datanodePortStr);
  242. out.print("<h3>File: ");
  243. JspHelper.printPathWithLinks(HtmlQuoting.quoteHtmlChars(filename),
  244. out, namenodeInfoPort, tokenString);
  245. out.print("</h3><hr>");
  246. String parent = new File(filename).getParent();
  247. JspHelper.printGotoForm(out, namenodeInfoPort, tokenString,
  248. HtmlQuoting.quoteHtmlChars(parent));
  249. out.print("<hr>");
  250. out.print("<a href=\"http://" + req.getServerName() + ":" +
  251. req.getServerPort() +
  252. "/browseDirectory.jsp?dir=" +
  253. URLEncoder.encode(parent, "UTF-8") +
  254. "&namenodeInfoPort=" + namenodeInfoPort +
  255. "\"><i>Go back to dir listing</i></a><br>");
  256. out.print("<a href=\"#viewOptions\">Advanced view/download options</a><br>");
  257. out.print("<hr>");
  258. //Determine the prev & next blocks
  259. long nextStartOffset = 0;
  260. long nextBlockSize = 0;
  261. String nextBlockIdStr = null;
  262. String nextGenStamp = null;
  263. String nextHost = req.getServerName();
  264. int nextPort = req.getServerPort();
  265. int nextDatanodePort = datanodePort;
  266. //determine data for the next link
  267. if (startOffset + chunkSizeToView >= blockSize) {
  268. //we have to go to the next block from this point onwards
  269. List<LocatedBlock> blocks =
  270. dfs.namenode.getBlockLocations(filename, 0, Long.MAX_VALUE).getLocatedBlocks();
  271. for (int i = 0; i < blocks.size(); i++) {
  272. if (blocks.get(i).getBlock().getBlockId() == blockId) {
  273. if (i != blocks.size() - 1) {
  274. LocatedBlock nextBlock = blocks.get(i+1);
  275. nextBlockIdStr = Long.toString(nextBlock.getBlock().getBlockId());
  276. nextGenStamp = Long.toString(nextBlock.getBlock().getGenerationStamp());
  277. nextStartOffset = 0;
  278. nextBlockSize = nextBlock.getBlock().getNumBytes();
  279. DatanodeInfo d = jspHelper.bestNode(nextBlock);
  280. String datanodeAddr = d.getName();
  281. nextDatanodePort = Integer.parseInt(
  282. datanodeAddr.substring(
  283. datanodeAddr.indexOf(':') + 1,
  284. datanodeAddr.length()));
  285. nextHost = InetAddress.getByName(d.getHost()).getCanonicalHostName();
  286. nextPort = d.getInfoPort();
  287. }
  288. }
  289. }
  290. }
  291. else {
  292. //we are in the same block
  293. nextBlockIdStr = blockIdStr;
  294. nextStartOffset = startOffset + chunkSizeToView;
  295. nextBlockSize = blockSize;
  296. nextGenStamp = blockGenStamp;
  297. }
  298. String nextUrl = null;
  299. if (nextBlockIdStr != null) {
  300. nextUrl = "http://" + nextHost + ":" +
  301. nextPort +
  302. "/browseBlock.jsp?blockId=" + nextBlockIdStr +
  303. "&blockSize=" + nextBlockSize + "&startOffset=" +
  304. nextStartOffset +
  305. "&genstamp=" + nextGenStamp +
  306. "&filename=" + URLEncoder.encode(filename, "UTF-8") +
  307. "&chunkSizeToView=" + chunkSizeToView +
  308. "&datanodePort=" + nextDatanodePort +
  309. "&namenodeInfoPort=" + namenodeInfoPort +
  310. JspHelper.getDelegationTokenUrlParam(tokenString);
  311. out.print("<a href=\"" + nextUrl + "\">View Next chunk</a>&nbsp;&nbsp;");
  312. }
  313. //determine data for the prev link
  314. String prevBlockIdStr = null;
  315. String prevGenStamp = null;
  316. long prevStartOffset = 0;
  317. long prevBlockSize = 0;
  318. String prevHost = req.getServerName();
  319. int prevPort = req.getServerPort();
  320. int prevDatanodePort = datanodePort;
  321. if (startOffset == 0) {
  322. List<LocatedBlock> blocks =
  323. dfs.namenode.getBlockLocations(filename, 0, Long.MAX_VALUE).getLocatedBlocks();
  324. for (int i = 0; i < blocks.size(); i++) {
  325. if (blocks.get(i).getBlock().getBlockId() == blockId) {
  326. if (i != 0) {
  327. LocatedBlock prevBlock = blocks.get(i-1);
  328. prevBlockIdStr = Long.toString(prevBlock.getBlock().getBlockId());
  329. prevGenStamp = Long.toString(prevBlock.getBlock().getGenerationStamp());
  330. prevStartOffset = prevBlock.getBlock().getNumBytes() - chunkSizeToView;
  331. if (prevStartOffset < 0)
  332. prevStartOffset = 0;
  333. prevBlockSize = prevBlock.getBlock().getNumBytes();
  334. DatanodeInfo d = jspHelper.bestNode(prevBlock);
  335. String datanodeAddr = d.getName();
  336. prevDatanodePort = Integer.parseInt(
  337. datanodeAddr.substring(
  338. datanodeAddr.indexOf(':') + 1,
  339. datanodeAddr.length()));
  340. prevHost = InetAddress.getByName(d.getHost()).getCanonicalHostName();
  341. prevPort = d.getInfoPort();
  342. }
  343. }
  344. }
  345. }
  346. else {
  347. //we are in the same block
  348. prevBlockIdStr = blockIdStr;
  349. prevStartOffset = startOffset - chunkSizeToView;
  350. if (prevStartOffset < 0) prevStartOffset = 0;
  351. prevBlockSize = blockSize;
  352. prevGenStamp = blockGenStamp;
  353. }
  354. String prevUrl = null;
  355. if (prevBlockIdStr != null) {
  356. prevUrl = "http://" + prevHost + ":" +
  357. prevPort +
  358. "/browseBlock.jsp?blockId=" + prevBlockIdStr +
  359. "&blockSize=" + prevBlockSize + "&startOffset=" +
  360. prevStartOffset +
  361. "&filename=" + URLEncoder.encode(filename, "UTF-8") +
  362. "&chunkSizeToView=" + chunkSizeToView +
  363. "&genstamp=" + prevGenStamp +
  364. "&datanodePort=" + prevDatanodePort +
  365. "&namenodeInfoPort=" + namenodeInfoPort +
  366. JspHelper.getDelegationTokenUrlParam(tokenString);
  367. out.print("<a href=\"" + prevUrl + "\">View Prev chunk</a>&nbsp;&nbsp;");
  368. }
  369. out.print("<hr>");
  370. out.print("<textarea cols=\"100\" rows=\"25\" wrap=\"virtual\" style=\"width:100%\" READONLY>");
  371. try {
  372. jspHelper.streamBlockInAscii(
  373. new InetSocketAddress(req.getServerName(), datanodePort), blockId,
  374. accessToken, genStamp, blockSize, startOffset, chunkSizeToView,
  375. out, conf);
  376. } catch (Exception e){
  377. out.print(e);
  378. }
  379. out.print("</textarea>");
  380. dfs.close();
  381. }
  382. %>
  383. <html>
  384. <head>
  385. <%JspHelper.createTitle(out, request, request.getParameter("filename")); %>
  386. </head>
  387. <body onload="document.goto.dir.focus()">
  388. <%
  389. Configuration conf =
  390. (Configuration) getServletContext().getAttribute(JspHelper.CURRENT_CONF);
  391. generateFileChunks(out, request, conf);
  392. %>
  393. <hr>
  394. <%
  395. generateFileDetails(out, request, conf);
  396. %>
  397. <h2>Local logs</h2>
  398. <a href="/logs/">Log</a> directory
  399. <%
  400. out.println(ServletUtil.htmlFooter());
  401. %>