001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.hadoop.hdfs.tools.offlineImageViewer; 019 020 import java.io.IOException; 021 import java.net.InetSocketAddress; 022 import java.util.concurrent.Executors; 023 024 import org.apache.commons.logging.Log; 025 import org.apache.commons.logging.LogFactory; 026 import org.jboss.netty.bootstrap.ServerBootstrap; 027 import org.jboss.netty.channel.Channel; 028 import org.jboss.netty.channel.ChannelFactory; 029 import org.jboss.netty.channel.ChannelHandlerContext; 030 import org.jboss.netty.channel.ChannelPipeline; 031 import org.jboss.netty.channel.ChannelStateEvent; 032 import org.jboss.netty.channel.Channels; 033 import org.jboss.netty.channel.SimpleChannelUpstreamHandler; 034 import org.jboss.netty.channel.group.ChannelGroup; 035 import org.jboss.netty.channel.group.DefaultChannelGroup; 036 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; 037 import org.jboss.netty.handler.codec.http.HttpRequestDecoder; 038 import org.jboss.netty.handler.codec.http.HttpResponseEncoder; 039 import org.jboss.netty.handler.codec.string.StringEncoder; 040 041 import com.google.common.annotations.VisibleForTesting; 042 043 /** 044 * WebImageViewer loads a fsimage and exposes read-only WebHDFS API for its 045 * namespace. 046 */ 047 public class WebImageViewer { 048 public static final Log LOG = LogFactory.getLog(WebImageViewer.class); 049 050 private Channel channel; 051 private InetSocketAddress address; 052 private final ChannelFactory factory = 053 new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), 054 Executors.newCachedThreadPool(), 1); 055 private final ServerBootstrap bootstrap = new ServerBootstrap(factory); 056 057 static final ChannelGroup allChannels = 058 new DefaultChannelGroup("WebImageViewer"); 059 060 public WebImageViewer(InetSocketAddress address) { 061 this.address = address; 062 } 063 064 /** 065 * Start WebImageViewer and wait until the thread is interrupted. 066 * @param fsimage the fsimage to load. 067 * @throws IOException if failed to load the fsimage. 068 */ 069 public void initServerAndWait(String fsimage) throws IOException { 070 initServer(fsimage); 071 try { 072 channel.getCloseFuture().await(); 073 } catch (InterruptedException e) { 074 LOG.info("Interrupted. Stopping the WebImageViewer."); 075 shutdown(); 076 } 077 } 078 079 /** 080 * Start WebImageViewer. 081 * @param fsimage the fsimage to load. 082 * @throws IOException if fail to load the fsimage. 083 */ 084 @VisibleForTesting 085 public void initServer(String fsimage) throws IOException { 086 FSImageLoader loader = FSImageLoader.load(fsimage); 087 088 ChannelPipeline pipeline = Channels.pipeline(); 089 pipeline.addLast("channelTracker", new SimpleChannelUpstreamHandler() { 090 @Override 091 public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) 092 throws Exception { 093 allChannels.add(e.getChannel()); 094 } 095 }); 096 pipeline.addLast("httpDecoder", new HttpRequestDecoder()); 097 pipeline.addLast("requestHandler", new FSImageHandler(loader)); 098 pipeline.addLast("stringEncoder", new StringEncoder()); 099 pipeline.addLast("httpEncoder", new HttpResponseEncoder()); 100 bootstrap.setPipeline(pipeline); 101 channel = bootstrap.bind(address); 102 allChannels.add(channel); 103 104 address = (InetSocketAddress) channel.getLocalAddress(); 105 LOG.info("WebImageViewer started. Listening on " + address.toString() 106 + ". Press Ctrl+C to stop the viewer."); 107 } 108 109 /** 110 * Stop WebImageViewer. 111 */ 112 @VisibleForTesting 113 public void shutdown() { 114 allChannels.close().awaitUninterruptibly(); 115 factory.releaseExternalResources(); 116 } 117 118 /** 119 * Get the listening port. 120 * @return the port WebImageViewer is listening on 121 */ 122 @VisibleForTesting 123 public int getPort() { 124 return address.getPort(); 125 } 126 }