From: <st...@us...> - 2006-11-27 20:02:53
|
Revision: 3664 http://svn.sourceforge.net/smartfrog/?rev=3664&view=rev Author: steve_l Date: 2006-11-27 12:02:48 -0800 (Mon, 27 Nov 2006) Log Message: ----------- Better failure handling on log setup, and the SFprocess has had its signal handler pulled out and bound to by reflection. This may let us run on free JVMs. Modified Paths: -------------- trunk/core/smartfrog/src/org/smartfrog/sfcore/logging/LogToFileImpl.java trunk/core/smartfrog/src/org/smartfrog/sfcore/logging/LogToStreamsImpl.java trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/SFProcess.java Added Paths: ----------- trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/InterruptHandler.java trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/InterruptHandlerImpl.java Modified: trunk/core/smartfrog/src/org/smartfrog/sfcore/logging/LogToFileImpl.java =================================================================== --- trunk/core/smartfrog/src/org/smartfrog/sfcore/logging/LogToFileImpl.java 2006-11-27 00:30:21 UTC (rev 3663) +++ trunk/core/smartfrog/src/org/smartfrog/sfcore/logging/LogToFileImpl.java 2006-11-27 20:02:48 UTC (rev 3664) @@ -26,6 +26,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; +import java.io.FileNotFoundException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; @@ -62,7 +63,8 @@ /** Use date in file name */ boolean datedName = true; /** Used to format date used in filename */ - protected DateFormat fileNameDateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS zzz");; + protected DateFormat fileNameDateFormatter = new SimpleDateFormat( + FILE_DATE_FORMAT); /** Use Log Name in file name */ boolean useLogNameInFileName = true; @@ -78,6 +80,7 @@ /** Append data */ boolean append = true; + private static final String FILE_DATE_FORMAT = "yyyy-MM-dd_HH:mm:ss:SSS_zzz"; /** @@ -97,55 +100,57 @@ * @param componentComponentDescription A component description to overwrite class configuration * @param initialLogLevel level to log at */ - public LogToFileImpl (String name, ComponentDescription componentComponentDescription, Integer initialLogLevel) { - super(name,initialLogLevel); + public LogToFileImpl(String name, + ComponentDescription componentComponentDescription, + Integer initialLogLevel) { + super(name, initialLogLevel); try { - readSFFileAttributes(classComponentDescription); - } catch (SmartFrogException ex1) { - this.error("",ex1); - } - try { - readSFFileAttributes(componentComponentDescription); - } catch (SmartFrogException ex1) { - this.error("",ex1); - } - PrintStream out=null; - try { - logFile = createFile(logFileExtension); - FileOutputStream fos = new FileOutputStream(logFile,append); - out = new PrintStream(fos); - } catch (Exception ex){ - //@todo - ex.printStackTrace(); - } - if (isDebugEnabled() && this.getClass().toString().endsWith("LogToFileImpl")) { - //This will go to the std output. - debug("LogToFileImpl using file name: "+logFile.getAbsolutePath()); - } - setOutstream(out); - if (redirectSystemOutputs){ - try { + readSFFileAttributes(classComponentDescription); + readSFFileAttributes(componentComponentDescription); + PrintStream out = null; + logFile = createFile(logFileExtension); + FileOutputStream fos = new FileOutputStream(logFile, + append); + out = new PrintStream(fos); + if (isDebugEnabled() && this.getClass() + .toString() + .endsWith("LogToFileImpl")) { + //This will go to the std output. + debug("LogToFileImpl using file name: " + logFile.getAbsolutePath()); + } + setOutstream(out); + if (redirectSystemOutputs) { redirectOutputs(); - } catch (Exception ex1) { - ex1.printStackTrace(); } + if (isTraceEnabled() && this.getClass() + .toString() + .endsWith("LogToFileImpl")) { + String msg2 = "Log '" + name + "' " + + "\nusing Class ComponentDescription:\n{" + classComponentDescription + + "}\n, and using Component ComponentDescription:\n{" + componentComponentDescription + "}"; + trace(this.getClass().toString() + " " + msg2); + } +// setLevel(initialLogLevel.intValue()); + } catch (FileNotFoundException ex) { + faultInInitialization(ex); } - if (isTraceEnabled() && this.getClass().toString().endsWith("LogToFileImpl")) { - String msg2 = "Log '"+name+"' "+ - "\nusing Class ComponentDescription:\n{"+classComponentDescription+ - "}\n, and using Component ComponentDescription:\n{"+ componentComponentDescription+"}"; - trace(this.getClass().toString() + " "+msg2); - } -// setLevel(initialLogLevel.intValue()); + } + /** + * Called to handle faults in initialization + * @param thrown + */ + private static void faultInInitialization(Throwable thrown) { + thrown.printStackTrace(); + } /** * Reads optional and mandatory attributes. * @param cd ComponentDescription A component description to read attributes from * @throws SmartFrogException error while reading attributes */ - protected void readSFFileAttributes(ComponentDescription cd) throws SmartFrogException { + protected void readSFFileAttributes(ComponentDescription cd) { if (cd==null) return; //Optional attributes. try { @@ -158,7 +163,8 @@ useHostNameInFileName = cd.sfResolve(ATR_USE_HOST_NAME_IN_FILE_NAME,useHostNameInFileName, false); useProcessNameInFileName = cd.sfResolve(ATR_USE_PROCESS_NAME_IN_FILE_NAME,useProcessNameInFileName, false); try { - fileNameDateFormatter = new SimpleDateFormat(cd.sfResolve(ATR_FILE_NAME_DATE_FORMAT, "yyyy/MM/dd HH:mm:ss:SSS zzz", false)); + fileNameDateFormatter = new SimpleDateFormat(cd.sfResolve(ATR_FILE_NAME_DATE_FORMAT, + FILE_DATE_FORMAT, false)); } catch (Exception ex) { if (this.isErrorEnabled())this.error("fileNameDateFormatter", ex); } @@ -175,19 +181,16 @@ * @return filename * @throws Exception error while creating file */ - public File createFile(String fileExtension) throws Exception { + public File createFile(String fileExtension) { // check the path ends correctly if (!path.endsWith(File.separator)) { path += File.separator; } + //Create new dir if it does not exist + File parentDir = new File(path); + parentDir.mkdirs(); - { - //Create new dir if it does not exist - File parentDir = new File(path); - parentDir.mkdir(); - } - fullLogFileName.append(path); StringBuffer newfileName=new StringBuffer(); @@ -275,7 +278,7 @@ * Redirects system outputs to a file. * @throws Exception if any io error */ - public void redirectOutputs() throws Exception { + public void redirectOutputs() throws FileNotFoundException { PrintStream originalOut = System.out; PrintStream originalErr = System.err; @@ -306,10 +309,7 @@ // Redirecting output System.setOut(newOut); // Redirecting err - if (errToOut) - System.setErr(newOut); - else - System.setErr(newErr); + System.setErr(errToOut?newOut:newErr); } catch (Exception e) { System.setOut(originalOut); System.setErr(originalErr); Modified: trunk/core/smartfrog/src/org/smartfrog/sfcore/logging/LogToStreamsImpl.java =================================================================== --- trunk/core/smartfrog/src/org/smartfrog/sfcore/logging/LogToStreamsImpl.java 2006-11-27 00:30:21 UTC (rev 3663) +++ trunk/core/smartfrog/src/org/smartfrog/sfcore/logging/LogToStreamsImpl.java 2006-11-27 20:02:48 UTC (rev 3664) @@ -271,7 +271,9 @@ * @param outstream output stream to log to */ public void setOutstream(PrintStream outstream) { - assert(outstream != null); + if (outstream == null) { + throw new IllegalArgumentException("Null outstream passed down"); + } this.outstream = outstream; } @@ -282,6 +284,9 @@ */ public void setErrstream(PrintStream errstream) { assert(errstream != null); + if(errstream==null) { + throw new IllegalArgumentException("Null errorstream passed down"); + } this.errstream = errstream; } Added: trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/InterruptHandler.java =================================================================== --- trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/InterruptHandler.java (rev 0) +++ trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/InterruptHandler.java 2006-11-27 20:02:48 UTC (rev 3664) @@ -0,0 +1,20 @@ +package org.smartfrog.sfcore.processcompound; + +import org.smartfrog.sfcore.logging.LogSF; + +/** + * Interface used to decouple a Sun-JVM-only class from the rest of the system. + */ +public interface InterruptHandler { + + + /** + * bind to a signal. On HP-UX+cruise control this fails with an error, + * one we don't see on the command line. + * This handler catches the exception and logs it, so that smartfrog + * keeps running even if graceful shutdown is broken. + * @param name name of interrupt to bind to. + * @param log + */ + void bind(String name, LogSF log); +} Added: trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/InterruptHandlerImpl.java =================================================================== --- trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/InterruptHandlerImpl.java (rev 0) +++ trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/InterruptHandlerImpl.java 2006-11-27 20:02:48 UTC (rev 3664) @@ -0,0 +1,75 @@ +package org.smartfrog.sfcore.processcompound; + +import sun.misc.SignalHandler; +import sun.misc.Signal; +import org.smartfrog.sfcore.prim.TerminationRecord; +import org.smartfrog.sfcore.common.ExitCodes; +import org.smartfrog.sfcore.logging.LogSF; + +import java.rmi.RemoteException; + +/** + * signal handler for control-C events + * This is not portable to Non-Sun runtimes (like gcj), because it extends + * a sun.misc method. + */ +class InterruptHandlerImpl implements SignalHandler,InterruptHandler { + + private SignalHandler oldHandler; + protected LogSF log; + + public InterruptHandlerImpl() { + } + + public void handle(Signal sig) { + if (!SFProcess.markProcessCompoundTerminated()) { + if (SFProcess.processCompound != null) { + try { + //Logger.log("Terminating sfDaemon gracefully!!"); + log.out("Terminating sfDaemon gracefully!!"); + SFProcess.processCompound.sfTerminate(new TerminationRecord(TerminationRecord.NORMAL, + "sfDaemon forced to terminate ", + SFProcess.processCompound.sfCompleteName())); + } catch (RemoteException re) { + //Logger.log(re); + //log and ignore + if (log.isIgnoreEnabled()) { + log.ignore(re); + } + + } catch (Throwable thr) { + //Logger.log(thr); + if (log.isIgnoreEnabled()) { + log.ignore(thr); + } + } + } + } else { + //Logger.log("sfDaemon killed!"); + log.out("sfDaemon killed!"); + //http://www.tldp.org/LDP/abs/html/exitcodes.html + // 130 - Control-C is fatal error signal 2, (130 = 128 + 2) + ExitCodes.exitWithError(ExitCodes.EXIT_ERROR_CODE_CRTL_ALT_DEL); + } + } + + /** + * bind to a signal. On HP-UX+cruise control this fails with an error, + * one we dont see on the command line. + * This handler catches the exception and logs it, so that smartfrog + * keeps running even if graceful shutdown is broken. + * @param name name of interrupt to bind to. + * @param log + */ + public void bind(String name, LogSF log) { + this.log=log; + try { + oldHandler=Signal.handle(new Signal(name), this); + } catch (IllegalArgumentException e) { + //this happens when binding fails. In this situation, warn, but keep going + this.log.err("Failed to set control-C handler -is JVM running with -Xrs set?",e); +// Logger.log("Failed to set control-C handler -is JVM running with -Xrs set?"); +// Logger.log(e); + } + } +} Modified: trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/SFProcess.java =================================================================== --- trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/SFProcess.java 2006-11-27 00:30:21 UTC (rev 3663) +++ trunk/core/smartfrog/src/org/smartfrog/sfcore/processcompound/SFProcess.java 2006-11-27 20:02:48 UTC (rev 3664) @@ -35,9 +35,6 @@ import org.smartfrog.sfcore.prim.TerminationRecord; import org.smartfrog.sfcore.reference.Reference; import org.smartfrog.sfcore.security.SFClassLoader; -import org.smartfrog.sfcore.common.ExitCodes; -import sun.misc.Signal; -import sun.misc.SignalHandler; import java.net.InetAddress; import java.net.UnknownHostException; @@ -45,10 +42,10 @@ import java.util.Enumeration; import java.util.Properties; import java.rmi.ConnectException; +import java.lang.reflect.Constructor; import org.smartfrog.sfcore.logging.LogFactory; import org.smartfrog.sfcore.logging.LogSF; -import org.smartfrog.Version; /** @@ -91,8 +88,8 @@ */ protected static final Reference refProcessCompound = new Reference( "ProcessCompound"); + private static final String INTERRUPT_HANDLER = "org.smartfrog.sfcore.processcompound.InterruptHandlerImpl"; - // /** ProcessLog. This log is used to log into the core log: SF_CORE_LOG // * It can be replaced using sfSetLog() // */ @@ -110,7 +107,7 @@ * * @throws Exception if failed to set root locator */ - public synchronized static void setRootLocator(RootLocator c) throws Exception { + public static synchronized void setRootLocator(RootLocator c) throws Exception { if (rootLocator != null) { throw new Exception("Root locator already set"); } @@ -126,7 +123,7 @@ * * @throws Exception if failed to set process compound */ - public synchronized static void setProcessCompound (ProcessCompound pc) throws Exception { + public static synchronized void setProcessCompound (ProcessCompound pc) throws Exception { if (processCompound != null) { throw new Exception("ProcessCompound already set"); } @@ -146,7 +143,7 @@ * @throws SmartFrogDeploymentException In case of any error while * deploying the component */ - public synchronized static RootLocator getRootLocator() + public static synchronized RootLocator getRootLocator() throws SmartFrogException, RemoteException { String className = null; @@ -274,68 +271,34 @@ } } - private static boolean processCompoundTerminated = false; /** - * signal handler for control-C events + * Flag that indicates the process is terminated */ - private static class InterruptHandler implements SignalHandler { + private static volatile boolean processCompoundTerminated = false; - private SignalHandler oldHandler; - public void handle(Signal sig) { - if (!processCompoundTerminated) { - processCompoundTerminated = true; - if (processCompound != null) { - try { - //Logger.log("Terminating sfDaemon gracefully!!"); - sfLog().out("Terminating sfDaemon gracefully!!"); - processCompound.sfTerminate(new TerminationRecord(TerminationRecord.NORMAL, - "sfDaemon forced to terminate ", - ((Prim) processCompound).sfCompleteName())); - } catch (RemoteException re) { - //Logger.log(re); - //log and ignore - if (sfLog().isIgnoreEnabled()) { - sfLog().ignore(re); - } + /** + * Flag that indicates the process is terminated + * @return the current flag value + */ + static boolean isProcessCompoundTerminated() { + return processCompoundTerminated; + } - } catch (Throwable thr) { - //Logger.log(thr); - if (sfLog().isIgnoreEnabled()) { - sfLog().ignore(thr); - } - } - } - } else { - //Logger.log("sfDaemon killed!"); - sfLog().out("sfDaemon killed!"); - //http://www.tldp.org/LDP/abs/html/exitcodes.html - // 130 - Control-C is fatal error signal 2, (130 = 128 + 2) - ExitCodes.exitWithError(ExitCodes.EXIT_ERROR_CODE_CRTL_ALT_DEL); - } + /** + * Sets processCompoundTerminated to true, and returns its + * previous value, in a synchronized operation + * @return the previous value. + */ + static synchronized boolean markProcessCompoundTerminated() { + boolean isTerminated=processCompoundTerminated; + if(!isTerminated) { + processCompoundTerminated=true; } - - /** - * bind to a signal. On HP-UX+cruise control this fails with an error, - * one we dont see on the command line. - * This handler catches the exception and logs it, so that smartfrog - * keeps running even if graceful shutdown is broken. - * @param name name of interrupt to bind to. - */ - public void bind(String name) { - try { - oldHandler=Signal.handle(new Signal(name), this); - } catch (IllegalArgumentException e) { - //this happens when binding fails. In this situation, warn, but keep going - sfLog().err("Failed to set control-C handler -is JVM running with -Xrs set?",e); -// Logger.log("Failed to set control-C handler -is JVM running with -Xrs set?"); -// Logger.log(e); - } - } + return isTerminated; } - /** * Deploys the local process compound, if not already there * @@ -352,9 +315,17 @@ } - //conditionally add a shutdown hook + //conditionally add a shutdown hook when the JVM permits it if (addShutdownHook) { - new InterruptHandler().bind("INT"); + try { + Class irqHandlerClass = Class.forName(INTERRUPT_HANDLER); + Constructor constructor = irqHandlerClass.getConstructor(new Class[0]); + InterruptHandler handler=(InterruptHandler) constructor.newInstance(new Object[0]); + handler.bind("INT", sfLog()); + } catch (Exception e) { + sfLog().error("Could not create an interrupt handler from "+ INTERRUPT_HANDLER + +"\nSmartFrog may be running on a JVM which does not support this feature",e); + } } ComponentDescription descr = (ComponentDescription) getProcessCompoundDescription().copy(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |