View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package openr66.protocol.utils;
22  
23  import goldengate.common.logging.GgInternalLogger;
24  import goldengate.common.logging.GgInternalLoggerFactory;
25  
26  import java.util.Map;
27  import java.util.Timer;
28  import java.util.TimerTask;
29  
30  import openr66.protocol.configuration.Configuration;
31  
32  import org.jboss.netty.util.internal.SystemPropertyUtil;
33  
34  import sun.misc.Signal;
35  import sun.misc.SignalHandler;
36  
37  /**
38   * Signal Handler to allow trapping signals.
39   *
40   * @author Frederic Bregier
41   */
42  public class OpenR66SignalHandler implements SignalHandler {
43      /**
44       * Set if the program is in shutdown
45       */
46      private static volatile boolean shutdown = false;
47  
48      /**
49       * Set if the program is in shutdown
50       */
51      private static volatile boolean immediate = false;
52  
53      /**
54       * Set if the Handler is initialized
55       */
56      private static boolean initialized = false;
57  
58      /**
59       * Previous Handler
60       */
61      private SignalHandler oldHandler = null;
62  
63      /**
64       * Says if the Process is currently in shutdown
65       *
66       * @return True if already in shutdown
67       */
68      public static boolean isInShutdown() {
69          return shutdown;
70      }
71  
72      /**
73       * This function is the top function to be called when the process is to be
74       * shutdown.
75       *
76       * @param immediateSet
77       */
78      public static void terminate(boolean immediateSet) {
79          if (immediateSet) {
80              immediate = immediateSet;
81          }
82          terminate();
83      }
84  
85      /**
86       * Print stack trace
87       * @param thread
88       * @param stacks
89       */
90      static public void printStackTrace(Thread thread, StackTraceElement[] stacks) {
91          System.err.print(thread.toString() + " : ");
92          for (int i = 0; i < stacks.length-1; i++) {
93              System.err.print(stacks[i].toString()+" ");
94          }
95          if (stacks.length >= 1)
96              System.err.println(stacks[stacks.length-1].toString());
97      }
98  
99      /**
100      * Finalize resources attached to handlers
101      *
102      * @author Frederic Bregier
103      */
104     public static class R66TimerTask extends TimerTask {
105         /**
106          * Internal Logger
107          */
108         private static final GgInternalLogger logger = GgInternalLoggerFactory
109                 .getLogger(R66TimerTask.class);
110 
111         /**
112          * EXIT type (System.exit(1))
113          */
114         public static final int TIMER_EXIT = 1;
115 
116         /**
117          * Type of execution in run() method
118          */
119         private final int type;
120 
121         /**
122          * Constructor from type
123          *
124          * @param type
125          */
126         public R66TimerTask(int type) {
127             this.type = type;
128         }
129 
130         @Override
131         public void run() {
132             switch (type) {
133                 case TIMER_EXIT:
134                     logger.error("System will force EXIT");
135                     Map<Thread, StackTraceElement[]> map = Thread
136                             .getAllStackTraces();
137                     for (Thread thread: map.keySet()) {
138                         printStackTrace(thread, map.get(thread));
139                     }
140                     System.exit(0);
141                     break;
142                 default:
143                     logger.error("Type unknown in TimerTask");
144             }
145         }
146     }
147 
148     /**
149      * Function to terminate IoSession and Connection.
150      */
151     private static void terminate() {
152         shutdown = true;
153         if (immediate) {
154             ChannelUtils.exit();
155             // Force exit!
156             try {
157                 Thread.sleep(Configuration.configuration.TIMEOUTCON);
158             } catch (InterruptedException e) {
159             }
160             Map<Thread, StackTraceElement[]> map = Thread
161                 .getAllStackTraces();
162             for (Thread thread: map.keySet()) {
163                 printStackTrace(thread, map.get(thread));
164             }
165             try {
166                 Thread.sleep(1000);
167             } catch (InterruptedException e) {
168             }
169             System.err.println("Halt System");
170             Runtime.getRuntime().halt(0);
171         } else {
172             launchFinalExit();
173             immediate = true;
174             ChannelUtils.exit();
175             System.err.println("Exit System");
176             //System.exit(0);
177         }
178     }
179     
180     public static void launchFinalExit() {
181         Timer timer = new Timer("R66FinalExit", true);
182         R66TimerTask timerTask = new R66TimerTask(R66TimerTask.TIMER_EXIT);
183         timer.schedule(timerTask, Configuration.configuration.TIMEOUTCON * 3);
184     }
185 
186     /**
187      * Function to initialized the SignalHandler
188      */
189     public static void initSignalHandler() {
190         if (initialized) {
191             return;
192         }
193         Signal diagSignal = new Signal("TERM");
194         OpenR66SignalHandler diagHandler = new OpenR66SignalHandler();
195         diagHandler.oldHandler = Signal.handle(diagSignal, diagHandler);
196         // Not on WINDOWS ?
197         Configuration.ISUNIX = (!System.getProperty("os.name")
198                 .toLowerCase().startsWith("win"));
199         System.out.println("ISUNIX: "+Configuration.ISUNIX);
200         if (Configuration.ISUNIX) {
201             String vendor = SystemPropertyUtil.get("java.vm.vendor");
202             vendor = vendor.toLowerCase();
203             if (vendor.indexOf("ibm") >= 0) {
204                 diagSignal = new Signal("USR1");
205                 diagHandler = new OpenR66SignalHandler();
206                 diagHandler.oldHandler = Signal.handle(diagSignal, diagHandler);
207             }
208         }
209         initialized = true;
210     }
211 
212     /**
213      * Handle signal
214      *
215      * @param signal
216      */
217     public void handle(Signal signal) {
218         try {
219             terminate();
220             // Chain back to previous handler, if one exists
221             if (oldHandler != SIG_DFL && oldHandler != SIG_IGN) {
222                 oldHandler.handle(signal);
223             }
224         } catch (final Exception e) {
225         }
226         //ChannelUtils.stopLogger();
227         System.err.println("Signal: "+signal.getNumber());
228         System.exit(0);
229     }
230 }