/** * Copyright (c) 2013 Johannes Dillmann, Zuse Institute Berlin * * Licensed under the BSD License, see LICENSE file for details. * */ package org.xtreemfs.dir; import java.io.IOException; import java.util.HashMap; import java.util.Map.Entry; import org.xtreemfs.babudb.api.database.Database; import org.xtreemfs.babudb.api.database.ResultSet; import org.xtreemfs.babudb.api.exception.BabuDBException; import org.xtreemfs.common.statusserver.StatusServerHelper; import org.xtreemfs.common.statusserver.StatusServerModule; import org.xtreemfs.dir.data.ServiceRecord; import org.xtreemfs.foundation.buffer.ReusableBuffer; import org.xtreemfs.foundation.json.JSONException; import org.xtreemfs.foundation.json.JSONParser; import org.xtreemfs.foundation.logging.Logging; import org.xtreemfs.pbrpc.generatedinterfaces.DIR.ServiceType; import com.sun.net.httpserver.HttpExchange; /** * Serves a HTML page, which is using JavaScript to monitor and present the states of the OSDs and open files. */ public class ReplicaStatusPage extends StatusServerModule { private DIRRequestDispatcher master; private final String statusPageTemplate; private enum Vars { OSDSJSON("<!-- $OSDSJSON -->"); private String template; Vars(String template) { this.template = template; } @Override public String toString() { return template; } }; public ReplicaStatusPage() { StringBuffer sb = StatusServerHelper.readTemplate("org/xtreemfs/dir/templates/replica_status.html"); if (sb == null) { statusPageTemplate = "<h1>Template was not found, unable to show status page!</h1>"; } else { statusPageTemplate = sb.toString(); } } @Override public String getDisplayName() { return "Replica Status Summary"; } @Override public String getUriPath() { return "/replica_status"; } @Override public boolean isAvailableForService(ServiceType service) { return service == ServiceType.SERVICE_TYPE_DIR; } @Override public void initialize(ServiceType service, Object serviceRequestDispatcher) { assert (service == ServiceType.SERVICE_TYPE_DIR); master = (DIRRequestDispatcher) serviceRequestDispatcher; } @Override public void shutdown() { } @Override public void handle(HttpExchange httpExchange) throws IOException { String uriPath = httpExchange.getRequestURI().getPath(); if (uriPath.equals("/replica_status/d3.v3.js")) { StatusServerHelper.sendFile("org/xtreemfs/dir/templates/d3.v3.js", httpExchange); } else if (uriPath.equals("/replica_status")) { handleStatusPage(httpExchange); } else { httpExchange.sendResponseHeaders(404, -1); httpExchange.close(); } } private void handleStatusPage(HttpExchange httpExchange) throws IOException { // The OSDs will be saved as a map associating the OSDs uuid with a map consisting of the uuid, the // name and the status page url. This map will be served as JSON. // For example: { "osd-uuid-1": { "uuid": "osd-uuid-1", "name": "OSD Number 1", "status_page_url": "http://osd1.cluster.tld"} } HashMap<String, HashMap<String, String>> osds = new HashMap<String, HashMap<String, String>>(); ResultSet<byte[], byte[]> iter = null; try { // NOTE(jdillmann): Access to the database is not synchronized. This might result in reading stale data. final Database database = master.getDirDatabase(); iter = database.prefixLookup(DIRRequestDispatcher.INDEX_ID_SERVREG, new byte[0], null).get(); while (iter.hasNext()) { Entry<byte[], byte[]> e = iter.next(); final String uuid = new String(e.getKey()); final ServiceRecord sreg = new ServiceRecord(ReusableBuffer.wrap(e.getValue())); if (sreg.getType() == ServiceType.SERVICE_TYPE_OSD) { HashMap<String, String> data = new HashMap<String, String>(); data.put("uuid", sreg.getUuid()); data.put("name", sreg.getName()); for (Entry<String, String> dataEntry : sreg.getData().entrySet()) { if (dataEntry.getKey().equals("status_page_url")) { data.put("status_page_url", dataEntry.getValue()); } } // Add only OSDs with a status_page_url and are not shutdown. if (data.containsKey("status_page_url") && sreg.getLast_updated_s() != 0) { osds.put(sreg.getUuid(), data); } } } String osdsJSON = JSONParser.writeJSON(osds); sendResponse(httpExchange, statusPageTemplate.replace(Vars.OSDSJSON.toString(), osdsJSON)); } catch (BabuDBException ex) { Logging.logError(Logging.LEVEL_WARN, (Object) null, ex); httpExchange.sendResponseHeaders(500, 0); } catch (JSONException ex) { Logging.logError(Logging.LEVEL_WARN, (Object) null, ex); httpExchange.sendResponseHeaders(500, 0); } finally { httpExchange.close(); if (iter != null) { iter.free(); } } } }