/******************************************************************************* * Copyright 2015 alladin-IT GmbH * * Licensed 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. *******************************************************************************/ package at.alladin.rmbt.util.tools; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import org.json.JSONException; import org.json.JSONObject; /** * Tool for running {@link Collector}s, an interface that can be implemented by other classes to create information collectors * @author lb * * @param <T> */ public class InformationCollectorTool { /** * */ final static String TAG = InformationCollectorTool.class.getCanonicalName(); /** * */ final static int PAUSE_BETWEEN_AUTO_EXECUTION_IN_MS = 500; /** * Default timeout. Stops the information collector after this period of ms, if it has not been stopped manually */ final static int DEFAULT_TIMEOUT = 30000; /** * */ final List<CollectorHolder> collectorList = new ArrayList<>(); final TimeUnit deltaTimeUnit; private final AtomicBoolean running = new AtomicBoolean(false); private final AtomicLong timeout = new AtomicLong(DEFAULT_TIMEOUT); public final class CollectorHolder { final Collector<?,?> collector; private long lastUpdate = Long.MIN_VALUE; public CollectorHolder(final Collector<?,?> collector) { this.collector = collector; } public Collector<?,?> getCollector() { return collector; } /** * returns the last update in nanoseconds * @return */ public long getLastUpdateNs() { return lastUpdate; } /** * returns the last update in the time unit defined by the {@link InformationCollectorTool} * @return */ public long getLastUpdate() { return deltaTimeUnit.convert(lastUpdate, TimeUnit.NANOSECONDS); } } /** * * @param timeUnit * @param timeout */ public InformationCollectorTool(final TimeUnit timeUnit, final long timeout) { this.timeout.set(timeout); this.deltaTimeUnit = timeUnit; } /** * * @param timeUnit */ public InformationCollectorTool(final TimeUnit timeUnit) { this(timeUnit, timeUnit.convert(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)); } /** * * @return */ public List<CollectorHolder> getCollectorHolderList() { return collectorList; } /** * * @param collector */ public void addCollector(final Collector<?,?> collector) { collectorList.add(new CollectorHolder(collector)); } /** * * @param collector */ public void removeCollector(final Collector<?,?> collector) { Iterator<CollectorHolder> iterator = collectorList.iterator(); while (iterator.hasNext()) { CollectorHolder holder = iterator.next(); if (holder.collector == collector) { iterator.remove(); } } } public void start(final ExecutorService executor) { final long startTimeNs = System.nanoTime(); if (!this.running.get()) { running.set(true); executor.submit(new Runnable() { public void run() { try { while (InformationCollectorTool.this.running.get()) { update(); Thread.sleep(PAUSE_BETWEEN_AUTO_EXECUTION_IN_MS); final long executingTimeNs = System.nanoTime() - startTimeNs; if (executingTimeNs >= TimeUnit.NANOSECONDS.convert(timeout.get(), deltaTimeUnit)) { System.out.println("Timeout reached. Stopping InformationCollectorTool"); InformationCollectorTool.this.running.set(false); } } } catch (InterruptedException e) { e.printStackTrace(); } running.set(false); } }); } } /** * * @param timeout */ public void setTimeOut(final long timeout) { this.timeout.set(timeout); } /** * * @return */ public long getTimeOut() { return timeout.get(); } /** * */ public void stop() { System.out.println("stopping InformationCollectorTool"); this.running.set(false); } /** * * @return */ public boolean isRunning() { return running.get(); } /** * update all collectors */ public void update() { final long now = System.nanoTime(); try { for (CollectorHolder c : collectorList) { if ((c.lastUpdate + c.collector.getNanoPause()) <= now) { c.collector.update(deltaTimeUnit.convert(now - c.lastUpdate, TimeUnit.NANOSECONDS), deltaTimeUnit); c.lastUpdate = now; } else if (c.lastUpdate <= 0) { c.collector.update(0, deltaTimeUnit); c.lastUpdate = now; } } } catch (Exception e) { e.printStackTrace(); } } /** * * @param jsonObjectName * @return */ public JSONObject getJsonObject(final boolean clean) { return getJsonObject(clean, 0); } /** * * @param clean * @param relativeTimeStamp * @return */ public JSONObject getJsonObject(final boolean clean, long relativeTimeStamp) { try { JSONObject json = new JSONObject(); for (CollectorHolder c : collectorList) { synchronized (c.collector) { json.put(c.collector.getJsonKey(), c.collector.getJsonResult(clean, relativeTimeStamp, deltaTimeUnit)); } } return json; } catch (JSONException e) { e.printStackTrace(); } return null; } }