/** * Copyright 2014 SAP AG * * 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 org.aim.api.measurement.collector; import java.util.Properties; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.aim.api.exceptions.MeasurementException; import org.aim.api.measurement.AbstractRecord; import org.aim.logging.AIMLogger; import org.aim.logging.AIMLoggerFactory; import org.lpe.common.util.system.LpeSystemUtils; /** * The abstract {@link Datacollector} should be the super-class for all data * collectors. * * @author Alexander Wert * */ public abstract class AbstractDataSource implements IDataCollector, IDataReader, Runnable { private static final AIMLogger LOGGER = AIMLoggerFactory.getLogger(AbstractDataSource.class); protected static final int BUFFER_SIZE = 1024; private static final long MILLISECONDS_TO_WAIT = 500; private boolean finished; private static AbstractDataSource dataSource; private boolean enabled = false; /** * Pipe for colelcted records. */ protected final BlockingQueue<AbstractRecord> records = new LinkedBlockingQueue<AbstractRecord>(); /** * Abstract Constructor. * */ public AbstractDataSource() { enabled = false; finished = true; } /** * Processes the record, in particular writing it to the data sink. * * @param record * record to be processed */ protected abstract void process(AbstractRecord record); /** * Cleans up the writer, in particular the data sink. */ protected abstract void cleanUp(); /** * Initializes the data writer. * * @throws MeasurementException * Thrown if initialization fails. */ protected abstract void init() throws MeasurementException; /** * Initializes the data source. * * @param properties * properties to use for initialization */ public abstract void initialize(Properties properties); /** * Repeatedly reads data from the pipe and processes it. */ public void run() { while (enabled || !records.isEmpty()) { try { AbstractRecord record = records.poll(MILLISECONDS_TO_WAIT, TimeUnit.MILLISECONDS); if (record != null) { process(record); } } catch (InterruptedException e) { LOGGER.error("Monitoring error. Reason: {}", e); } } synchronized (this) { enabled = false; this.notifyAll(); } finished = true; } /** * Writes the new record to the pipe. * * @param record * the new record to be collected. */ @Override public void newRecord(AbstractRecord record) { if (!enabled) { return; } boolean ok = records.offer(record); if (!ok) { LOGGER.warn("Writer queue is full. Measurement record ignored!"); } } @Override public void enable() throws MeasurementException { LOGGER.debug("Enabling Data Collector..."); init(); enabled = true; if (finished) { finished = false; LpeSystemUtils.submitTask(this); } LOGGER.debug("Data Collector is running"); } @Override public void disable() { enabled = false; synchronized (this) { while (!records.isEmpty()) { try { this.wait(); } catch (InterruptedException e) { LOGGER.error("Wait for empty queue interrupted. Cause: {}", e.getMessage()); throw new RuntimeException("Wait for empty queue interrupted."); } } } cleanUp(); LOGGER.debug("Data Collector disabled"); } /** * @return the dataCollector */ public static AbstractDataSource getDefaultDataSource() { return dataSource; } /** * * @return Returns true, if data writer has been disabled and has finished * writing data, otherwise returns false; */ public boolean isFinished() { return finished; } /** * @param dataSource * the dataSource to set */ public static void setDefaultDataSource(AbstractDataSource dataSource) { AbstractDataSource.dataSource = dataSource; } }