All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.hdfs.server.common.JspHelper Maven / Gradle / Ivy

The newest version!
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.hadoop.hdfs.server.common;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Random;
import java.util.TreeSet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspWriter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.BlockReader;
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;
import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
import org.apache.hadoop.hdfs.server.namenode.DatanodeDescriptor;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
import org.apache.hadoop.http.HtmlQuoting;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.util.VersionInfo;

@InterfaceAudience.Private
public class JspHelper {
  public static final String CURRENT_CONF = "current.conf";
  final static public String WEB_UGI_PROPERTY_NAME = "dfs.web.ugi";
  public static final String DELEGATION_PARAMETER_NAME = "delegation";
  static final String SET_DELEGATION = "&" + DELEGATION_PARAMETER_NAME +
                                              "=";
  private static final Log LOG = LogFactory.getLog(JspHelper.class);

  static final Random rand = new Random();

  /** Private constructor for preventing creating JspHelper object. */
  private JspHelper() {} 
  
  // data structure to count number of blocks on datanodes.
  private static class NodeRecord extends DatanodeInfo {
    int frequency;

    public NodeRecord() {
      frequency = -1;
    }
    public NodeRecord(DatanodeInfo info, int count) {
      super(info);
      this.frequency = count;
    }
    
    @Override
    public boolean equals(Object obj) {
      // Sufficient to use super equality as datanodes are uniquely identified
      // by DatanodeID
      return (this == obj) || super.equals(obj);
    }
    @Override
    public int hashCode() {
      // Super implementation is sufficient
      return super.hashCode();
    }
  }
 
  // compare two records based on their frequency
  private static class NodeRecordComparator implements Comparator {

    public int compare(NodeRecord o1, NodeRecord o2) {
      if (o1.frequency < o2.frequency) {
        return -1;
      } else if (o1.frequency > o2.frequency) {
        return 1;
      } 
      return 0;
    }
  }
  public static DatanodeInfo bestNode(LocatedBlocks blks) throws IOException {
    HashMap map =
      new HashMap();
    for (LocatedBlock block : blks.getLocatedBlocks()) {
      DatanodeInfo[] nodes = block.getLocations();
      for (DatanodeInfo node : nodes) {
        NodeRecord record = map.get(node);
        if (record == null) {
          map.put(node, new NodeRecord(node, 1));
        } else {
          record.frequency++;
        }
      }
    }
    NodeRecord[] nodes = map.values().toArray(new NodeRecord[map.size()]);
    Arrays.sort(nodes, new NodeRecordComparator());
    return bestNode(nodes, false);
  }

  public static DatanodeInfo bestNode(LocatedBlock blk) throws IOException {
    DatanodeInfo[] nodes = blk.getLocations();
    return bestNode(nodes, true);
  }

  public static DatanodeInfo bestNode(DatanodeInfo[] nodes, boolean doRandom)
    throws IOException {
    TreeSet deadNodes = new TreeSet();
    DatanodeInfo chosenNode = null;
    int failures = 0;
    Socket s = null;
    int index = -1;
    if (nodes == null || nodes.length == 0) {
      throw new IOException("No nodes contain this block");
    }
    while (s == null) {
      if (chosenNode == null) {
        do {
          if (doRandom) {
            index = rand.nextInt(nodes.length);
          } else {
            index++;
          }
          chosenNode = nodes[index];
        } while (deadNodes.contains(chosenNode));
      }
      chosenNode = nodes[index];

      //just ping to check whether the node is alive
      InetSocketAddress targetAddr = NetUtils.createSocketAddr(
          chosenNode.getHost() + ":" + chosenNode.getInfoPort());
        
      try {
        s = new Socket();
        s.connect(targetAddr, HdfsConstants.READ_TIMEOUT);
        s.setSoTimeout(HdfsConstants.READ_TIMEOUT);
      } catch (IOException e) {
        deadNodes.add(chosenNode);
        s.close();
        s = null;
        failures++;
      }
      if (failures == nodes.length)
        throw new IOException("Could not reach the block containing the data. Please try again");
        
    }
    s.close();
    return chosenNode;
  }

  public static void streamBlockInAscii(InetSocketAddress addr, 
      long blockId, Token blockToken, long genStamp,
      long blockSize, long offsetIntoBlock, long chunkSizeToView,
      JspWriter out, Configuration conf) throws IOException {
    if (chunkSizeToView == 0) return;
    Socket s = new Socket();
    s.connect(addr, HdfsConstants.READ_TIMEOUT);
    s.setSoTimeout(HdfsConstants.READ_TIMEOUT);
      
      long amtToRead = Math.min(chunkSizeToView, blockSize - offsetIntoBlock);     
      
      // Use the block name for file name. 
      String file = BlockReader.getFileName(addr, blockId);
      BlockReader blockReader = BlockReader.newBlockReader(s, file,
        new Block(blockId, 0, genStamp), blockToken,
        offsetIntoBlock, amtToRead, conf.getInt("io.file.buffer.size", 4096));
        
    byte[] buf = new byte[(int)amtToRead];
    int readOffset = 0;
    int retries = 2;
    while ( amtToRead > 0 ) {
      int numRead;
      try {
        numRead = blockReader.readAll(buf, readOffset, (int)amtToRead);
      }
      catch (IOException e) {
        retries--;
        if (retries == 0)
          throw new IOException("Could not read data from datanode");
        continue;
      }
      amtToRead -= numRead;
      readOffset += numRead;
    }
    blockReader = null;
    s.close();
    out.print(HtmlQuoting.quoteHtmlChars(new String(buf)));
  }

  public static void addTableHeader(JspWriter out) throws IOException {
    out.print("");
    out.print("");
  }
  public static void addTableRow(JspWriter out, String[] columns) throws IOException {
    out.print("");
    for (int i = 0; i < columns.length; i++) {
      out.print("");
    }
    out.print("");
  }
  public static void addTableRow(JspWriter out, String[] columns, int row) throws IOException {
    out.print("");
      
    for (int i = 0; i < columns.length; i++) {
      if (row/2*2 == row) {//even
        out.print("");
      } else {
        out.print("");
          
      }
    }
    out.print("");
  }
  public static void addTableFooter(JspWriter out) throws IOException {
    out.print("
"+columns[i]+"
"+columns[i]+"
"+columns[i]+"
"); } public static void sortNodeList(ArrayList nodes, String field, String order) { class NodeComapare implements Comparator { static final int FIELD_NAME = 1, FIELD_LAST_CONTACT = 2, FIELD_BLOCKS = 3, FIELD_CAPACITY = 4, FIELD_USED = 5, FIELD_PERCENT_USED = 6, FIELD_NONDFS_USED = 7, FIELD_REMAINING = 8, FIELD_PERCENT_REMAINING = 9, SORT_ORDER_ASC = 1, SORT_ORDER_DSC = 2; int sortField = FIELD_NAME; int sortOrder = SORT_ORDER_ASC; public NodeComapare(String field, String order) { if (field.equals("lastcontact")) { sortField = FIELD_LAST_CONTACT; } else if (field.equals("capacity")) { sortField = FIELD_CAPACITY; } else if (field.equals("used")) { sortField = FIELD_USED; } else if (field.equals("nondfsused")) { sortField = FIELD_NONDFS_USED; } else if (field.equals("remaining")) { sortField = FIELD_REMAINING; } else if (field.equals("pcused")) { sortField = FIELD_PERCENT_USED; } else if (field.equals("pcremaining")) { sortField = FIELD_PERCENT_REMAINING; } else if (field.equals("blocks")) { sortField = FIELD_BLOCKS; } else { sortField = FIELD_NAME; } if (order.equals("DSC")) { sortOrder = SORT_ORDER_DSC; } else { sortOrder = SORT_ORDER_ASC; } } public int compare(DatanodeDescriptor d1, DatanodeDescriptor d2) { int ret = 0; switch (sortField) { case FIELD_LAST_CONTACT: ret = (int) (d2.getLastUpdate() - d1.getLastUpdate()); break; case FIELD_CAPACITY: long dlong = d1.getCapacity() - d2.getCapacity(); ret = (dlong < 0) ? -1 : ((dlong > 0) ? 1 : 0); break; case FIELD_USED: dlong = d1.getDfsUsed() - d2.getDfsUsed(); ret = (dlong < 0) ? -1 : ((dlong > 0) ? 1 : 0); break; case FIELD_NONDFS_USED: dlong = d1.getNonDfsUsed() - d2.getNonDfsUsed(); ret = (dlong < 0) ? -1 : ((dlong > 0) ? 1 : 0); break; case FIELD_REMAINING: dlong = d1.getRemaining() - d2.getRemaining(); ret = (dlong < 0) ? -1 : ((dlong > 0) ? 1 : 0); break; case FIELD_PERCENT_USED: double ddbl =((d1.getDfsUsedPercent())- (d2.getDfsUsedPercent())); ret = (ddbl < 0) ? -1 : ((ddbl > 0) ? 1 : 0); break; case FIELD_PERCENT_REMAINING: ddbl =((d1.getRemainingPercent())- (d2.getRemainingPercent())); ret = (ddbl < 0) ? -1 : ((ddbl > 0) ? 1 : 0); break; case FIELD_BLOCKS: ret = d1.numBlocks() - d2.numBlocks(); break; case FIELD_NAME: ret = d1.getHostName().compareTo(d2.getHostName()); break; } return (sortOrder == SORT_ORDER_DSC) ? -ret : ret; } } Collections.sort(nodes, new NodeComapare(field, order)); } public static void printPathWithLinks(String dir, JspWriter out, int namenodeInfoPort, String tokenString ) throws IOException { try { String[] parts = dir.split(Path.SEPARATOR); StringBuilder tempPath = new StringBuilder(dir.length()); out.print("" + Path.SEPARATOR + ""); tempPath.append(Path.SEPARATOR); for (int i = 0; i < parts.length-1; i++) { if (!parts[i].equals("")) { tempPath.append(parts[i]); out.print("" + parts[i] + "" + Path.SEPARATOR); tempPath.append(Path.SEPARATOR); } } if(parts.length > 0) { out.print(parts[parts.length-1]); } } catch (UnsupportedEncodingException ex) { ex.printStackTrace(); } } public static void printGotoForm(JspWriter out, int namenodeInfoPort, String tokenString, String file) throws IOException { out.print("
"); out.print("Goto : "); out.print(""); out.print(""); out.print(""); if (UserGroupInformation.isSecurityEnabled()) { out.print(""); } out.print("
"); } public static void createTitle(JspWriter out, HttpServletRequest req, String file) throws IOException{ if(file == null) file = ""; int start = Math.max(0,file.length() - 100); if(start != 0) file = "..." + file.substring(start, file.length()); out.print("HDFS:" + file + ""); } /** Convert a String to chunk-size-to-view. */ public static int string2ChunkSizeToView(String s, int defaultValue) { int n = s == null? 0: Integer.parseInt(s); return n > 0? n: defaultValue; } /** Return a table containing version information. */ public static String getVersionTable() { return "
" + "\n
Version:" + VersionInfo.getVersion() + ", " + VersionInfo.getRevision() + "\n
Compiled:" + VersionInfo.getDate() + " by " + VersionInfo.getUser() + " from " + VersionInfo.getBranch() + "\n
"; } /** * Validate filename. * @return null if the filename is invalid. * Otherwise, return the validated filename. */ public static String validatePath(String p) { return p == null || p.length() == 0? null: new Path(p).toUri().getPath(); } /** * Validate a long value. * @return null if the value is invalid. * Otherwise, return the validated Long object. */ public static Long validateLong(String value) { return value == null? null: Long.parseLong(value); } /** * Validate a URL. * @return null if the value is invalid. * Otherwise, return the validated URL String. */ public static String validateURL(String value) { try { return URLEncoder.encode(new URL(value).toString(), "UTF-8"); } catch (IOException e) { return null; } } /** * If security is turned off, what is the default web user? * @param conf the configuration to look in * @return the remote user that was configuration */ public static UserGroupInformation getDefaultWebUser(Configuration conf ) throws IOException { String[] strings = conf.getStrings(JspHelper.WEB_UGI_PROPERTY_NAME); if (strings == null || strings.length == 0) { throw new IOException("Cannot determine UGI from request or conf"); } return UserGroupInformation.createRemoteUser(strings[0]); } /** * Get {@link UserGroupInformation} and possibly the delegation token out of * the request. * @param request the http request * @return a new user from the request * @throws AccessControlException if the request has no token */ public static UserGroupInformation getUGI(HttpServletRequest request, Configuration conf ) throws IOException { UserGroupInformation ugi = null; if(UserGroupInformation.isSecurityEnabled()) { String user = request.getRemoteUser(); String tokenString = request.getParameter(DELEGATION_PARAMETER_NAME); if (tokenString != null) { Token token = new Token(); token.decodeFromUrlString(tokenString); InetSocketAddress serviceAddr = NameNode.getAddress(conf); LOG.info("Setting service in token: " + new Text(serviceAddr.getAddress().getHostAddress() + ":" + serviceAddr.getPort())); token.setService(new Text(serviceAddr.getAddress().getHostAddress() + ":" + serviceAddr.getPort())); ByteArrayInputStream buf = new ByteArrayInputStream(token .getIdentifier()); DataInputStream in = new DataInputStream(buf); DelegationTokenIdentifier id = new DelegationTokenIdentifier(); id.readFields(in); ugi = id.getUser(); ugi.addToken(token); ugi.setAuthenticationMethod(AuthenticationMethod.TOKEN); } else { if(user == null) { throw new IOException("Security enabled but user not " + "authenticated by filter"); } ugi = UserGroupInformation.createRemoteUser(user); // This is not necessarily true, could have been auth'ed by user-facing // filter ugi.setAuthenticationMethod(AuthenticationMethod.KERBEROS_SSL); } } else { // Security's not on, pull from url String user = request.getParameter("ugi"); if(user == null) { // not specified in request ugi = getDefaultWebUser(conf); } else { ugi = UserGroupInformation.createRemoteUser(user.split(",")[0]); } ugi.setAuthenticationMethod(AuthenticationMethod.SIMPLE); } if(LOG.isDebugEnabled()) LOG.debug("getUGI is returning: " + ugi.getShortUserName()); return ugi; } /** * Returns the url parameter for the given token string. * @param tokenString * @return url parameter */ public static String getDelegationTokenUrlParam(String tokenString) { if (tokenString == null ) { return ""; } if (UserGroupInformation.isSecurityEnabled()) { return SET_DELEGATION + tokenString; } else { return ""; } } /** * Returns the url parameter for the given string, prefixed with * paramSeparator. * * @param name parameter name * @param val parameter value * @param paramSeparator URL parameter prefix, i.e. either '?' or '&' * @return url parameter */ public static String getUrlParam(String name, String val, String paramSeparator) { return val == null ? "" : paramSeparator + name + "=" + val; } /** * Returns the url parameter for the given string, prefixed with '?' if * firstParam is true, prefixed with '&' if firstParam is false. * * @param name parameter name * @param val parameter value * @param firstParam true if this is the first parameter in the list, false otherwise * @return url parameter */ public static String getUrlParam(String name, String val, boolean firstParam) { return getUrlParam(name, val, firstParam ? "?" : "&"); } /** * Returns the url parameter for the given string, prefixed with '&'. * * @param name parameter name * @param val parameter value * @return url parameter */ public static String getUrlParam(String name, String val) { return getUrlParam(name, val, false); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy