You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-commits@lucene.apache.org by yo...@apache.org on 2009/12/31 23:17:23 UTC
svn commit: r894948 - in /lucene/solr/branches/cloud/src:
java/org/apache/solr/core/ZooKeeperController.java
webapp/web/admin/solr-admin.css webapp/web/admin/zookeeper.jsp
Author: yonik
Date: Thu Dec 31 22:17:23 2009
New Revision: 894948
URL: http://svn.apache.org/viewvc?rev=894948&view=rev
Log:
SOLR-1277: basic zookeeper browser for admin pages
Added:
lucene/solr/branches/cloud/src/webapp/web/admin/zookeeper.jsp (with props)
Modified:
lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java
lucene/solr/branches/cloud/src/webapp/web/admin/solr-admin.css
Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java?rev=894948&r1=894947&r2=894948&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java Thu Dec 31 22:17:23 2009
@@ -37,21 +37,25 @@
private String shardAddress;
+ private String zooKeeperHost;
+
/**
- * @param zookeeperHost ZooKeeper host service
+ * @param zooKeeperHost ZooKeeper host service
* @param shardAddress
* @param zkClientTimeout
* @param zkSolrPathPrefix Solr ZooKeeper node (default is /solr)
*/
- public ZooKeeperController(String zookeeperHost, String collection,
+ public ZooKeeperController(String zooKeeperHost, String collection,
String shardAddress, int zkClientTimeout) {
this.collectionName = collection;
this.shardAddress = shardAddress;
+ this.zooKeeperHost = zooKeeperHost;
+
CountdownWatcher countdownWatcher = new CountdownWatcher(
"ZooKeeperController");
System.out.println("timeout:" + zkClientTimeout);
try {
- keeper = new ZooKeeper(zookeeperHost, zkClientTimeout, countdownWatcher);
+ keeper = new ZooKeeper(zooKeeperHost, zkClientTimeout, countdownWatcher);
countdownWatcher.waitForConnected(5000);
@@ -193,4 +197,12 @@
// nocommit: handle
}
}
+
+ public ZooKeeper getZooKeeper() {
+ return keeper;
+ }
+
+ public String getZooKeeperHost() {
+ return zooKeeperHost;
+ }
}
Modified: lucene/solr/branches/cloud/src/webapp/web/admin/solr-admin.css
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/webapp/web/admin/solr-admin.css?rev=894948&r1=894947&r2=894948&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/webapp/web/admin/solr-admin.css (original)
+++ lucene/solr/branches/cloud/src/webapp/web/admin/solr-admin.css Thu Dec 31 22:17:23 2009
@@ -36,6 +36,13 @@
max-width:450px;
}
+input.big, textarea.big {
+ color: black;
+ border: 2px inset #ff9933;
+ background-color: #ffffff;
+ width:100%;
+}
+
input.stdbutton {
font-family: ITC Officina Sans Book, Helvetica, Arial, sans-serif;
font-style: bold;
Added: lucene/solr/branches/cloud/src/webapp/web/admin/zookeeper.jsp
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/webapp/web/admin/zookeeper.jsp?rev=894948&view=auto
==============================================================================
--- lucene/solr/branches/cloud/src/webapp/web/admin/zookeeper.jsp (added)
+++ lucene/solr/branches/cloud/src/webapp/web/admin/zookeeper.jsp Thu Dec 31 22:17:23 2009
@@ -0,0 +1,424 @@
+<%@ page contentType="text/html; charset=utf-8" pageEncoding="UTF-8"%>
+<%--
+ 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.
+--%>
+<%@ page import="javax.servlet.jsp.JspWriter,java.io.IOException,org.apache.zookeeper.*,org.apache.zookeeper.data.Stat,org.apache.solr.core.*,org.apache.solr.common.util.*
+ "%>
+<%@ page import="java.io.*"%>
+<%@ page import="java.util.*"%>
+<%@ page import="java.net.URLEncoder"%>
+
+<%@include file="header.jsp" %>
+
+<br clear="all">
+<h2>Zookeeper Browser</h2>
+
+<%
+ 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");
+
+ ZKPrinter printer = new ZKPrinter(out, core, addr);
+ printer.detail = detail;
+ String tryAddr = printer.keeperAddr!=null ? printer.keeperAddr : "localhost:2181";
+%>
+
+<form method="GET" action="zookeeper.jsp" accept-charset="UTF-8">
+<table>
+<tr>
+ <td>
+ <strong> <% XML.escapeCharData(printer.keeper==null ? "Disconnected" : ("Connected to zookeeper "+printer.keeperAddr), out); %> </strong>
+ </td>
+ <td>
+ <strong>Connect to different zookeeper</strong>
+ <input class="std" name="addr" type="text" value="<% XML.escapeCharData(tryAddr, out); %>">
+ </td>
+ <td>
+ <input class="stdbutton" type="submit" value="CONNECT">
+ </td>
+</tr>
+<tr>
+</form>
+
+
+<%
+ printer.print(path);
+%>
+
+</body>
+</html>
+
+<%!
+
+
+ static class ZKPrinter {
+ static boolean FULLPATH_DEFAULT=true;
+ boolean fullpath=FULLPATH_DEFAULT;
+ boolean detail=false;
+ String addr; // the address passed to us
+ String keeperAddr; // the address we're connected to
+
+ ZooKeeper keeper;
+ JspWriter out;
+ int level;
+ int maxData = 60;
+
+ private boolean levelchange;
+
+ public ZKPrinter(JspWriter out, SolrCore core, String addr) throws IOException {
+ this.out = out;
+ this.addr = addr;
+
+ // ZooKeeperController controller = core.getCoreDescriptor().getCoreContainer().getZooKeeperController();
+ ZooKeeperController controller = null;
+
+ if (controller == null) {
+ keeperAddr = addr;
+ if (addr == null) {
+ out.println("Zookeeper is not configured for this Solr Core. Please try connecting to an alternate zookeeper address.");
+ return;
+ }
+
+ try {
+ keeper = new ZooKeeper(addr, 10000, null);
+ } catch (IOException e) {
+ out.println("Could not connect to zookeeper at " + addr);
+ return;
+ }
+
+ try {
+ Thread.sleep(2000); // temporary hack to wait until connected
+ } catch (InterruptedException e) {
+ exception(e);
+ }
+
+ if (keeper.getState() != ZooKeeper.States.CONNECTED) {
+ out.println("Could not connect to zookeeper at " + addr);
+ keeper = null;
+ return;
+ }
+ } else {
+ keeper = controller.getZooKeeper();
+ keeperAddr = controller.getZooKeeperHost();
+ }
+
+ }
+
+
+ // main entry point
+ void print(String path) throws IOException {
+ if (keeper==null) return;
+
+ out.print("<table>");
+ out.print("<tr><td>");
+ out.print("[");
+ url("ROOT","/",false);
+ out.print("]");
+
+ // 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.print(" [");
+ url("PARENT",parent,detail);
+ out.print("]");
+ out.print("</td></tr>");
+
+ if (detail) {
+ out.print("<tr><td>");
+ printZnode(path);
+ out.print("</td></tr>");
+ }
+
+ out.print("<tr><td>");
+ printTree(path);
+ out.print("</td></tr>");
+
+ out.print("</table>");
+ }
+
+
+
+ void exception(Exception e) {
+ try {
+ out.println(e.toString());
+ } catch (IOException e1) {
+ // nothing we can do
+ }
+ }
+
+ void xmlescape(String s) {
+ try {
+ XML.escapeCharData(s, out);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ void up() throws IOException {
+ level++;
+ if (!fullpath) out.println("<BLOCKQUOTE>");
+ levelchange=true;
+ }
+
+ void down() throws IOException {
+ level--;
+ if (!fullpath) out.println("</BLOCKQUOTE>");
+ levelchange=true;
+ }
+
+ void indent() throws IOException {
+ // if we are using blockquote and just changed indent levels, don't output a break
+ if (fullpath || !levelchange) out.println("<br>");
+ levelchange = false;
+ // if fullpath, no indent is needed
+ // if not, we are currently using blockquote which the browser
+ // will take care of indenting.
+ }
+
+
+ // 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");
+ } 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.jsp?");
+ 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 {
+
+ indent();
+
+ // TODO: make a link from the path
+
+ String label = path;
+ if (!fullpath) {
+ int idx = path.lastIndexOf('/');
+ label = idx > 0 ? path.substring(idx+1) : path;
+ }
+
+ url(label, path, true);
+
+ out.print(" [");
+
+ Stat stat = new Stat();
+ try {
+ byte[] data = keeper.getData(path, null, stat);
+
+ out.print("v=" + stat.getVersion());
+ if (stat.getNumChildren() != 0) {
+ out.print(" children=" + stat.getNumChildren());
+ }
+
+ if (data != null) {
+ String str;
+ try {
+ str = new String(data, "UTF-8");
+ out.print(" d=\"");
+ xmlescape(compress(str));
+ out.print("\"");
+ } 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(" d="+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();
+ }
+
+ out.println("]");
+
+ if (stat.getNumChildren() <= 0) return;
+
+ List<String> children = null;
+ try {
+ children = keeper.getChildren(path, null);
+ } 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)");
+ }
+
+ up();
+ for (String child : children) {
+ String childPath = path + (path.endsWith("/")?"":"/") + child;
+ printTree(childPath);
+ }
+ down();
+ }
+
+ void printZnode(String path) throws IOException {
+ try {
+
+ Stat stat = new Stat();
+ byte[] data = keeper.getData(path, null, stat);
+
+ out.print("<h2>");
+ xmlescape(path);
+ out.print("</h2>");
+
+ up();
+ indent(); out.print("version=" + stat.getVersion());
+ indent(); out.print("aversion=" + stat.getAversion());
+ indent(); out.print("cversion=" + stat.getCversion());
+ indent(); out.print("ctime=" + stat.getCtime());
+ indent(); out.print("mtime=" + stat.getMtime());
+ indent(); out.print("czxid=" + stat.getCzxid());
+ indent(); out.print("mzxid=" + stat.getMzxid());
+ indent(); out.print("pzxid=" + stat.getPzxid());
+ indent(); out.print("numChildren=" + stat.getNumChildren());
+ indent(); out.print("ephemeralOwner=" + stat.getEphemeralOwner());
+ indent(); out.print("dataLength=" + stat.getDataLength());
+
+ if (data != null) {
+ boolean isBinary = false;
+ String str;
+ try {
+ str = new String(data, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // 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();
+ }
+
+ int nLines = 1;
+ int lineLen = 0;
+ int maxLineLen = 10; // the minimum
+ for (int i=0; i<str.length(); i++) {
+ if (str.charAt(i)=='\n') {
+ nLines++;
+ maxLineLen = Math.max(maxLineLen, lineLen);
+ lineLen = 0;
+ } else {
+ lineLen++;
+ }
+ }
+
+ indent();
+ out.println("<form method='post' action=''>");
+ out.println("<textarea class='big' wrap='off' readonly rows='" + Math.min(20,nLines)
+// + "' cols='" + Math.min(80, maxLineLen+1)
+// + "' cols='" + (maxLineLen+1)
+ + "' name='data'>");
+
+ xmlescape(str);
+
+ out.println("</textarea></form>");
+ }
+
+ down();
+
+ } catch (KeeperException e) {
+ exception(e);
+ return;
+ } catch (InterruptedException e) {
+ exception(e);
+ }
+ }
+ }
+%>
\ No newline at end of file
Propchange: lucene/solr/branches/cloud/src/webapp/web/admin/zookeeper.jsp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/solr/branches/cloud/src/webapp/web/admin/zookeeper.jsp
------------------------------------------------------------------------------
svn:executable = *
Propchange: lucene/solr/branches/cloud/src/webapp/web/admin/zookeeper.jsp
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL