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