001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.report2;
017
018import java.util.HashMap;
019import java.util.Map;
020
021/**
022 * 帳票処理を行う各スレッドを管理するクラスです。
023 *
024 * 各スレッドは、内部的にプールされます。
025 * スレッドのIDはOOoQueue#getThreadId()で返される値です。
026 * スレッドが生成されるタイミングは、そのIDで初めてスタック要求が来た(insertQueue()が呼ばれた)時です。
027 *
028 * 指定のスレッドを終了するには、funishThread( key )を呼び出します。
029 * 全てのスレッドを終了するには、funishAllThreads()を呼び出します。
030 *
031 * 現時点での実装では、生成されたスレッドに対しての監視は行っていません。
032 * これは、特定のスレッドがフリーズした際、外部から強制終了を行おうとすると、
033 * 監視スレッドもフリーズしてしまう問題があるためです。
034 * (但し、1つのsoffice.binのプロセスに対してシリアルに対して処理している限りでは、
035 *  フリーズ問題は発生しないようです)
036 *
037 * @og.group 帳票システム
038 *
039 * @version  4.0
040 * @author   Hiroki.Nakamura
041 * @since    JDK1.6
042 */
043public final class ExecThreadManager {
044
045        /**
046         * スレッドプール
047         */
048        private static final Map<String, ExecThread>      pool    = new HashMap<String, ExecThread>();
049        private static boolean debug    = false; // 4.3.0.0 (2008/07/15) デバッグ追加
050
051//      /**
052//       * チェックスレッドの実行間隔
053//       */
054//      private static final int REPORT_THREAD_CHECK_INTERVAL = 1000 * 2;
055
056//      /**
057//       * OOoがクラッシュしていると判断される停止時間
058//       */
059//      private static final int REPORT_THREAD_CRASH_TIME = 1000 * 2;
060
061//      /**
062//       * チェック用のスレッドを開始します
063//       */
064//      static {
065//              checkThreads();
066//      }
067
068        /**
069         * オブジェクトの生成を禁止します
070         */
071        private ExecThreadManager() {}
072
073        /**
074         * キューを該当するスレッドにスタックする
075         *
076         * @og.rev 4.3.0.0 (2008/07/15) スレッドIDにシステムIDを付加
077         *
078         * @param       queue   ExecQueueオブジェクト
079         */
080        public static void insertQueue( final ExecQueue queue ) {
081                // 4.3.3.6 (2008/11/15) この部分は不要なので元に戻します
082                ExecThread oet = getExecThread( queue.getThreadId() );
083//              ExecThread oet = getExecThread( queue.getSystemId() + "_" + queue.getThreadId() ); // 4.3.0.0 (2008/07/15) システムIDをスレッドIDに付加します。
084                oet.stackQueue( queue );
085        }
086
087        /**
088         * キューを該当するスレッドにスタックする
089         *
090         * このメソッドでは、既に同じスレッドが存在するかどうかをチェックせずに必ず
091         * 新しいスレッドを生成し、キューを処理します。
092         * また、処理が完了した後、そのスレッドは、WAITすることなく終了します。
093         *
094         * @og.rev 5.1.6.0 (2010/05/01) 新規作成
095         *
096         * @param       queue   ExecQueueオブジェクト
097         */
098        public static void insertQueueOnNewThread( final ExecQueue queue ) {
099                ExecThread oet = new ExecThread( queue.getThreadId(), debug );
100                oet.start();
101                System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + queue.getThreadId() );
102                oet.stackQueue( queue );
103                oet.finishAfterExec();
104        }
105
106        /**
107         * 該当するスレッドIDを持つスレッドを取得します。
108         * スレッドプールに存在しない場合は、新規に作成されます。
109         *
110         * @param       threadId        スレッドID
111         *
112         * @return      ExecThreadスレッド
113         */
114        private static ExecThread getExecThread( final String threadId ) {
115                ExecThread oet = null;
116                synchronized( pool ) {
117                        oet = pool.get( threadId );
118
119                        // スレッドが終了している場合は、再度作成
120                        if( oet != null && !oet.isAlive() ) {
121                                pool.remove( threadId );
122                                oet = null;
123                        }
124
125                        if( oet == null ) {
126                                // oet = new ExecThread( threadId );
127                                oet = new ExecThread( threadId, debug );
128                                oet.start();
129                                System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + threadId );
130                                pool.put( threadId, oet );
131                        }
132                }
133
134                return oet;
135        }
136
137        /**
138         * 全てのスレッドを終了します。
139         *
140         */
141        public static void finishAllThreads() {
142                synchronized( pool ) {
143                        for( ExecThread oet : pool.values() ) {
144                                oet.finish();
145                        }
146                        pool.clear();
147                        System.out.println( "[INFO]ALL THREADS FINISHED" );
148                }
149        }
150
151        /**
152         * 指定のスレッドを終了します。
153         *
154         * @param threadId スレッドID
155         */
156        public static void finishThread( final String threadId ) {
157                synchronized( pool ) {
158                        ExecThread oet = pool.remove( threadId );
159                        if( oet != null ) {
160                                oet.finish();
161                                System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + threadId );
162                        }
163                }
164        }
165
166        /**
167         * スレッド情報のマップを返します。
168         *
169         * @return      スレッド情報のマップ
170         */
171        public static Map<String, String> getThreadInfo() {
172                Map<String, String> info = new HashMap<String, String>();
173                synchronized( pool ) {
174                        for( Map.Entry<String, ExecThread> entry : pool.entrySet() ) {
175                                info.put( entry.getKey(), entry.getValue().toString() );
176                        }
177                }
178                return info;
179        }
180
181        /**
182         * デバッグフラグの設定
183         *
184         * @og.rev  4.3.0.0 (2008/07/15) デバッグ追加
185         *
186         * @param   flag デバッグフラグ [true:デバッグ/false:通常]
187         */
188        public static void setDebug ( final boolean flag ){
189                debug = flag;
190        }
191
192//      /**
193//       * 監視用のスレッドを開始します。
194//       *
195//       */
196//      private static void checkThreads() {
197//              new Thread() {
198//                      public void run() {
199//
200//                              while( true ) {
201//                                      try {
202//                                              Thread.sleep( REPORT_THREAD_CHECK_INTERVAL );
203//                                      }
204//                                      catch( InterruptedException e ) {}
205//
206//                                      synchronized( pool ) {
207//                                              for( Map.Entry<String, ExecThread> entry : pool.entrySet() ) {
208//                                                      String id = entry.getKey();
209//                                                      ExecThread oet = entry.getValue();
210//
211//                                                      System.out.println(oet.getExecTime());
212//
213//                                                      if( oet.getExecTime() > REPORT_THREAD_CRASH_TIME ) {
214//                                                              System.out.println( "【監視】スレッドID=" + id + "がクラッシュしている可能性がありますので、割込要求を発行します。(処理時間=" + String.valueOf( oet.getExecTime() ) + ")" );
215//                                                              oet.interrupt();
216//                                                      }
217//                                              }
218//                                      }
219//                              }
220//
221//                      }
222//              }.start();
223//      }
224
225}