package edu.vt.marian.server; import java.io.*; import java.net.*; import java.lang.*; import java.util.*; import edu.vt.marian.common.*; /** class name: log_manager class description: this class manage the log data of the system. uses the services of class(es): designer(s): Jianxin Zhao (jxzhao@csgrad.cs.vt.edu) implementator(s): Ning Chai (nchai@csgrad.cs.vt.edu) finished time: Nov 30th, 1998 known bugs: JDK version: 1.1.5 side effects: */ public class log_manager { public final static int OK = 0; public final static int ALREADY_EXIT = 1; public final static int INVALID_LEVEL = 2; public final static int LOGGING_LEVEL_TOO_LOW = 3; private int logging_level; private String message_separator; private PrintWriter pw; private boolean exit_flag; /** this is just used for debugging */ Debug debug; /** these two variables are used to reduce the disk writing times */ private int writing_count = 0; private int writing_threhold = 100; /** method description: this constructor will create a log manager object from the specified directory uses the services of class(es): input parameter(s): file_name -- this directory contains all the configuration information for log manager, it's also the directory to write log data debug -- used for debugging output parameter(s): none return value: none synchronization: none */ public log_manager(String dir_name, Debug debug) { BufferedReader in_file = null; String line = null; StringTokenizer token_line = null; String s = null; String s1 = null; init(); this.debug = debug; if (dir_name == null) { debug.dumpTrace("Class:log_manager Method:constructor Dir name is null."); exit_flag = true; return; } try { in_file = new BufferedReader(new FileReader(dir_name+"config")); line = in_file.readLine(); while (line != null) { token_line = new StringTokenizer(line," ",false); if (token_line.countTokens() > 1) // in case an empty line is encoutered { // ignore empty lines and lines with only one token s = token_line.nextToken(); if (!s.startsWith("#")) //Ignore comments(begin with "#") { if (s.equals("logging_level")) { s1 = token_line.nextToken(); try { logging_level = Integer.parseInt(s1); if (logging_level < 0) { logging_level = 0; debug.dumpTrace("Class:log_manager Method:constructor logging_level must be greater than 0."); } } catch (Exception e) { logging_level = 0; debug.dumpTrace("Class:log_manager Method:constructor logging_level must be a non-negtive integer."); } } if (s.equals("message_separator")) { message_separator = token_line.nextToken(); } } // end if (!s.startsWith("#")) } //end if (token_line.countTokens() > 1) line = in_file.readLine(); } // end while in_file.close(); } catch (IOException e) { debug.dumpTrace("Class:log_manager Method:constructor File open error."); } try{ FileWriter fw = new FileWriter(dir_name + get_current_file_name()); pw = new PrintWriter(fw); pw.println(message_separator); pw.print("time: "); Date date = new Date(); pw.println(date.toString()); pw.print("Start logging, logging level: "); pw.println(logging_level); pw.flush(); } catch (IOException e) { debug.dumpTrace("Class:log_manager Method:constructor Create PrintWriter error."); exit_flag = true; } return; } /** method description: this method will set the logging level of this object, the higher the level, more detailed the logging uses the services of class(es): none input parameter(s): level -- this will be the new logging level of this log manager output parameter(s): none return value: OK -- the new level has been set ALREADY_EXIT -- the exit_flag is true INVALID_LEVEL -- the new level can't be set since the value is not supported yet synchronization: synchronized */ public synchronized int set_logging_level(int level) { if (exit_flag) { debug.dumpTrace("Class:log_manager Method:set_logging_level exit_flag is already true."); return ALREADY_EXIT; } if (level >= 0) { pw.println(message_separator); pw.print("time: "); Date date = new Date(); pw.println(date.toString()); pw.print("New logging level: "); pw.println(level); // not write disk every time writing_count++; if (writing_count > writing_threhold) { writing_count = 0; pw.flush(); } logging_level = level; return OK; } else { debug.dumpTrace("Class:log_manager Method:set_logging_level Logging level must be an integer greater than 0."); return INVALID_LEVEL; } } /** method description: this method will return the current logging level of this object. uses the services of class(es): none input parameter(s): none output parameter(s): none return value: an integer specifies the current logging level of this object synchronization: none */ public int get_logging_level() { return logging_level; } /** method description: this method will let this object exit smoothly, release resources it occupied andf kill threads it created. uses the services of class(es): input parameter(s): condition -- specifies the condition under which this method is called output parameter(s): none return value: OK -- the exit is smooth ALREADY_EXIT -- the exit_flag is true other -- synchronization: synchronized */ public synchronized int exit(String condition) { if (exit_flag) { debug.dumpTrace("Class:log_manager Method:exit exit_flag is already true."); return ALREADY_EXIT; } pw.println(message_separator); pw.print("time: "); Date date = new Date(); pw.println(date.toString()); pw.println("Stop logging."); pw.print("reason: "); pw.println(condition); pw.flush(); pw.close(); exit_flag = true; return OK; } /** method description: this method will generate a log file name based on the current time, this can guranteen that log files are of different name, so that they are easy to find uses the services of class(es): none input parameter(s): none output parameter(s): none return value: The generated file name as a string synchronization: none */ private String get_current_file_name() { Date date = new Date(); String current_file = new String(Integer.toString(date.getYear() + 1900)+"_" +Integer.toString(date.getMonth() + 1)+"_" +Integer.toString(date.getDate())+"_" +Integer.toString(date.getHours())+"_" +Integer.toString(date.getMinutes())+"_" +Integer.toString(date.getSeconds())); return current_file; } /** method description: this method will process the log data sent by the system uses the services of class(es): input parameter(s): log_level -- the log level of the data sent by source caller_desc -- specify the source send this message message -- the message sent by the source output parameter(s): none return value: OK -- the datd has been logged correctly ALREADY_EXIT -- the exit_flag is true LOGGING_LEVEL_TOO_LOW -- the system's logging_level is lower than requested logging level other -- */ public synchronized int write_log(int log_level, String caller_desc, String message) { if (exit_flag) { debug.dumpTrace("Class:log_manager Method:write_log Exit_flag is already true."); return ALREADY_EXIT; } if (log_level > logging_level) { return LOGGING_LEVEL_TOO_LOW; } pw.println(message_separator); pw.print("time: "); Date date = new Date(); pw.println(date.toString()); pw.print("from: "); pw.println(caller_desc); pw.println(message); // not write disk every time writing_count++; if (writing_count > writing_threhold) { writing_count = 0; pw.flush(); } return OK; } /** method description: this method initialize the data members of this class uses the services of class(es): none input parameter(s): none output parameter(s): none return value: none synchronization: none */ private void init() { debug = null; logging_level = 0; message_separator = new String("====================================="); exit_flag = false; pw = null; return; } }