Package org.apache.hadoop.hdfs.tools.offlineImageViewer

Source Code of org.apache.hadoop.hdfs.tools.offlineImageViewer.LsrPBImage

/**
* 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.tools.offlineImageViewer;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.permission.PermissionStatus;
import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockProto;
import org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode;
import org.apache.hadoop.hdfs.server.namenode.FSImageFormatProtobuf.SectionName;
import org.apache.hadoop.hdfs.server.namenode.FSImageUtil;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.FileSummary;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeDirectorySection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeReferenceSection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INode;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeDirectory;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeFile;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeSymlink;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.StringTableSection;
import org.apache.hadoop.hdfs.server.namenode.INodeId;
import org.apache.hadoop.io.IOUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.LimitInputStream;

/**
* LsrPBImage displays the blocks of the namespace in a format very similar
* to the output of ls/lsr.  Entries are marked as directories or not,
* permissions listed, replication, username and groupname, along with size,
* modification date and full path.
*
* Note: A significant difference between the output of the lsr command
* and this image visitor is that this class cannot sort the file entries;
* they are listed in the order they are stored within the fsimage file.
* Therefore, the output of this class cannot be directly compared to the
* output of the lsr command.
*/
final class LsrPBImage {

  private static final Log LOG = LogFactory.getLog(LsrPBImage.class);

  private final Configuration conf;
  private final PrintWriter out;
  private String[] stringTable;
  private final HashMap<Long, INodeSection.INode> inodes = Maps.newHashMap();
  private final HashMap<Long, long[]> dirmap = Maps.newHashMap();
  private final ArrayList<INodeReferenceSection.INodeReference> refList = Lists.newArrayList();

  public LsrPBImage(Configuration conf, PrintWriter out) {
    this.conf = conf;
    this.out = out;
  }

  public void visit(RandomAccessFile file) throws IOException {
    if (!FSImageUtil.checkFileFormat(file)) {
      throw new IOException("Unrecognized FSImage");
    }

    FileSummary summary = FSImageUtil.loadSummary(file);
    FileInputStream fin = null;
    try {
      fin = new FileInputStream(file.getFD());

      ArrayList<FileSummary.Section> sections = Lists.newArrayList(summary
          .getSectionsList());
      Collections.sort(sections, new Comparator<FileSummary.Section>() {
        @Override
        public int compare(FileSummary.Section s1, FileSummary.Section s2) {
          SectionName n1 = SectionName.fromString(s1.getName());
          SectionName n2 = SectionName.fromString(s2.getName());
          if (n1 == null) {
            return n2 == null ? 0 : -1;
          } else if (n2 == null) {
            return -1;
          } else {
            return n1.ordinal() - n2.ordinal();
          }
        }
      });

      for (FileSummary.Section s : sections) {
        fin.getChannel().position(s.getOffset());
        InputStream is = FSImageUtil.wrapInputStreamForCompression(conf,
            summary.getCodec(), new BufferedInputStream(new LimitInputStream(
                fin, s.getLength())));

        switch (SectionName.fromString(s.getName())) {
        case STRING_TABLE:
          loadStringTable(is);
          break;
        case INODE:
          loadINodeSection(is);
          break;
        case INODE_REFERENCE:
          loadINodeReferenceSection(is);
          break;
        case INODE_DIR:
          loadINodeDirectorySection(is);
          break;
        default:
          break;
        }
      }
      list("", INodeId.ROOT_INODE_ID);
    } finally {
      IOUtils.cleanup(null, fin);
    }
  }

  private void list(String parent, long dirId) {
    INode inode = inodes.get(dirId);
    if (LOG.isTraceEnabled()) {
      LOG.trace("Listing directory id " + dirId + " parent '" + parent
          + "' (INode is " + inode + ")");
    }
    listINode(parent.isEmpty() ? "/" : parent, inode);
    long[] children = dirmap.get(dirId);
    if (children == null) {
      return;
    }
    String newParent = parent + inode.getName().toStringUtf8() + "/";
    for (long cid : children) {
      list(newParent, cid);
    }
  }

  private void listINode(String parent, INode inode) {
    switch (inode.getType()) {
    case FILE: {
      INodeFile f = inode.getFile();
      PermissionStatus p = FSImageFormatPBINode.Loader.loadPermission(
          f.getPermission(), stringTable);
      out.print(String.format("-%s %2s %8s %10s %10s %10d %s%s\n", p
          .getPermission().toString(), f.getReplication(), p.getUserName(), p
          .getGroupName(), f.getModificationTime(), getFileSize(f), parent,
          inode.getName().toStringUtf8()));
    }
      break;
    case DIRECTORY: {
      INodeDirectory d = inode.getDirectory();
      PermissionStatus p = FSImageFormatPBINode.Loader.loadPermission(
          d.getPermission(), stringTable);
      out.print(String.format("d%s  - %8s %10s %10s %10d %s%s\n", p
          .getPermission().toString(), p.getUserName(), p.getGroupName(), d
          .getModificationTime(), 0, parent, inode.getName().toStringUtf8()));
    }
      break;
    case SYMLINK: {
      INodeSymlink d = inode.getSymlink();
      PermissionStatus p = FSImageFormatPBINode.Loader.loadPermission(
          d.getPermission(), stringTable);
      out.print(String.format("-%s  - %8s %10s %10s %10d %s%s -> %s\n", p
          .getPermission().toString(), p.getUserName(), p.getGroupName(), d
          .getModificationTime(), 0, parent, inode.getName().toStringUtf8(),
          d.getTarget().toStringUtf8()));
    }
      break;
    default:
      break;
    }
  }

  private long getFileSize(INodeFile f) {
    long size = 0;
    for (BlockProto p : f.getBlocksList()) {
      size += p.getNumBytes();
    }
    return size;
  }

  private void loadINodeDirectorySection(InputStream in) throws IOException {
    if (LOG.isDebugEnabled()) {
      LOG.debug("Loading directory section");
    }
    while (true) {
      INodeDirectorySection.DirEntry e = INodeDirectorySection.DirEntry
          .parseDelimitedFrom(in);
      // note that in is a LimitedInputStream
      if (e == null) {
        break;
      }
      long[] l = new long[e.getChildrenCount() + e.getRefChildrenCount()];
      for (int i = 0; i < e.getChildrenCount(); ++i) {
        l[i] = e.getChildren(i);
      }
      for (int i = e.getChildrenCount(); i < l.length; i++) {
        int refId = e.getRefChildren(i - e.getChildrenCount());
        l[i] = refList.get(refId).getReferredId();
      }
      dirmap.put(e.getParent(), l);
      if (LOG.isDebugEnabled()) {
        LOG.debug("Loaded directory (parent " + e.getParent()
            + ") with " + e.getChildrenCount() + " children and "
            + e.getRefChildrenCount() + " reference children");
      }
    }
    if (LOG.isDebugEnabled()) {
      LOG.debug("Loaded " + dirmap.size() + " directories");
    }
  }

  private void loadINodeReferenceSection(InputStream in) throws IOException {
    if (LOG.isDebugEnabled()) {
      LOG.debug("Loading inode reference section");
    }
    while (true) {
      INodeReferenceSection.INodeReference e = INodeReferenceSection
          .INodeReference.parseDelimitedFrom(in);
      if (e == null) {
        break;
      }
      refList.add(e);
      if (LOG.isTraceEnabled()) {
        LOG.trace("Loaded inode reference named '" + e.getName()
            + "' referring to id " + e.getReferredId() + "");
      }
    }
    if (LOG.isDebugEnabled()) {
      LOG.debug("Loaded " + refList.size() + " inode references");
    }
  }

  private void loadINodeSection(InputStream in) throws IOException {
    INodeSection s = INodeSection.parseDelimitedFrom(in);
    if (LOG.isDebugEnabled()) {
      LOG.debug("Found " + s.getNumInodes() + " inodes in inode section");
    }
    for (int i = 0; i < s.getNumInodes(); ++i) {
      INodeSection.INode p = INodeSection.INode.parseDelimitedFrom(in);
      inodes.put(p.getId(), p);
      if (LOG.isTraceEnabled()) {
        LOG.trace("Loaded inode id " + p.getId() + " type " + p.getType()
            + " name '" + p.getName().toStringUtf8() + "'");
      }
    }
  }

  private void loadStringTable(InputStream in) throws IOException {
    StringTableSection s = StringTableSection.parseDelimitedFrom(in);
    if (LOG.isDebugEnabled()) {
      LOG.debug("Found " + s.getNumEntry() + " strings in string section");
    }
    stringTable = new String[s.getNumEntry() + 1];
    for (int i = 0; i < s.getNumEntry(); ++i) {
      StringTableSection.Entry e = StringTableSection.Entry
          .parseDelimitedFrom(in);
      stringTable[e.getId()] = e.getStr();
      if (LOG.isTraceEnabled()) {
        LOG.trace("Loaded string " + e.getStr());
      }
    }
  }
}
TOP

Related Classes of org.apache.hadoop.hdfs.tools.offlineImageViewer.LsrPBImage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.