PageRenderTime 40ms CodeModel.GetById 29ms app.highlight 9ms RepoModel.GetById 0ms app.codeStats 0ms

/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java

https://github.com/lalithsuresh/Scaling-HDFS-NameNode
Java | 221 lines | 149 code | 21 blank | 51 comment | 17 complexity | ac5ea1d9cfc7d80e723001e16ec27b12 MD5 | raw file
  1/**
  2* Licensed to the Apache Software Foundation (ASF) under one
  3* or more contributor license agreements.  See the NOTICE file
  4* distributed with this work for additional information
  5* regarding copyright ownership.  The ASF licenses this file
  6* to you under the Apache License, Version 2.0 (the
  7* "License"); you may not use this file except in compliance
  8* with the License.  You may obtain a copy of the License at
  9*
 10*     http://www.apache.org/licenses/LICENSE-2.0
 11*
 12* Unless required by applicable law or agreed to in writing, software
 13* distributed under the License is distributed on an "AS IS" BASIS,
 14* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15* See the License for the specific language governing permissions and
 16* limitations under the License.
 17*/
 18
 19package org.apache.hadoop.yarn.webapp;
 20
 21import static com.google.common.base.Preconditions.*;
 22import com.google.inject.AbstractModule;
 23import com.google.inject.Guice;
 24import com.google.inject.Injector;
 25import com.google.inject.Module;
 26import com.google.inject.servlet.GuiceFilter;
 27
 28import java.net.ConnectException;
 29import java.net.URL;
 30import org.apache.commons.lang.StringUtils;
 31
 32import org.apache.hadoop.conf.Configuration;
 33import org.apache.hadoop.http.HttpServer;
 34
 35import org.slf4j.Logger;
 36import org.slf4j.LoggerFactory;
 37
 38/**
 39 * Helpers to create an embedded webapp.
 40 *
 41 * <h4>Quick start:</h4>
 42 * <pre>
 43 *   WebApp wa = WebApps.$for(myApp).start();</pre>
 44 * Starts a webapp with default routes binds to 0.0.0.0 (all network interfaces)
 45 * on an ephemeral port, which can be obtained with:<pre>
 46 *   int port = wa.port();</pre>
 47 * <h4>With more options:</h4>
 48 * <pre>
 49 *   WebApp wa = WebApps.$for(myApp).at(address, port).
 50 *                        with(configuration).
 51 *                        start(new WebApp() {
 52 *     &#064;Override public void setup() {
 53 *       route("/foo/action", FooController.class);
 54 *       route("/foo/:id", FooController.class, "show");
 55 *     }
 56 *   });</pre>
 57 */
 58public class WebApps {
 59  static final Logger LOG = LoggerFactory.getLogger(WebApps.class);
 60
 61  public static class Builder<T> {
 62    final String name;
 63    final Class<T> api;
 64    final T application;
 65    String bindAddress = "0.0.0.0";
 66    int port = 0;
 67    boolean findPort = false;
 68    Configuration conf;
 69    boolean devMode = false;
 70    Module[] modules;
 71
 72    Builder(String name, Class<T> api, T application) {
 73      this.name = name;
 74      this.api = api;
 75      this.application = application;
 76    }
 77
 78    public Builder<T> at(String bindAddress) {
 79      String[] parts = StringUtils.split(bindAddress, ':');
 80      if (parts.length == 2) {
 81        return at(parts[0], Integer.parseInt(parts[1]), true);
 82      }
 83      return at(bindAddress, 0, true);
 84    }
 85
 86    public Builder<T> at(int port) {
 87      return at("0.0.0.0", port, false);
 88    }
 89
 90    public Builder<T> at(String address, int port, boolean findPort) {
 91      this.bindAddress = checkNotNull(address, "bind address");
 92      this.port = port;
 93      this.findPort = findPort;
 94      return this;
 95    }
 96
 97    public Builder<T> with(Configuration conf) {
 98      this.conf = conf;
 99      return this;
100    }
101
102    public Builder<T> with(Module... modules) {
103      this.modules = modules; // OK
104      return this;
105    }
106
107    public Builder<T> inDevMode() {
108      devMode = true;
109      return this;
110    }
111
112    public WebApp start(WebApp webapp) {
113      if (webapp == null) {
114        webapp = new WebApp() {
115          @Override
116          public void setup() {
117            // Defaults should be fine in usual cases
118          }
119        };
120      }
121      webapp.setName(name);
122      if (conf == null) {
123        conf = new Configuration();
124      }
125      try {
126        if (application != null) {
127          webapp.setHostClass(application.getClass());
128        } else {
129          String cls = inferHostClass();
130          LOG.debug("setting webapp host class to {}", cls);
131          webapp.setHostClass(Class.forName(cls));
132        }
133        if (devMode) {
134          if (port > 0) {
135            try {
136              new URL("http://localhost:"+ port +"/__stop").getContent();
137              LOG.info("stopping existing webapp instance");
138              Thread.sleep(100);
139            } catch (ConnectException e) {
140              LOG.info("no existing webapp instance found: {}", e.toString());
141            } catch (Exception e) {
142              // should not be fatal
143              LOG.warn("error stopping existing instance: {}", e.toString());
144            }
145          } else {
146            LOG.error("dev mode does NOT work with ephemeral port!");
147            System.exit(1);
148          }
149        }
150        HttpServer server =
151            new HttpServer(name, bindAddress, port, findPort, conf);
152        server.addGlobalFilter("guice", GuiceFilter.class.getName(), null);
153        webapp.setConf(conf);
154        webapp.setHttpServer(server);
155        server.start();
156        LOG.info("Web app /"+ name +" started at "+ server.getPort());
157      } catch (Exception e) {
158        throw new WebAppException("Error starting http server", e);
159      }
160      Injector injector = Guice.createInjector(webapp, new AbstractModule() {
161        @Override
162        protected void configure() {
163          if (api != null) {
164            bind(api).toInstance(application);
165          }
166        }
167      });
168      LOG.info("Registered webapp guice modules");
169      // save a guice filter instance for webapp stop (mostly for unit tests)
170      webapp.setGuiceFilter(injector.getInstance(GuiceFilter.class));
171      if (devMode) {
172        injector.getInstance(Dispatcher.class).setDevMode(devMode);
173        LOG.info("in dev mode!");
174      }
175      return webapp;
176    }
177
178    public WebApp start() {
179      return start(null);
180    }
181
182    private String inferHostClass() {
183      String thisClass = this.getClass().getName();
184      Throwable t = new Throwable();
185      for (StackTraceElement e : t.getStackTrace()) {
186        if (e.getClassName().equals(thisClass)) continue;
187        return e.getClassName();
188      }
189      LOG.warn("could not infer host class from", t);
190      return thisClass;
191    }
192  }
193
194  /**
195   * Create a new webapp builder.
196   * @see WebApps for a complete example
197   * @param <T> application (holding the embedded webapp) type
198   * @param prefix of the webapp
199   * @param api the api class for the application
200   * @param app the application instance
201   * @return a webapp builder
202   */
203  public static <T> Builder<T> $for(String prefix, Class<T> api, T app) {
204    return new Builder<T>(prefix, api, app);
205  }
206
207  // Short cut mostly for tests/demos
208  @SuppressWarnings("unchecked")
209  public static <T> Builder<T> $for(String prefix, T app) {
210    return $for(prefix, (Class<T>)app.getClass(), app);
211  }
212
213  // Ditto
214  public static <T> Builder<T> $for(T app) {
215    return $for("", app);
216  }
217
218  public static <T> Builder<T> $for(String prefix) {
219    return $for(prefix, null, null);
220  }
221}