You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ry...@apache.org on 2012/02/22 19:06:40 UTC

svn commit: r1292429 - in /lucene/dev/trunk/solr: core/src/java/org/apache/solr/servlet/ZookeeperInfoServlet.java webapp/web/WEB-INF/web.xml webapp/web/index.jsp webapp/web/zookeeper.jsp

Author: ryan
Date: Wed Feb 22 18:06:40 2012
New Revision: 1292429

URL: http://svn.apache.org/viewvc?rev=1292429&view=rev
Log:
SOLR-3151: moving zookeeper.jsp to a servlet, this is a direct copy nothing new yet

Added:
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/ZookeeperInfoServlet.java
Removed:
    lucene/dev/trunk/solr/webapp/web/zookeeper.jsp
Modified:
    lucene/dev/trunk/solr/webapp/web/WEB-INF/web.xml
    lucene/dev/trunk/solr/webapp/web/index.jsp

Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/ZookeeperInfoServlet.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/ZookeeperInfoServlet.java?rev=1292429&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/ZookeeperInfoServlet.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/ZookeeperInfoServlet.java Wed Feb 22 18:06:40 2012
@@ -0,0 +1,538 @@
+/**
+ * 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.solr.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.solr.cloud.ZkController;
+import org.apache.solr.common.cloud.SolrZkClient;
+import org.apache.solr.common.util.StrUtils;
+import org.apache.solr.common.util.XML;
+import org.apache.solr.core.CoreContainer;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.data.Stat;
+
+
+/**
+ * Zookeeper Info
+ *
+ * @since solr 4.0
+ */
+public final class ZookeeperInfoServlet extends HttpServlet {
+
+  @Override
+  public void init() throws ServletException {
+  }
+
+  @Override
+  public void doGet(HttpServletRequest request,
+                    HttpServletResponse response)
+          throws IOException, ServletException {
+    response.setCharacterEncoding("UTF-8");
+    response.setContentType("application/json");
+
+    CoreContainer cores = (CoreContainer) request.getAttribute("org.apache.solr.CoreContainer");
+    
+    String path = request.getParameter("path");
+    String addr = request.getParameter("addr");
+    
+    if (addr != null && addr.length() == 0)
+    {
+      addr = null;
+    }
+    
+    String detailS = request.getParameter("detail");
+    boolean detail = detailS != null && detailS.equals("true");
+    PrintWriter out = response.getWriter();
+    
+    ZKPrinter printer = new ZKPrinter(response, out, cores.getZkController(), addr);
+    printer.detail = detail;
+    
+    try {
+      printer.print(path);
+    } finally {
+      printer.close();
+    }
+  }
+
+  @Override
+  public void doPost(HttpServletRequest request,
+                     HttpServletResponse response)
+          throws IOException, ServletException {
+    doGet(request,response);
+  }
+
+
+  //--------------------------------------------------------------------------------------
+  // 
+  //--------------------------------------------------------------------------------------
+  
+  static class ZKPrinter
+  {
+  
+    static boolean FULLPATH_DEFAULT = false;
+  
+    boolean indent = true;
+    boolean fullpath = FULLPATH_DEFAULT;
+    boolean detail = false;
+  
+    String addr; // the address passed to us
+    String keeperAddr; // the address we're connected to
+  
+    boolean doClose;  // close the client after done if we opened it
+  
+    HttpServletResponse response;
+    PrintWriter out;
+    SolrZkClient zkClient;
+  
+    int level;
+    int maxData = 95;
+  
+    public ZKPrinter(HttpServletResponse response, PrintWriter out, ZkController controller, String addr) throws IOException
+    {
+      this.response = response;
+      this.out = out;
+      this.addr = addr;
+      
+      if (addr == null)
+      {
+        if (controller != null)
+        {
+          // this core is zk enabled
+          keeperAddr = controller.getZkServerAddress();
+          zkClient = controller.getZkClient();
+          if (zkClient != null && zkClient.isConnected())
+          {
+            return;
+          }
+          else
+          {
+            // try a different client with this address
+            addr = keeperAddr;
+          }
+        }
+      }
+  
+      keeperAddr = addr;
+      if (addr == null)
+      {
+        response.setStatus(404);
+        out.println
+        (
+          "{" +
+          "\"status\": 404" +
+          ", \"error\" : \"Zookeeper is not configured for this Solr Core. Please try connecting to an alternate zookeeper address.\"" +
+          "}"
+        );
+        return;
+      }
+  
+      try
+      {
+        zkClient = new SolrZkClient(addr, 10000);
+        doClose = true;
+      }
+      catch (TimeoutException e)
+      {
+        response.setStatus(503);
+        out.println
+        (
+          "{" +
+          "\"status\": 503" +
+          ", \"error\" : \"Could not connect to zookeeper at '" + addr + "'\"" +
+          "}"
+        );
+        zkClient = null;
+        return;
+      }
+      catch (InterruptedException e)
+      {
+        // Restore the interrupted status
+        Thread.currentThread().interrupt();
+        response.setStatus(503);
+        out.println
+        (
+          "{" +
+          "\"status\": 503" +
+          ", \"error\" : \"Could not connect to zookeeper at '" + addr + "'\"" +
+          "}"
+        );
+        zkClient = null;
+        return;
+      }
+  
+    }
+
+    public void close()
+    {
+      try {
+        if (doClose)
+        {
+          zkClient.close();
+        }
+      } catch (InterruptedException e) {
+          // ignore exception on close
+      }
+    }
+  
+    // main entry point
+    void print(String path) throws IOException
+    {
+      if (zkClient == null) {
+        return;
+      }
+  
+      // normalize path
+      if (path == null) {
+        path = "/";
+      }
+      else {
+        path.trim();
+        if (path.length() == 0)
+        {
+          path = "/";
+        }
+      }
+      
+      if (path.endsWith("/") && path.length() > 1)
+      {
+        path = path.substring(0, path.length() - 1);
+      }
+  
+      int idx = path.lastIndexOf('/');
+      String parent = idx >= 0 ? path.substring(0, idx) : path;
+      if (parent.length() == 0)
+      {
+        parent = "/";
+      }
+  
+      out.println("{");
+  
+      if (detail)
+      {
+        printZnode(path);
+        out.println(", ");
+      }
+  
+      out.println("\"tree\" : [");
+      printTree(path);
+      out.println("]");
+  
+      out.println("}");
+    }
+  
+    void exception(Exception e)
+    {
+      response.setStatus(500);
+      out.println
+      (
+        "{" +
+        "\"status\": 500" +
+        ", \"error\" : \"" + e.toString() + "\"" +
+        "}"
+      );
+    }
+  
+    void xmlescape(String s)
+    {
+      try
+      {
+        XML.escapeCharData(s, out);
+      }
+      catch (IOException e)
+      {
+        throw new RuntimeException(e);
+      }
+    }
+  
+    // collapse all whitespace to a single space or escaped newline
+    String compress(String str) {
+      StringBuilder sb = new StringBuilder();
+      for (int i = 0; i < str.length(); i++) {
+        char ch = str.charAt(i);
+        boolean whitespace = false;
+        boolean newline = false;
+        while (Character.isWhitespace(ch)) {
+          whitespace = true;
+          if (ch == '\n')
+            newline = true;
+          if (++i >= str.length())
+            return sb.toString();
+          ch = str.charAt(i);
+        }
+
+        if (newline) {
+          // sb.append("\\n");
+          sb.append("  ");  // collapse newline to two spaces
+        } else if (whitespace) {
+          sb.append(' ');
+        }
+
+        // TODO: handle non-printable chars
+        sb.append(ch);
+
+        if (sb.length() >= maxData)
+          return sb.toString() + " ...";
+      }
+      return sb.toString();
+    }
+
+    void url(String label, String path, boolean detail) throws IOException {
+      try {
+        out.print("<a href=\"zookeeper?");
+        if (path != null) {
+          out.print("path=");
+          out.print(URLEncoder.encode(path, "UTF-8"));
+        }
+        if (detail) {
+          out.print("&detail=" + detail);
+        }
+        if (fullpath != FULLPATH_DEFAULT) {
+          out.print("&fullpath=" + fullpath);
+        }
+        if (addr != null) {
+          out.print("&addr=");
+          out.print(URLEncoder.encode(addr, "UTF-8"));
+        }
+
+        out.print("\">");
+        xmlescape(label);
+        out.print("</a>");
+
+      } catch (UnsupportedEncodingException e) {
+        exception(e);
+      }
+    }
+
+    void printTree(String path) throws IOException
+    {
+      String label = path;
+      if (!fullpath)
+      {
+        int idx = path.lastIndexOf('/');
+        label = idx > 0 ? path.substring(idx + 1) : path;
+      }
+  
+      //url(label, path, true);
+      out.println("{");
+      out.println("\"data\" : \"" + label + "\"");
+  
+      Stat stat = new Stat();
+      try
+      {
+        byte[] data = zkClient.getData(path, null, stat, true);
+  
+        if( stat.getEphemeralOwner() != 0 )
+        {
+          out.println(", \"ephemeral\" : true");
+          out.println(", \"version\" : \"" + stat.getVersion() + "\"");
+        }
+        
+        /*
+        if (stat.getNumChildren() != 0)
+        {
+          out.println(", \"children_count\" : \"" + stat.getNumChildren() + "\"");
+        }
+        */
+  
+        //if (data != null)
+        if( stat.getDataLength() != 0 )
+        {
+          String str;
+          try
+          {
+            str = new String(data, "UTF-8");
+            str = str.replaceAll("\\\"", "\\\\\"");
+  
+            out.print(", \"content\" : \"");
+            //xmlescape(compress(str));
+            out.print(compress(str));
+            out.println("\"");
+          }
+          catch (UnsupportedEncodingException e)
+          {
+            // not UTF8
+            StringBuilder sb = new StringBuilder("BIN(");
+            sb.append("len=" + data.length);
+            sb.append("hex=");
+            int limit = Math.min(data.length, maxData / 2);
+            for (int i = 0; i < limit; i++)
+            {
+              byte b = data[i];
+              sb.append(StrUtils.HEX_DIGITS[(b >> 4) & 0xf]);
+              sb.append(StrUtils.HEX_DIGITS[b & 0xf]);
+            }
+            if (limit != data.length)
+            {
+              sb.append("...");
+            }
+            sb.append(")");
+            str = sb.toString();
+            //out.print(str);
+          }
+        }
+      }
+      catch (IllegalArgumentException e)
+      {
+        // path doesn't exist (must have been removed)
+        out.println("(path gone)");
+      }
+      catch (KeeperException e)
+      {
+        e.printStackTrace();
+      }
+      catch (InterruptedException e)
+      {
+        e.printStackTrace();
+      }
+  
+      if( stat.getNumChildren() > 0 )
+      {
+        out.print(", \"children\" : [");
+  
+        List<String> children = null;
+        try
+        {
+          children = zkClient.getChildren(path, null, true);
+        }
+        catch (KeeperException e)
+        {
+          exception(e);
+          return;
+        }
+        catch (InterruptedException e)
+        {
+          exception(e);
+        }
+        catch (IllegalArgumentException e)
+        {
+          // path doesn't exist (must have been removed)
+          out.println("(children gone)");
+        }
+  
+        Integer i = 0;
+        for( String child : children )
+        {
+          if( 0 != i )
+          {
+            out.print(", ");
+          }
+  
+          String childPath = path + (path.endsWith("/") ? "" : "/") + child;
+          printTree( childPath );
+  
+          i++;
+        }
+  
+        out.println("]");
+      }
+  
+      out.println("}");
+    }
+
+    String time(long ms) {
+      return (new Date(ms)).toString() + " (" + ms + ")";
+    }
+  
+    void printZnode(String path) throws IOException
+    {
+      try
+      {
+        Stat stat = new Stat();
+        byte[] data = zkClient.getData(path, null, stat, true);
+  
+        out.println("\"znode\" : {");
+  
+        out.print("\"path\" : \"");
+        xmlescape(path);
+        out.println("\"");
+  
+        out.println(", \"version\" : \"" + stat.getVersion() + "\"");
+        out.println(", \"aversion\" : \"" + stat.getAversion() + "\"");
+        out.println(", \"cversion\" : \"" + stat.getCversion() + "\"");
+        out.println(", \"ctime\" : \"" + time(stat.getCtime()) + "\"");
+        out.println(", \"mtime\" : \"" + time(stat.getMtime()) + "\"");
+        out.println(", \"czxid\" : \"" + stat.getCzxid() + "\"");
+        out.println(", \"mzxid\" : \"" + stat.getMzxid() + "\"");
+        out.println(", \"pzxid\" : \"" + stat.getPzxid() + "\"");
+        out.println(", \"children_count\" : \"" + stat.getNumChildren() + "\"");
+        out.println(", \"ephemeralOwner\" : \"" + stat.getEphemeralOwner() + "\"");
+        out.println(", \"dataLength\" : \"" + stat.getDataLength() + "\"");
+  
+        if( stat.getDataLength() != 0 )
+        {
+          boolean isBinary = false;
+          String str;
+          try
+          {
+            str = new String(data, "UTF-8");
+          }
+          catch (UnsupportedEncodingException e)
+          {
+            // The results are unspecified
+            // when the bytes are not properly encoded.
+  
+            // not UTF8
+            StringBuilder sb = new StringBuilder(data.length * 2);
+            for (int i = 0; i < data.length; i++)
+            {
+              byte b = data[i];
+              sb.append(StrUtils.HEX_DIGITS[(b >> 4) & 0xf]);
+              sb.append(StrUtils.HEX_DIGITS[b & 0xf]);
+              if ((i & 0x3f) == 0x3f)
+              {
+                sb.append("\n");
+              }
+            }
+            str = sb.toString();
+          }
+          str = str.replaceAll("\\\"", "\\\\\"");
+  
+          out.print(", \"data\" : \"");
+          //xmlescape(str);
+          out.print(str);
+          out.println("\"");
+        }
+  
+        out.println("}");
+  
+      }
+      catch (KeeperException e)
+      {
+        exception(e);
+        return;
+      }
+      catch (InterruptedException e)
+      {
+        exception(e);
+      }
+    }
+  }
+}
+

Modified: lucene/dev/trunk/solr/webapp/web/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/WEB-INF/web.xml?rev=1292429&r1=1292428&r2=1292429&view=diff
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/WEB-INF/web.xml (original)
+++ lucene/dev/trunk/solr/webapp/web/WEB-INF/web.xml Wed Feb 22 18:06:40 2012
@@ -87,11 +87,21 @@
     <servlet-name>Logging</servlet-name>
     <servlet-class>org.apache.solr.servlet.LogLevelSelection</servlet-class>
   </servlet>
+  
+  <servlet>
+    <servlet-name>Zookeeper</servlet-name>
+    <servlet-class>org.apache.solr.servlet.ZookeeperInfoServlet</servlet-class>
+  </servlet>
 
   <servlet-mapping>
     <servlet-name>Logging</servlet-name>
     <url-pattern>/admin/logging</url-pattern>
   </servlet-mapping>
+  
+  <servlet-mapping>
+    <servlet-name>Zookeeper</servlet-name>
+    <url-pattern>/zookeeper</url-pattern>
+  </servlet-mapping>
 
   <mime-mapping>
     <extension>.xsl</extension>

Modified: lucene/dev/trunk/solr/webapp/web/index.jsp
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/index.jsp?rev=1292429&r1=1292428&r2=1292429&view=diff
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/index.jsp (original)
+++ lucene/dev/trunk/solr/webapp/web/index.jsp Wed Feb 22 18:06:40 2012
@@ -20,7 +20,7 @@
     
     app_config.solr_path = '<%= request.getContextPath() %>';
     app_config.core_admin_path = '<%= cores.getAdminPath() %>';
-    app_config.zookeeper_path = 'zookeeper.jsp';
+    app_config.zookeeper_path = 'zookeeper';
     app_config.schema_path = '/admin/file?file=schema.xml&contentType=text/xml;charset=utf-8';
     app_config.config_path = '/admin/file?file=solrconfig.xml&contentType=text/xml;charset=utf-8';