package diskCacheV111.hsmControl.flush; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.PrintWriter; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.StringTokenizer; import diskCacheV111.pools.PoolCellInfo; import diskCacheV111.pools.PoolCostInfo; import diskCacheV111.pools.StorageClassFlushInfo; import diskCacheV111.util.CacheException; import diskCacheV111.util.TimeoutCacheException; import dmg.cells.nucleus.CellEndpoint; import dmg.cells.nucleus.CellMessageSender; import dmg.cells.nucleus.CellPath; import dmg.cells.nucleus.NoRouteToCellException; import dmg.util.HttpException; import dmg.util.HttpRequest; import dmg.util.HttpResponseEngine; import org.dcache.cells.CellStub; import static java.util.concurrent.TimeUnit.SECONDS; public class HttpHsmFlushMgrEngineV1 implements HttpResponseEngine, CellMessageSender { private static final Logger _log = LoggerFactory.getLogger(HttpHsmFlushMgrEngineV1.class); private CellEndpoint _endpoint; private long _errorCounter; private long _requestCounter; private String _cssFile = "/flushManager/css/default.css" ; private final List<String> _managerList = new ArrayList<>() ; private final HttpFlushManagerHelper.PoolEntryComparator _poolCompare; private final HttpFlushManagerHelper.FlushEntryComparator _flushCompare; public HttpHsmFlushMgrEngineV1(String [] argsString ){ for( int i = 0 ; i < argsString.length ; i++ ){ _log.info("HttpPoolMgrEngineV3 : argument : "+i+" : "+argsString[i]); if( argsString[i].startsWith("css=") ){ decodeCss( argsString[i].substring(4) ) ; }else if( argsString[i].startsWith("mgr=") ){ decodeManager( argsString[i].substring(4) ) ; } } _poolCompare = new HttpFlushManagerHelper.PoolEntryComparator() ; _poolCompare.setColumn(0) ; _flushCompare = new HttpFlushManagerHelper.FlushEntryComparator() ; _flushCompare.setColumn(1); if(_managerList.isEmpty()) { _managerList.add("FlushManager"); } _log.info("Using Manager : "+_managerList ) ; _log.info("Using CSS file : "+_cssFile ) ; } @Override public void setCellEndpoint(CellEndpoint endpoint) { _endpoint = endpoint; } private void decodeManager( String managers ){ managers = managers.trim() ; for( StringTokenizer st = new StringTokenizer(managers,",") ; st.hasMoreTokens() ; ){ _managerList.add( st.nextToken() ) ; } } private void decodeCss( String cssDetails ){ cssDetails = cssDetails.trim() ; if((!cssDetails.isEmpty()) && ! cssDetails.equals("default") ) { _cssFile = cssDetails; } } @Override public void queryUrl( HttpRequest request ) throws HttpException { PrintWriter pw = request.getPrintWriter() ; String [] urlItems = request.getRequestTokens() ; request.printHttpHeader(0); _requestCounter ++ ; try{ if( urlItems.length < 1 ) { return; } if( ( urlItems.length > 1 ) && ( urlItems[1].equals("css") ) ){ // // the internal css stuff (if nothing else is specifed) // if( urlItems.length > 2 ) { printCssFile(pw, urlItems[2]); } // }else if( ( urlItems.length > 1 ) && ( urlItems[1].equals("mgr") ) ){ // // the parameter handler (dCache partitioning) // String flushManagerName = "FlushManager" ; Map<?,?> optionsMap = new HashMap<>() ; if( urlItems.length > 2 ) { flushManagerName = urlItems[2]; } if( urlItems.length > 3 ) { optionsMap = createMap(urlItems[3]); } CellStub flushManager = new CellStub(_endpoint, new CellPath(flushManagerName), 20, SECONDS); _log.info("MAP -> "+optionsMap); printFlushHeader( pw , "Flush Info"); printDirectory( pw ) ; if( ! flushManagerName.equals("*") ){ StringBuffer result = new StringBuffer() ; doActionsIfNecessary(flushManager, optionsMap, result); String errorString = result.toString() ; if(!errorString.isEmpty()){ pw.println("<hr>"); pw.println("<h2>The following errors were reported</h2>"); pw.println("<pre>"); pw.println(errorString); pw.println("</pre>"); pw.println("<hr>"); } try{ printUpdateThis( pw , flushManagerName ) ; printCellInfo(pw, flushManager); printFlushManagerList(pw, flushManager, optionsMap); }catch(Exception ee ){ pw.println("<center><h2>Flush Manager "+flushManagerName+" seems not to be present</h2>"); } } } }catch(Exception ee ){ _errorCounter ++ ; showProblem( pw , ee.getMessage() ) ; pw.println("<ul>"); for( int i = 0 ; i < urlItems.length ; i++ ){ pw.println("<li> ["+i+"] ") ; pw.println(urlItems[i]) ; } pw.println("</ul>"); }finally{ pw.println( "<address>Last Modified : "+( new Date() )+ " $Id: HttpHsmFlushMgrEngineV1.java,v 1.3 2006-05-20 10:40:02 patrick Exp $</address>"); pw.println( "</body>" ) ; pw.println( "</html>" ) ; } } @Override public void startup() { // No background activity to start } @Override public void shutdown() { // No background activity to shutdown } private void printUpdateThis( PrintWriter pw , String thisManager ){ pw.println("<center><a class=\"big-link\" href=\""); pw.println(thisManager); pw.println("\"><span class=\"big-link\">"); pw.println("Update this Flush Manager ("+thisManager+")"); pw.println("</span></a></center><hr>"); } private Map<String,Object> createMap( String message ){ Map<String, Object> map = new HashMap<>() ; int pos = message.indexOf('?'); if( ( pos < 0 ) || ( pos == ( message.length() - 1 ) ) ){ map.put("$MAIN$",message); return map ; } map.put("$MAIN$",message.substring(pos)); StringTokenizer st = new StringTokenizer(message.substring(pos+1),"&") ; while( st.hasMoreTokens() ){ StringTokenizer ss = new StringTokenizer( st.nextToken() , "=" ) ; try{ String key = ss.nextToken() ; String value = ss.hasMoreTokens() ? ss.nextToken() : "true" ; Object o = map.get(key) ; if( o == null ){ map.put( key , value ) ; }else if( o instanceof List ){ ((List)o).add(value) ; }else if( o instanceof String ){ List l = new ArrayList() ; l.add( o ) ; l.add( value ) ; map.put( key , l ) ; } }catch(NoSuchElementException nsee ){} } return map ; } private void printCellInfo( PrintWriter pw , CellStub flushManager) throws Exception { try { FlushControlCellInfo info = flushManager.sendAndWait("xgetcellinfo", FlushControlCellInfo.class); prepareCellInfo(pw, flushManager.getDestinationPath().toString(), info); } catch (TimeoutCacheException e) { showTimeout(pw) ; } catch (CacheException e) { showProblem(pw, e.getMessage()); } } private void prepareCellInfo( PrintWriter pw , String flushManagerName , FlushControlCellInfo info ){ pw.println("<h2 class=\"s-table\">Manager : "+flushManagerName+"</h2>"); pw.println("<center><table class=\"s-table\">"); pw.println("<tr class=\"s-table\">"); pw.println("<th class=\"s-table\">Cell Name</th>"); pw.println("<th class=\"s-table\">Driver Class</th>"); pw.println("<th class=\"s-table\">Control Type</th>"); pw.println("</tr><tr class=\"s-table-b\">"); pw.println("<td class=\"s-table\"><span class=\"s-table\">") ; pw.println(info.getCellName()+"@"+info.getDomainName()); pw.println("</span></td>"); pw.println("<td class=\"s-table\"><span class=\"s-table\">") ; pw.println(info.getDriverName()); pw.println("</span></td>"); pw.println("<td class=\"s-table\"><span class=\"s-table\">") ; pw.println(info.getIsControlled()?"Centrally Controlled":"Locally Controlled"); pw.println("</span></td>"); pw.println("</tr></table><br>"); pw.println("<form action=\"submitonoff\" method=\"get\">" ); pw.println("<input type=\"submit\" value=\"Control Locally\" name=\"command\">"); pw.println("<input type=\"submit\" value=\"Control Centrally\" name=\"command\">"); pw.println("</form>"); pw.println("</center>"); pw.println("<hr>"); } private void printFlushManagerList(PrintWriter pw, CellStub flushManager, Map<?,?> options) throws Exception { try { List<HsmFlushControlCore.PoolDetails> list = flushManager.sendAndWait("ls pool -l -binary", List.class); preparePoolList(pw, flushManager.getDestinationPath().toString(), options, list); } catch (TimeoutCacheException e) { showTimeout(pw); } catch (CacheException e) { showProblem(pw, e.getMessage()); } } private void doActionsIfNecessary(CellStub flushManager, Map<?,?> options , StringBuffer output ){ if( ( options == null ) || ( options.size() == 1 ) ) { return; } String command = (String)options.get("command") ; if( command == null ) { return; } if( command.startsWith("Control") ){ boolean central = command.contains("Centrally"); String remote = "set control "+( central ? "on" : "off" ) ; sendCommand(flushManager , remote , output ) ; }else if( command.equals("Flush") ){ Object o = options.get("storageclass") ; List<Object> list; if( o == null ) { return; } if( o instanceof String ){ list = new ArrayList<>() ; list.add( o ) ; } else if( o instanceof List ){ list = (List<Object>) o ; } else { return; } for (Object element : list) { StringTokenizer st = new StringTokenizer(element.toString(), "$"); String poolName = st.nextToken(); String storageClass = st.nextToken(); String remote = "flush pool " + poolName + " " + storageClass; sendCommand(flushManager, remote, output); } }else if( command.startsWith( "Set" ) || command.startsWith( "Query" ) ){ boolean rdOnly = command.contains("Only"); boolean query = command.contains("Query"); Object o = options.get("pools") ; List<Object> list; if( o == null ) { return; } if( o instanceof String ){ list = new ArrayList<>() ; list.add( o ) ; } else if( o instanceof List ){ list = (List<Object>) o ; } else { return; } for (Object element : list) { String poolName = element.toString(); String remote = query ? ("query pool mode " + poolName) : "set pool " + poolName + " " + (rdOnly ? "rdonly" : "rw"); sendCommand(flushManager, remote, output); } } } private void sendCommand(CellStub stub, String command, StringBuffer output) { try{ stub.sendAndWait(command, Serializable.class); } catch (TimeoutCacheException e) { output.append("Command timed out : ").append(command).append("\n"); } catch(InterruptedException | CacheException | NoRouteToCellException e) { output.append("Exception in command : ").append(command).append("\n") ; output.append(" ").append(e.getClass().getName()). append(" -> ").append( e.getMessage() ).append("\n") ; _log.warn(e.toString()); } } private void preparePoolList( PrintWriter pw , String flushManagerName , Map<?,?> options , List<HsmFlushControlCore.PoolDetails> list ){ List<HttpFlushManagerHelper.PoolEntry> pools = new ArrayList<>() ; List<HttpFlushManagerHelper.FlushEntry> flushs = new ArrayList<>() ; for (HsmFlushControlCore.PoolDetails pool : list) { String poolName = pool.getName(); boolean isReadOnly = pool.isReadOnly(); PoolCellInfo cellInfo = pool.getCellInfo(); if (cellInfo == null) { continue; } PoolCostInfo costInfo = cellInfo.getPoolCostInfo(); if (costInfo == null) { continue; } PoolCostInfo.PoolSpaceInfo spaceInfo = costInfo.getSpaceInfo(); PoolCostInfo.PoolQueueInfo queueInfo = costInfo.getStoreQueue(); long totalSpace = spaceInfo.getTotalSpace(); long preciousSpace = spaceInfo.getPreciousSpace(); HttpFlushManagerHelper.PoolEntry pentry = new HttpFlushManagerHelper.PoolEntry(); pentry._poolName = pool.getName(); pentry._total = totalSpace; pentry._precious = preciousSpace; pentry._isReadOnly = isReadOnly; pentry._flushing = 0; pools.add(pentry); List<HsmFlushControlCore.FlushInfoDetails> flushes = pool.getFlushInfos(); if ((flushes == null) || (flushes.isEmpty())) { continue; } for (Object flush1 : flushes) { HsmFlushControlCore.FlushInfoDetails flush = (HsmFlushControlCore.FlushInfoDetails) flush1; StorageClassFlushInfo info = flush.getStorageClassFlushInfo(); HttpFlushManagerHelper.FlushEntry fentry = new HttpFlushManagerHelper.FlushEntry(); fentry._poolName = pool.getName(); fentry._storageClass = flush.getName(); fentry._isFlushing = flush.isFlushing(); fentry._total = totalSpace; fentry._precious = info.getTotalPendingFileSize(); fentry._pending = info.getRequestCount(); fentry._active = info.getActiveCount(); fentry._failed = info.getFailedRequestCount(); if (fentry._isFlushing) { pentry._flushing++; } flushs.add(fentry); } } Collections.sort( pools , _poolCompare ) ; Collections.sort( flushs , _flushCompare ) ; printFlushingPools( pw , flushManagerName , options , pools ) ; printFlushingStorageClasses( pw , flushManagerName , options , flushs ) ; } private static final String [] POOL_TABLE_TITLE = { "Action" , "PoolName" , "Pool Mode" , "Flushing" , "Total Size" , "Precious Size" , "Fraction" } ; private void printFlushingPools( PrintWriter pw , String flushManagerName , Map<?,?> options , List<HttpFlushManagerHelper.PoolEntry> pools ){ pw.println("<form action=\"submitpools\" method=\"get\">" ); pw.println("<h2 class=\"s-table\">Flushing Pools</h2>"); pw.println("<center><table class=\"s-table\">"); pw.println("<tr class=\"s-table\">"); for (String s : POOL_TABLE_TITLE) { pw.print("<th class=\"s-table\">"); pw.print(s); pw.println("</th>"); } pw.println("</tr>"); int row = 0 ; for( Iterator<HttpFlushManagerHelper.PoolEntry> it = pools.iterator() ; it.hasNext() ; row++ ){ HttpFlushManagerHelper.PoolEntry pentry = it.next(); /* pw.print( pentry._isReadOnly || ( pentry._flushing > 0 ) ? "<tr class=\"s-table-e\">" : row%2 == 0 ? "<tr class=\"s-table-a\">" : "<tr class=\"s-table-b\">" ); */ pw.print( row%2 == 0 ? "<tr class=\"s-table-a\">" : "<tr class=\"s-table-b\">" ); pw.print("<td class=\"s-table\">"); pw.print("<input type=\"checkbox\" name=\"pools\" value=\""); pw.print(pentry._poolName) ; pw.print("\">"); pw.print("</input>"); pw.println("</td>"); pw.print("<td class=\"s-table\">");pw.print(pentry._poolName);pw.println("</td>"); if( pentry._isReadOnly ){ pw.print("<td class=\"s-table-e\">"); pw.print("ReadOnly"); }else{ pw.print("<td class=\"s-table\">"); pw.print("ReadWrite"); } pw.println("</td>"); pw.print(pentry._flushing>0?"<td class=\"s-table-e\">":"<td class=\"s-table\">"); pw.print(pentry._flushing); pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(pentry._total);pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(pentry._precious);pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print( (float)(((double)pentry._precious/(double)pentry._total)/100.0)); pw.println("</td>"); pw.println("</tr>"); } pw.println("</table><br>"); pw.println("<input type=\"submit\" value=\"Set Read Only\" name=\"command\">"); pw.println("<input type=\"submit\" value=\"Set Read Write\" name=\"command\">"); pw.println("<input type=\"submit\" value=\"Query\" name=\"command\">"); pw.println("</center>"); pw.println("</form>"); pw.println("<hr>"); } private static final String [] FLUSH_TABLE_TITLE = { "Action" , "PoolName" , "StorageClass" , "Status" , "Total Size" , "Precious Size" , "Fraction" , "Active" , "Pending" , "Failed" } ; private void printFlushingStorageClasses( PrintWriter pw , String flushManagerName , Map<?,?> options , List<HttpFlushManagerHelper.FlushEntry> pools ){ pw.println("<form action=\"submitstorageclass\" method=\"get\">" ); pw.print("<h2 class=\"s-table\">Flushing Storage Classes</h2>"); pw.print("<center><table class=\"s-table\">"); pw.println("<tr class=\"s-table\">"); for (String s : FLUSH_TABLE_TITLE) { pw.print("<th class=\"s-table\">"); pw.print(s); pw.println("</th>"); } pw.println("</tr>"); int row = 0 ; for( Iterator<HttpFlushManagerHelper.FlushEntry> it = pools.iterator() ; it.hasNext() ; row++ ){ HttpFlushManagerHelper.FlushEntry fentry = it.next(); pw.print( fentry._isFlushing ? "<tr class=\"s-table-e\">" : row%2 == 0 ? "<tr class=\"s-table-a\">" : "<tr class=\"s-table-b\">" ); pw.print("<td class=\"s-table\">"); pw.print("<input type=\"checkbox\" name=\"storageclass\" value=\""); pw.print(fentry._poolName+"$"+fentry._storageClass) ; pw.print("\">"); pw.print("</input>"); pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(fentry._poolName);pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(fentry._storageClass);pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(fentry._isFlushing?"Flushing":"Idle"); pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(fentry._total);pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(fentry._precious);pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print( (float)(((double)fentry._precious/(double)fentry._total)/100.0)); pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(fentry._active);pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(fentry._pending);pw.println("</td>"); pw.print("<td class=\"s-table\">"); pw.print(fentry._failed);pw.println("</td>"); pw.println("</tr>"); } pw.println("</table><br>"); if(!pools.isEmpty()) { pw.println("<input type=\"submit\" value=\"Flush\" name=\"command\">"); } pw.println("</center>"); pw.println("</form>"); pw.println("<hr>"); } private void printFlushHeader( PrintWriter pw , String title ){ pw.println( "<html>"); pw.println( "<head><title>"+title+"</title>"); pw.println("<link rel=\"stylesheet\" type=\"text/css\" href=\""+_cssFile+"\">"); pw.println("</head>"); pw.println( "<body class=\"flush-body\">") ; pw.println( "<table border=0 cellpadding=10 cellspacing=0 width=\"90%\">"); pw.println( "<tr><td align=center valign=center width=\"1%\">" ) ; pw.println( "<a href=\"/\"><img border=0 src=\"/images/eagleredtrans.gif\"></a>"); pw.println( "<br><font color=red>Birds Home</font>" ) ; pw.println( "</td><td align=center>" ) ; pw.println( "<h1 class=\"m-title\">"+title+"</font></h1>"); pw.println( "</td></tr></table>"); } private void printDirectory( PrintWriter pw ){ printDirectory( pw , -1 ) ; } private void printDirectory( PrintWriter pw , int position ){ pw.println("<br><center><h2 class=\"m-table\">Flush Managers</h2><table class=\"m-table\">"); pw.println("<tr class=\"m-table\">"); for (Object o : _managerList) { String managerName = (String) o; printDirEntry(pw, managerName, false, "/flushManager/mgr/" + managerName + "/*"); } pw.println("</tr>"); pw.println("</table></center>"); pw.println("<br><hr>"); } private void printDirEntry( PrintWriter pw , String text , boolean inUse , String link ){ String alternateClass=inUse?"class=\"m-table-active\"":"class=\"m-table\"" ; pw.print("<td width=\"25%\" class=\"m-table\"><span "); pw.print(alternateClass); pw.print("><a "); pw.print(alternateClass); pw.print(" href=\"") ; pw.print(link) ; pw.print("\">") ; pw.print(text) ; pw.println("</a></span></td>") ; } private void printCssFile( PrintWriter pw , String filename ) { if( filename.equals("test.html") ){ }else if( filename.equals("default.css") ){ printInternalCssFile( pw ) ; } } private void printInternalCssFile( PrintWriter pw ){ pw.println("body { background-color:orange ; }"); pw.println("table.s-table { width:90% ; border:1px ; border-style:solid ; border-spacing:0px ; border-collapse:collapse ; }"); pw.println("tr.s-table { background-color:#115259 ; color:white; font-size:18 ; }"); pw.println("tr.s-table-a { background-color:#bebebe ; text-align:center ; font-size:16 ; }"); pw.println("tr.s-table-b { background-color:#efefef ; text-align:center ; font-size:16 ; }"); pw.println("tr.s-table-e { background-color:red ; text-align:center ; font-size:16 ; }"); pw.println("td.s-table { border:1px ; border-style:solid ; border-spacing:1px ; padding:3 ; }"); pw.println("th.s-table { border:1px ; border-style:solid ; border-spacing:1px ;}"); pw.println("td.s-table-disabled { border:1px ; border-style:solid ; border-spacing:0px ; padding:3 ;}"); pw.println("td.s-table-e { background-color:red ;}"); pw.println("td.s-table-regular { border:1px ; border-style:solid ; border-spacing:0px ; padding:3 ;}"); pw.println("span.s-table-disabled { color:gray ; }"); pw.println("span.s-table-regular { color:black ; }"); pw.println("a.s-table:visited { text-decoration:none ; color:blue ; }"); pw.println("a.s-table:link { text-decoration:none ; color:blue ; }"); pw.println("table.m-table { width:90% ; border:0px ; border-style:none ; border-spacing:0px ; border-collapse:collapse ; }"); pw.println("td.m-table { background-color:white ; text-align:center ; border:1px ; border-style:solid ; border-spacing:1px ;}"); pw.println("a.m-table:visited { text-decoration:none ; }"); pw.println("a.m-table-active:visited { text-decoration:none ; color:red ; }"); pw.println("a.m-table:link { text-decoration:none ; }"); pw.println("a.m-table-active:link { text-decoration:none ; color:red ; }"); pw.println("table.l-table { width:90% ; color:black ; table-layout:auto ;"); pw.println(" border:1px ; border-style:none ; border-spacing:0px ; border-collapse:collapse ; }"); pw.println("tr.l-table { background-color:green ; }"); pw.println("td.l-table { background-color:white ; color:black ;"); pw.println("width:10.5% ;"); pw.println("padding:4 ; text-align:center ;"); pw.println("border:1px ; border-style:solid ; border-spacing:0px ; border-collapse:collapse ; }"); pw.println("span.l-table { font-size:16 ;}"); pw.println("a.l-table:visited { text-decoration:none ; color:blue ; }"); pw.println("a.l-table:link { text-decoration:none ; color:blue ; }"); pw.println("table.f-table-a { width:90% ; color:black ; table-layout:auto ; background-color:white ;"); pw.println("border:1px ; border-style:solid ; border-spacing:0px ; border-collapse:collapse ;}"); pw.println("td.f-table-a { text-align:center ; padding:10 ; }"); pw.println("span.f-table-a { text-align:center ; font-size:20px }"); pw.println("table.f-table-b { width:100% ; color:black ; table-layout:auto ; "); pw.println(" border:1px ; border-style:none ; border-spacing:0px ; border-collapse:collapse ; }"); pw.println("th.f-table-b { width:20% ;}"); pw.println("td.f-table-b { width:20% ; background-color:#eeeeee ; color:black ;"); pw.println("padding:4 ; text-align:center ; border:1px ; border-style:solid ; border-spacing:0px ; }"); pw.println("span.m-title { font-size:18 ; color=red ; }"); pw.println("a.big-link:visited { text-decoration:none ; color:red ; }"); pw.println("a.big-link:link { text-decoration:none ; color:red ; }"); pw.println("span.big-link { font-size:24 ; text-align:center }"); } private void showTimeout( PrintWriter pw ){ pw.println("<font color=red><h1>Sorry, the request timed out</h1></font>"); } private void showProblem( PrintWriter pw , String message ){ pw.print("<font color=red><h1>") ; pw.print(message) ; pw.println("</h1></font>"); } }