eu.esdihumboldt.hale.server.status.war.components.memory.MemoryPanel.java Source code

Java tutorial

Introduction

Here is the source code for eu.esdihumboldt.hale.server.status.war.components.memory.MemoryPanel.java

Source

/*
 * Copyright (c) 2012 Data Harmonisation Panel
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     Data Harmonisation Panel <http://www.dhpanel.eu>
 */

package eu.esdihumboldt.hale.server.status.war.components.memory;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior;
import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.resource.JQueryPluginResourceReference;
import org.apache.wicket.util.time.Duration;

/**
 * The main page for the memory view. It contains labels that show the current
 * memory situtation and a self-updating chart showing the memory values of the
 * last 60 seconds.
 * 
 * @author Michel Kraemer
 */
public class MemoryPanel extends Panel {

    private static final long serialVersionUID = 5228052421880544175L;

    /**
     * Default constructor
     * 
     * @param id the component ID
     */
    public MemoryPanel(String id) {
        super(id);

        // calculate start values
        long curMax = Runtime.getRuntime().maxMemory() / 1024 / 1024;
        long curTotal = Runtime.getRuntime().totalMemory() / 1024 / 1024;
        long curUsed = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024;

        // create labels that show the current memory situation (they will be
        // updated via Ajax)
        final Label maxLabel = new Label("max_memory_label", String.valueOf(curMax));
        final Label totalLabel = new Label("total_memory_label", String.valueOf(curTotal));
        final Label usedLabel = new Label("used_memory_label", String.valueOf(curUsed));
        maxLabel.setOutputMarkupId(true);
        totalLabel.setOutputMarkupId(true);
        usedLabel.setOutputMarkupId(true);

        // create a container that redraws itself every second
        WebMarkupContainer redrawContainer = new WebMarkupContainer("redraw_container");
        redrawContainer.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(1)) {

            private static final long serialVersionUID = -5579424950201876034L;

            /**
             * These arrays store the memory values of the last 61 seconds (one
             * second more, because the chart goes from 0 to 60)
             */
            private final long[] maxMemory = new long[61];
            private final long[] totalMemory = new long[61];
            private final long[] usedMemory = new long[61];

            /**
             * Shifts all values in the given array to the right and sets the
             * first entry to the given value
             * 
             * @param arr the array to shift
             * @param val the new value to insert at position 0
             */
            private void updateArray(long[] arr, long val) {
                System.arraycopy(arr, 0, arr, 1, arr.length - 1);
                arr[0] = val;
            }

            /**
             * Creates a string that can be used as plotting data for the memory
             * chart
             * 
             * @param arr the array that contains the memory values of the last
             *            61 seconds
             * @return the plot data string
             */
            private String makePlot(long[] arr) {
                StringBuffer result = new StringBuffer();
                for (int i = 0; i < arr.length; ++i) {
                    if (arr[i] != 0) {
                        if (result.length() > 0) {
                            result.append(",");
                        }
                        result.append("[" + i + "," + arr[i] + "]");
                    }
                }
                return result.toString();
            }

            /**
             * Gets the maximum value from an array
             * 
             * @param arr the array
             * @return the maximum value in <code>arr</code>
             */
            private long getMax(long[] arr) {
                long result = 0;
                for (int i = 0; i < arr.length; ++i) {
                    if (arr[i] > result) {
                        result = arr[i];
                    }
                }
                return result;
            }

            @Override
            protected void onPostProcessTarget(final AjaxRequestTarget target) {
                // get current memory situation
                long curMax = Runtime.getRuntime().maxMemory() / 1024 / 1024;
                long curTotal = Runtime.getRuntime().totalMemory() / 1024 / 1024;
                long curUsed = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024
                        / 1024;

                // update plot data of last 61 seconds
                updateArray(totalMemory, curTotal);
                updateArray(usedMemory, curUsed);

                // create plot data string
                String total = makePlot(totalMemory);
                String free = makePlot(usedMemory);

                // calculate the maximum for the chart's y axis (+ 50 MB)
                long ymax = getMax(totalMemory) + 50;

                // reset labels
                maxLabel.setDefaultModelObject(String.valueOf(curMax));
                totalLabel.setDefaultModelObject(String.valueOf(curTotal));
                usedLabel.setDefaultModelObject(String.valueOf(curUsed));
                target.add(maxLabel);
                target.add(totalLabel);
                target.add(usedLabel);

                // redraw chart
                target.appendJavaScript("chart_plot.axes.xaxis.max = " + (maxMemory.length - 1) + ";"
                        + "chart_plot.axes.yaxis.max = " + ymax + ";" + "chart_plot.series[0].data = [" + total
                        + "];" + "chart_plot.series[1].data = [" + free + "];" + "chart_plot.replot();");
            }
        });
        redrawContainer.add(maxLabel);
        redrawContainer.add(totalLabel);
        redrawContainer.add(usedLabel);
        add(redrawContainer);

        // add a button that performs garbage collection
        AjaxFallbackLink<Object> performGC = new AjaxFallbackLink<Object>("perform-gc") {

            private static final long serialVersionUID = -1411055574233411598L;

            @Override
            public void onClick(AjaxRequestTarget target) {
                System.gc();
            }
        };
        redrawContainer.add(performGC);
    }

    @Override
    public void renderHead(IHeaderResponse response) {
        super.renderHead(response);

        response.render(JavaScriptHeaderItem
                .forReference(new JQueryPluginResourceReference(MemoryPanel.class, "jquery.jqplot.min.js")));
        response.render(
                CssHeaderItem.forReference(new CssResourceReference(MemoryPanel.class, "jquery.jqplot.min.css")));
        response.render(
                JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(MemoryPanel.class, "update.js")));
    }
}