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 }