/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.hadoop.contrib.failmon; import java.util.Properties; import java.util.Calendar; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; /********************************************************** * This class takes care of the information that needs to be * persistently stored locally on nodes. Bookkeeping is done for the * state of parsing of log files, so that the portion of the file that * has already been parsed in previous calls will not be parsed again. * For each log file, we maintain the byte offset of the last * character parsed in previous passes. Also, the first entry in the * log file is stored, so that FailMon can determine when a log file * has been rotated (and thus parsing needs to start from the * beginning of the file). We use a property file to store that * information. For each log file we create a property keyed by the * filename, the value of which contains the byte offset and first log * entry separated by a SEPARATOR. * **********************************************************/ public class PersistentState { private final static String SEPARATOR = "###"; static String filename; static Properties persData = new Properties(); /** * Read the state of parsing for all open log files from a property * file. * * @param fname the filename of the property file to be read */ public static void readState(String fname) { filename = fname; try { persData.load(new FileInputStream(filename)); } catch (FileNotFoundException e1) { // ignore } catch (IOException e) { e.printStackTrace(); } } /** * Read and return the state of parsing for a particular log file. * * @param fname the log file for which to read the state */ public static ParseState getState(String fname) { String [] fields = persData.getProperty(fname, "null" + SEPARATOR + "0").split(SEPARATOR, 2); String firstLine; long offset; if (fields.length < 2) { System.err.println("Malformed persistent state data found"); Environment.logInfo("Malformed persistent state data found"); firstLine = null; offset = 0; } else { firstLine = (fields[0].equals("null") ? null : fields[0]); offset = Long.parseLong(fields[1]); } return new ParseState(fname, firstLine, offset); } /** * Set the state of parsing for a particular log file. * * @param state the ParseState to set */ public static void setState(ParseState state) { if (state == null) { System.err.println("Null state found"); Environment.logInfo("Null state found"); } persData.setProperty(state.filename, state.firstLine + SEPARATOR + state.offset); } /** * Upadate the state of parsing for a particular log file. * * @param filename the log file for which to update the state * @param firstLine the first line of the log file currently * @param offset the byte offset of the last character parsed */ public static void updateState(String filename, String firstLine, long offset) { ParseState ps = getState(filename); if (firstLine != null) ps.firstLine = firstLine; ps.offset = offset; setState(ps); } /** * Write the state of parsing for all open log files to a property * file on disk. * * @param fname the filename of the property file to write to */ public static void writeState(String fname) { try { persData.store(new FileOutputStream(fname), Calendar.getInstance().getTime().toString()); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } /********************************************************** * This class represents the state of parsing for a particular log * file. * **********************************************************/ class ParseState { public String filename; public String firstLine; public long offset; public ParseState(String _filename, String _firstLine, long _offset) { this.filename = _filename; this.firstLine = _firstLine; this.offset = _offset; } }