⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rrdlogger.java

📁 这是一个以JAVA编写的程序,本人还没有试过,是一个简单的温度控制系统
💻 JAVA
字号:
package net.sf.dz.daemon.logger;import java.io.BufferedReader;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.PrintWriter;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Set;import java.util.TreeSet;import org.freehold.jukebox.conf.Configuration;import org.freehold.jukebox.logger.LogChannel;import org.freehold.jukebox.service.ActiveService;import net.sf.dz.daemon.Server;import net.sf.dz.daemon.ServerModule;import net.sf.dz.daemon.onewire.OneWireServer;import net.sf.dz.daemon.onewire.OneWireContainerListener;import net.sf.dz.daemon.onewire.SwitchContainerListener;import net.sf.dz.daemon.onewire.TemperatureContainerListener;/** * The RRD logger. * * Listens to the notifications and writes them into the trace file and RRD * database. * * <p> * * This class uses <code>Runtime.exec()</code> call to call the actual * <code>rrdtool</code>, which is not the best solution. At the time of * initial implementation, the only alternative was <a * href="http://jrrd.sourceforge.net/" target="_top">jRRD</a>, and it only * supported read operations, which was not exactly what was needed. * * <p> * * Three years later, a viable alternative has eventually arrived, and it is * now implemented as {@link JRobinLogger JRobinLogger}. This class is * retained for version control history only, and may disappear any time, as * soon as <code>JRobinLogger</code> is completely polished. * * @author Copyright &copy; <a href="mailto:vt@freehold.crocodile.org">Vadim Tkachenko</a> 2001-2004 * @version $Id: RRDLogger.java,v 1.7 2004/07/01 06:29:02 vtt Exp $ */public class RRDLogger extends ActiveService implements ServerModule, OneWireContainerListener, TemperatureContainerListener {    public static final LogChannel CH_LOGGER = new LogChannel("Logger/RRD");    /**     * The server we're attached to.     */    protected Server server;        /**     * Set of known device addresses.     *     * @see #deviceArrived     * @see #deviceDeparted     */    protected Set deviceSet = new TreeSet();        /**     * List of device addresses.     *     * This list defines the order in which the data from the devices gets     * logged.     */    private List deviceOrder = new LinkedList();        /**     * Name of device order file.     *     * <p>     *     * It should either be created manually (recommended), or it will be     * automatically created on the first run, if the permissions are set     * properly. If the permissions are not sufficient, the daemon will stop     * working.     *     * <p>     *     * If you decide to let the daemon collect the device addresses, make     * sure it runs long enough so all the devices have time to arrive on     * the bus (usually takes no longer than a minute, in the worst case).     *     * <p>     *     * Also, keep in mind that if the device order file content doesn't     * match with the RRD database structure, we'll screw up logging     * altogether (VT: FIXME: Well, maybe just automate the hell out of it     * anyway?).     */    private String deviceOrderFile;        /**     * This flag is true if the logger is allowed to create or update the     * device order file and regenerate the RRD database when it is     * necessary.     *     * <p>     *     * The default value is <code>true</code>, but be careful - regenerating     * the RRD database may take quite a while.     */    private boolean autocreate = true;        /**     * The data map.     *     * The key is the device address, the value is the last known reading.     */    private Map dataMap = new HashMap();        /**     * The RRD tool location.     */    private String rrdtool;        /**     * The RRD write interval.     *     * The RRD database doesn't like it when the data gets written more     * often than specified at the time of RRD database creation, this is     * why it is necessary.     *     */    private long rrdInterval;        /**     * The RRD database location.     */    private String rrdDB;        /**     * The RRD trace file location.     */    private String rrdTrace;        /**     * The RRD regeneration script location.     */    private String rrdRegenerate;         public void attach(Server server) {            // VT: FIXME: check if attached already and blow up if yes                this.server = server;    }        protected void configure() throws Throwable {            Configuration cf = getConfiguration();        String cfroot = getConfigurationRoot();                autocreate = cf.getBoolean(cfroot + ".rrd_logger.autocreate.enabled", true);                deviceOrderFile = cf.getString(cfroot + ".rrd_logger.device_order");                try {            BufferedReader br = new BufferedReader(new FileReader(deviceOrderFile));                        while ( true ) {                            String line = br.readLine();                                if ( line == null ) {                                    break;                }                                deviceOrder.add(line.trim());            }        } catch ( FileNotFoundException fnfex ) {                    if ( !autocreate ) {                            Throwable t = new IllegalStateException("Autocreate is not enabled, and there's no device order file");                                t.initCause(fnfex);                                throw t;            }                    dumpDeviceOrderFile();        }                if ( deviceOrder.isEmpty() ) {                    complain(LOG_WARNING, CH_LOGGER, "The device order file (" + deviceOrderFile + ") doesn't contain any parseable entries");        }                rrdtool = cf.getString(cfroot + ".rrd_logger.tool");        rrdInterval = cf.getInteger(cfroot + ".rrd_logger.interval");        rrdDB = cf.getString(cfroot + ".rrd_logger.database");        rrdTrace = cf.getString(cfroot + ".rrd_logger.tracefile");        rrdRegenerate = cf.getString(cfroot + ".rrd_logger.regenerate");    }        protected void startup() throws Throwable {            // Check if we're configured        getConfiguration();                if ( server == null ) {                    throw new IllegalStateException("Not attached to the server yet");        }                // Register ourselves with the 1-Wire server[s]                int count = 0;                for ( Iterator i = server.getModuleMap().keySet().iterator(); i.hasNext(); ) {                    Object key = i.next();            Object module = server.getModuleMap().get(key);                        if ( module instanceof OneWireServer ) {                            complain(LOG_INFO, CH_LOGGER, "1-Wire server found as '" + key + "'");                                OneWireServer s = (OneWireServer)module;                count++;                                s.addListener(this);            }        }                if ( count == 0 ) {                    throw new IllegalStateException("OneWireServer has to be defined in the configuration and operable before this module");        }                    }        protected void execute() throws Throwable {            while ( isEnabled() ) {                    Thread.sleep(rrdInterval * 1000);            sync();        }    }    protected void shutdown(Throwable cause) throws Throwable {        }        public synchronized void deviceArrived(String address, String type) {            if (    (!"DS1820".equals(type))             && (!"DS1920".equals(type))             && (!"DS18B20".equals(type)) ) {                         complain(LOG_NOTICE, CH_LOGGER, "I guess we don't care about " + type + "?");            return;        }            deviceSet.add(address);                        if ( !deviceOrder.contains(address) ) {                    if ( autocreate ) {                        deviceOrder.add(address);                                try {                                    dumpDeviceOrderFile();                                    } catch ( IOException ioex ) {                                    // This is not good. Since the device order file                    // couldn't be updated, it doesn't make sense to                    // regenerate RRD.                                        // VT: FIXME: It may even make sense to stop.                                        complain(LOG_WARNING, CH_LOGGER, "Couldn't write device order file", ioex);                    return;                }                                try {                                    // Force an update so there's at least one record for                    // the regenerate script to feed - in case we're                    // processing the first arrival, there's no trace file                    // yet                                        sync();                    regenerateRRD();                                    } catch ( Throwable t ) {                                    // Damn! Now it is all screwed up... Don't even know what to do yet.                                        complain(LOG_ALERT, CH_LOGGER, "Couldn't regenerate RRD - you'll have to check its status...");                    return;                }            } else {                            // Well, they didn't want it, but maybe they'll change their                // mind if they know about it?                                complain(LOG_NOTICE, CH_LOGGER, "Autocreate disabled, device will not be logged: " + address);            }        }    }        public void deviceDeparted(String address) {            deviceSet.remove(address);        dataMap.remove(address);        // VT: FIXME: Make sure we realize the device has departed    }        public void deviceFault(String address, String message) {            // There's nothing we can do here    }        public void currentTemperatureChanged(String address, double temperature) {            dataMap.put(address, new Double(temperature));    }        private synchronized void sync() {            if ( deviceOrder.isEmpty() ) {                    complain(LOG_INFO, CH_LOGGER, "sync(): nothing to write");            return;        }                // Now, let's make sure that we don't write the data twice within        // the RRD allowed interval. If not enough time passed since last        // sync, we'll just wait            try {                    // We should do it rarely enough so the overhead of opening and            // closing the file, as well as running the RRD, is not too bad                        File file = new File(rrdTrace);            boolean append = file.exists() ? true : false;                        FileWriter fw = new FileWriter(rrdTrace, append);            PrintWriter pw = new PrintWriter(fw);                        StringBuffer sb = new StringBuffer();                        // Write the time                        String now = Long.toString(System.currentTimeMillis()/1000);                        sb.append(now);                        // Write the sensor data                        // VT: FIXME: Currently, it processes only the double values.            // Has to be adjusted for the switch state.                        for ( Iterator i = deviceOrder.iterator(); i.hasNext(); ) {                            String address = (String)i.next();                Double value = (Double)dataMap.get(address);                                if ( value != null ) {                                    sb.append(":" + value);                                } else {                                    sb.append(":U");                }            }                        String result = sb.toString();                        complain(LOG_DEBUG, CH_LOGGER, "poll: " + result);                        pw.println(sb);            pw.flush();            fw.flush();            fw.close();                        String command = rrdtool + " update " + rrdDB + " " + result;                        complain(LOG_DEBUG, CH_LOGGER, "Executing '" + command + "'");            complain(LOG_DEBUG, CH_LOGGER, "Error code " + Runtime.getRuntime().exec(command).waitFor());                } catch ( Throwable t ) {                    complain(LOG_ERR, CH_LOGGER, "sync failed, cause:", t);        }    }        /**     * Dump the device order list into the device order file.     */    private synchronized void dumpDeviceOrderFile() throws IOException {            // Let's be paranoid                if ( !autocreate ) {                    throw new IllegalStateException("autocreate is disabled, you idiot");        }            if ( deviceOrder.isEmpty() ) {                    return;        }            PrintWriter pw = new PrintWriter(new FileWriter(deviceOrderFile));                for ( Iterator i = deviceOrder.iterator(); i.hasNext(); ) {                    pw.println(i.next().toString());        }                pw.close();                complain(LOG_INFO, CH_LOGGER, "Written " + deviceOrder.size() + " item[s] into " + deviceOrderFile);    }        private synchronized void regenerateRRD() throws Throwable {            complain(LOG_DEBUG, CH_LOGGER, "Executing '" + rrdRegenerate + "'");                int rc = Runtime.getRuntime().exec(rrdRegenerate).waitFor();        complain(LOG_DEBUG, CH_LOGGER, "Error code " + rc);                if ( rc != 0 ) {                    complain(LOG_WARNING, CH_LOGGER, "Got error code " + rc + " from '" + rrdRegenerate + "'");            return;        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -