From: <tho...@us...> - 2011-06-16 11:58:31
|
Revision: 4713 http://bigdata.svn.sourceforge.net/bigdata/?rev=4713&view=rev Author: thompsonbry Date: 2011-06-16 11:58:24 +0000 (Thu, 16 Jun 2011) Log Message: ----------- Progress on [1] (Add an "EXPLAIN" feature to the NanoSparqlServer). [1] https://sourceforge.net/apps/trac/bigdata/ticket/331 Modified Paths: -------------- branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/engine/QueryLog.java branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/util/HTMLUtility.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/StatusServlet.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/XMLBuilder.java Modified: branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/engine/QueryLog.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/engine/QueryLog.java 2011-06-15 21:58:45 UTC (rev 4712) +++ branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/engine/QueryLog.java 2011-06-16 11:58:24 UTC (rev 4713) @@ -308,7 +308,16 @@ final IPredicate<?> pred = (IPredicate<?>) bop .getProperty(PipelineJoin.Annotations.PREDICATE); if (pred != null) { - sb.append(Integer.toString(pred.getId())); + try { + final int predId = pred.getId(); + sb.append(Integer.toString(predId)); + } catch (IllegalStateException ex) { + /* + * All predicates SHOULD have a bopId, but this catches the + * error if one does not. + */ + sb.append(NA); + } } } sb.append('\t'); @@ -469,8 +478,8 @@ w.write("<th>accessPathChunksIn</th>"); w.write("<th>accessPathUnitsIn</th>"); // dynamics based on elapsed wall clock time. - w.write("<th>solutions/ms</th>"); - w.write("<th>mutations/ms</th>"); + w.write("<th>");w.write(cdata("solutions/ms"));w.write("</th>"); + w.write("<th>");w.write(cdata("mutations/ms"));w.write("</th>"); // // cost model(s) // @@ -550,7 +559,7 @@ w.write(cdata(dateFormat.format(new Date(q.getDeadline())))); w.write(TDx); w.write(TD + cdata(Long.toString(elapsed)) + TDx); - w.write(TD + (serviceId == null ? NA : serviceId.toString()) + TDx); + w.write(TD); w.write(cdata(serviceId == null ? NA : serviceId.toString()));w.write(TDx); w.write(TD); if (cause != null) w.write(cause.getLocalizedMessage()); @@ -561,23 +570,41 @@ final BOp bop = bopIndex.get(bopId); // the operator. - w.write(TD); if (summary) { /* * The entire query (recursively). */ - w.write(cdata(BOpUtility.toString(q.getQuery())));//.replace('\n', ' '))); + final String queryStr = BOpUtility.toString(q.getQuery()); + w.write(TD); + w.write("<a href=\"#\" title=\""); + w.write(attrib(queryStr));// the entire query as a tooltip. + w.write("\"\n>"); + // A slice of the query inline on the page. + w.write(cdata(queryStr.substring(0/* begin */, Math.min(64, queryStr + .length())))); + w.write("..."); + w.write("</a>"); w.write(TDx); w.write(TD); w.write("total"); // summary line. + w.write(TDx); } else { // Otherwise show just this bop. - w.write(cdata(bopIndex.get(bopId).toString())); + final String queryStr = bopIndex.get(bopId).toString(); + w.write(TD); + w.write("<a href=\"#\" title=\""); + w.write(attrib(queryStr));// the entire query as a tooltip. + w.write("\"\n>"); + // A slice of the query inline on the page. + w.write(cdata(queryStr.substring(0/* begin */, Math.min(64, queryStr + .length())))); + w.write("..."); + w.write("</a>"); w.write(TDx); w.write(TD); - w.write(evalOrder); // eval order for this bop. + w.write(Integer.toString(evalOrder)); // eval order for this bop. + w.write(TDx); } - w.write(TDx); w.write(TD); w.write(Integer.toString(bopId)); @@ -593,7 +620,16 @@ .getProperty(PipelineJoin.Annotations.PREDICATE); w.write(TD); if (pred != null) { - w.write(Integer.toString(pred.getId())); + try { + final int predId = pred.getId(); + w.write(Integer.toString(predId)); + } catch (IllegalStateException ex) { + /* + * All predicates SHOULD have a bopId, but this catches the + * error if one does not. + */ + w.write(cdata(NA)); + } } w.write(TDx); } @@ -635,7 +671,7 @@ // nvars w.write(TD); if (keyOrder != null) - w.write(pred.getVariableCount(keyOrder)); + w.write(Integer.toString(pred.getVariableCount(keyOrder))); w.write(TDx); // rangeCount @@ -677,7 +713,6 @@ } final long unitsIn = stats.unitsIn.get(); final long unitsOut = stats.unitsOut.get(); - w.write(TDx); w.write(TD); w.write(Integer.toString(fanIO)); w.write(TDx); @@ -700,7 +735,7 @@ w.write(Long.toString(stats.unitsOut.get())); w.write(TDx); w.write(TD); - w.write(unitsIn == 0 ? NA : Double.toString(unitsOut / (double) unitsIn)); + w.write(cdata(unitsIn == 0 ? NA : Double.toString(unitsOut / (double) unitsIn))); w.write(TDx); w.write(TD); w.write(Long.toString(stats.accessPathDups.get())); @@ -734,22 +769,38 @@ w.write("</tr\n>"); } - + /** - * Format the data as an (X)HTML table. The table will include a header - * which declares the columns, a detail row for each operator, and a summary - * row for the query as a whole. - * + * Write a summary row for the query. The table element, header, and footer + * must be written separately. * @param q - * The query. * @param w - * Where to write the table. - * + * @param sb * @throws IOException */ - public static void getXHTMLTable(final IRunningQuery q, final Writer w) - throws IOException { + static public void getSummaryRowXHTML(final IRunningQuery q, + final Writer w, final StringBuilder sb) throws IOException { + getTableRowXHTML(q, w, -1/* orderIndex */, q.getQuery().getId(), true/* summary */); + + } + + /** + * Format the data as an (X)HTML table. The table will include a header + * which declares the columns, a detail row for each operator (optional), + * and a summary row for the query as a whole. + * + * @param q + * The query. + * @param w + * Where to write the table. + * @param summaryOnly + * When <code>true</code> only the summary row will be written. + * @throws IOException + */ + public static void getTableXHTML(final IRunningQuery q, final Writer w, + final boolean summaryOnly) throws IOException { + // the table start tag. { /* @@ -768,8 +819,18 @@ getTableHeaderXHTML(q, w); - getTableRowsXHTML(q, w); - + if(summaryOnly) { + + getSummaryRowXHTML(q, w, sb); + + } else { + + getTableRowsXHTML(q, w); + + } + + w.write("</table\n>"); + } private static String cdata(String s) { @@ -783,4 +844,5 @@ return XHTMLRenderer.attrib(s); } + } Modified: branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/util/HTMLUtility.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/util/HTMLUtility.java 2011-06-15 21:58:45 UTC (rev 4712) +++ branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/util/HTMLUtility.java 2011-06-16 11:58:24 UTC (rev 4713) @@ -107,6 +107,10 @@ sb.append("'"); break; + case '/': + sb.append("/"); + break; + case '&': sb.append("&"); break; Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/StatusServlet.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/StatusServlet.java 2011-06-15 21:58:45 UTC (rev 4712) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/StatusServlet.java 2011-06-16 11:58:24 UTC (rev 4713) @@ -21,6 +21,7 @@ import com.bigdata.rdf.sail.webapp.BigdataRDFContext.RunningQuery; import com.bigdata.rdf.store.AbstractTripleStore; import com.bigdata.util.HTMLUtility; +import com.bigdata.util.InnerCause; /** * A status page for the service. @@ -73,9 +74,12 @@ final boolean showRunningQueries = req .getParameter("showRunningQueries") != null; - final boolean showRunningQueryStats = req - .getParameter("showRunningQueryStats") != null; + final boolean showRunningQueryStats = req + .getParameter("showRunningQueryStats") != null; + final boolean showRunningQueryDetailStats = req + .getParameter("showRunningQueryDetailStats") != null; + // Information about the KB (stats, properties). final boolean showKBInfo = req.getParameter("showKBInfo") != null; @@ -84,7 +88,15 @@ final HTMLBuilder doc = new HTMLBuilder(); - XMLBuilder.Node current = doc.root("html").node("body"); + XMLBuilder.Node current = doc.root("html"); + { + current = current.node("head"); + current.node("meta").attr("http-equiv", "Content-Type").attr( + "content", "text/html;charset=utf-8").close(); + current.node("title").text("bigdata®").close(); + current = current.close();// close the head. + } + current = current.node("body"); current.node("p", "Accepted query count=" + getBigdataRDFContext().getQueryIdFactory().get()); @@ -177,7 +189,8 @@ } - if (showRunningQueries) { + if (showRunningQueries || showRunningQueryStats + || showRunningQueryDetailStats) { /* * Show the queries which are currently executing (actually running @@ -195,25 +208,41 @@ for (UUID queryId : queryIds) { - final IRunningQuery query = queryEngine - .getRunningQuery(queryId); + final IRunningQuery query; + try { + query = queryEngine.getRunningQuery(queryId); - if (query == null) { - // Already terminated. - continue; - } + if (query == null) { + + // Already terminated. + continue; + + } + + } catch (RuntimeException e) { + + if (InnerCause.isInnerCause(e, InterruptedException.class)) { + + // Already terminated. + continue; + + } + + throw new RuntimeException(e); + + } - ages.put(query.getElapsed(), query); + ages.put(query.getElapsed(), query); - } + } { final Iterator<IRunningQuery> itr = ages.values().iterator(); - final StringWriter w = showRunningQueryStats ? new StringWriter( - Bytes.kilobyte32 * 8) - : null; + final StringWriter w = showRunningQueryStats + || showRunningQueryDetailStats ? new StringWriter( + Bytes.kilobyte32 * 8) : null; while (itr.hasNext()) { @@ -224,23 +253,23 @@ continue; } - /* - * @todo The runstate and stats could be formatted into an - * HTML table ala QueryLog or RunState. - */ - current = current.node("p", - "age=" + query.getElapsed() + "ms").node("p", - "queryId=" + query.getQueryId()).node("p", - HTMLUtility.escapeForXHTML(query.toString())).node( - "p", - HTMLUtility.escapeForXHTML(BOpUtility - .toString(query.getQuery()))); + if (showRunningQueries) { + current = current.node("p", + "age=" + query.getElapsed() + "ms").node("p", + "queryId=" + query.getQueryId()).node("p", + HTMLUtility.escapeForXHTML(query.toString())) + .node( + "p", + HTMLUtility.escapeForXHTML(BOpUtility + .toString(query.getQuery()))); + } - if (showRunningQueryStats) { - - // Format as a table. - QueryLog.getXHTMLTable(query, w); + if (showRunningQueryStats || showRunningQueryDetailStats) { + // Format as a table. + QueryLog.getTableXHTML(query, w, + !showRunningQueryDetailStats); + // Extract as String final String s = w.getBuffer().toString(); Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/XMLBuilder.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/XMLBuilder.java 2011-06-15 21:58:45 UTC (rev 4712) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/XMLBuilder.java 2011-06-16 11:58:24 UTC (rev 4713) @@ -44,6 +44,7 @@ */ public class XMLBuilder { + private final boolean xml; private final Writer m_writer; // private boolean m_pp = false; @@ -57,16 +58,7 @@ } public XMLBuilder(boolean xml, OutputStream outstr) throws IOException { - - if (outstr == null) { - m_writer = new StringWriter(); - } else { - m_writer = new OutputStreamWriter(outstr); - } - - if (xml) { - m_writer.write("<?xml version=\"1.0\"?>"); - } + this(xml,null/*encoding*/,outstr); } public XMLBuilder(boolean xml, String encoding) throws IOException { @@ -77,6 +69,8 @@ public XMLBuilder(boolean xml, String encoding, OutputStream outstr) throws IOException { + this.xml = xml; + if (outstr == null) { m_writer = new StringWriter(); } else { @@ -84,7 +78,16 @@ } if (xml) { - m_writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>"); + if(encoding!=null) { + m_writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>"); + } else { + m_writer.write("<?xml version=\"1.0\"?>"); + } + } else { + // TODO Note the optional encoding for use in a meta tag. + m_writer.write("<!DOCTYPE HTML PUBLIC"); + m_writer.write(" \"-//W3C//DTD HTML 4.01 Transitional//EN\""); + m_writer.write(" \"http://www.w3.org/TR/html4/loose.dtd\">"); } } @@ -167,11 +170,35 @@ return tmp.close(); } + /** + * Close the open element. + * @return The parent element. + * @throws IOException + */ public Node close() throws IOException { + return close(!xml); + } + + /** + * Close the open element. + * + * @param simpleEnd + * When <code>true</code> an open tag without a body will be + * closed by a single > symbol rather than the XML style + * &47;>. + * + * @return The parent element. + * @throws IOException + */ + public Node close(final boolean simpleEnd) throws IOException { assert(m_open); if (emptyBody()) { - m_writer.write("/>"); + if(simpleEnd) { + m_writer.write(">"); + } else { + m_writer.write("/>"); + } } else { m_writer.write("</" + m_tag + ">"); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |