    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.ArrayList;
    019import java.util.Collections;
    020import java.util.List;
    021
    022import org.opengion.fukurou.util.StringUtil;
    023import org.opengion.hayabusa.common.HybsSystem;
    024
    025/**
    026 * 帳票要求スレッドの本体です。
    027 * 外部からスタックされたキューを先入れ先出しの順番に処理します。
    028 *
    029 * あるキューに対してエラーが発生すると、システムリソースのRETRY_COUNTで設定された回数再処理を試みます。
    030 * この回数分エラーが発生した場合は、そのキューのみがアプリエラーとなります。
    031 *
    032 * このスレッドは一度生成されると、外部から明示的に終了の要求を起こさない限り生存し続けます。
    033 * 終了するには、finish()メソッドを呼び出します。
    034 * このメソッドが呼ばれると、内部でスタックしているキューは全てクリアされるため、その時点で
    035 * 処理されているキューの処理が完了した時点で、スレッドが終了します。
    036 *
    037 * @og.group 帳票システム
    038 *
    039 * @version  4.0
    040 * @author   Hiroki.Nakamura
    041 * @since    JDK1.6
    042 */
    043public class ExecThread extends Thread {
    044
    045        private static enum Status { EXECUTE, WAIT };
    046        private Status state = Status.EXECUTE;
    047
    048        private static final int RETRY_COUNT = HybsSystem.sysInt( "REPORT_RETRY_COUNT" );
    049
    050        private final List<ExecQueue> queues = Collections.synchronizedList( new ArrayList<ExecQueue>() );
    051
    052        private long threadStart        = 0;
    053        private long execStart          = 0;
    054        private long execEnd            = 0;
    055        private final boolean debug;    // 4.3.0.0 (2008/07/15) デバッグの追加
    056
    057        /**
    058         * コンストラクタ
    059         * OOoへの接続を生成します。
    060         *
    061         * @param       id      スレッドID
    062         */
    063        public ExecThread( final String id ) {
    064                // threadStart = System.currentTimeMillis();
    065                // setName( id ); // スタックトレース時にスレッドIDを出すためにセット
    066                this ( id , false );
    067        }
    068
    069        /**
    070         * コンストラクタ
    071         * OOoへの接続を生成します。
    072         *
    073         * @og.rev 4.3.0.0 (2008/07/15) デバッグフラグを追加します。
    074         * @param       id                      スレッドID
    075         * @param       debugFlag       デバッグフラグ[true/false]
    076         */
    077        public ExecThread( final String id , final boolean debugFlag ) {
    078                threadStart = System.currentTimeMillis();
    079                setName( id ); // スタックトレース時にスレッドIDを出すためにセット
    080                debug = debugFlag; // 4.2.5.0 (2008/06/26) デバッグ処理の追加
    081        }
    082
    083        /**
    084         * キューをスタックします。
    085         *
    086         * @og.rev 4.3.0.0 (2008/07/15) debug追加
    087         * @param       queue   ExecQueueオブジェクト
    088         *
    089         * @return      スタックが受け付けられたかどうか
    090         */
    091        public boolean stackQueue( final ExecQueue queue ) {
    092                queue.addMsg( "[INFO]QUEUE STACK:THREAD-ID=" + queue.getThreadId() + ",YKNO=" + queue.getYkno() + HybsSystem.CR );
    093
    094                queues.add( queue );
    095
    096                queue.setExecute();
    097                if( debug ) { queue.addMsg( "[INFO]QUEUE STACKED" + HybsSystem.CR ); }
    098
    099                synchronized( this ) {
    100                        if( state == Status.WAIT ) {
    101                                this.interrupt();
    102                                if( debug ) { queue.addMsg( "[INFO]INTERRUPT" + HybsSystem.CR ); }
    103                        }
    104                }
    105                return true;
    106        }
    107
    108        /**
    109         * スレッド本体
    110         * スタックされたキューを順番に取り出し処理を行います。
    111         */
    112        @Override
    113        public void run() {
    114
    115                while( true ) {
    116
    117                        synchronized( this ) {
    118                                while( queues.isEmpty() ) {
    119                                        try {
    120                                                state = Status.WAIT;
    121                                                wait();
    122                                        }
    123                                        catch( InterruptedException ex ) {
    124                                                state = Status.EXECUTE;
    125                                        }
    126                                }
    127                        }
    128
    129                        ExecQueue queue = popQueue();
    130                        if( queue != null ) {
    131                                if( "_FINALIZE".equals( queue.getYkno() ) ) {
    132                                        if( debug ) { queue.addMsg( "[INFO]END" + HybsSystem.CR ); }
    133                                        break;
    134                                }
    135                                else {
    136                                        if( debug ) { queue.addMsg( "[INFO]QUEUE START" + HybsSystem.CR ); }
    137                                        exec( queue );
    138
    139                                        // System.out.println( queue.getMsg() );
    140                                        System.out.print( queue.getMsg() ); // 4.3.0.0 (2008/07/15)
    141                                }
    142                        }
    143                }
    144        }
    145
    146        /**
    147         * スレッドを終了させるためのキューを追加します。
    148         *
    149         * このメソッドが呼ばれると、内部にスタックしているキューは全てクリアされます。
    150         */
    151        public void finish() {
    152                queues.clear();
    153
    154                ExecQueue qu = new ExecQueue();
    155                qu.setYkno( "_FINALIZE" );
    156                stackQueue( qu );
    157        }
    158
    159        /**
    160         * スレッドを終了させるためのキューを追加します。
    161         *
    162         * このメソッドでは、既にスタックされているキューはクリアされず、全て処理された後で、
    163         * スレッドを終了します。
    164         *
    165         * @og.rev 5.1.6.0 (2010/05/01) 新規作成
    166         */
    167        public void finishAfterExec() {
    168                ExecQueue qu = new ExecQueue();
    169                qu.setYkno( "_FINALIZE" );
    170                stackQueue( qu );
    171        }
    172
    173//      /**
    174//       * 現在処理しているキューの処理時間を返します。
    175//       * スレッドがWAIT状態の場合は、0を返します。
    176//       *
    177//       * @return 処理時間
    178//       */
    179//      public int getExecTime() {
    180//              return ( execStart > execEnd ? (int)(System.currentTimeMillis() - execStart) : 0 );
    181//      }
    182
    183        /**
    184         * 帳票処理を行います。
    185         *
    186         * @og.rev 5.1.2.0 (2010/01/01) 256シートを超えた場合でも、正しく処理できるように対応
    187         *
    188         * @param       queue   ExecQueueオブジェクト
    189         */
    190        private void exec( final ExecQueue queue ) {
    191                execStart = System.currentTimeMillis();
    192
    193                ExecProcess oep = new ExecProcess( queue, debug );
    194                for( int i = 0; i <= RETRY_COUNT; i++ ) {
    195                        try {
    196                                // 5.1.2.0 (2010/01/01) データが終わるまで処理を継続する。
    197                                while( !queue.isEnd() ) {
    198                                        oep.process();
    199                                }
    200                                queue.setComplete();
    201                                break;
    202                        }
    203                        catch( Throwable th ) {
    204                                queue.addMsg( "[ERROR]ERROR OCCURRED!" + HybsSystem.CR );
    205                                queue.addMsg( StringUtil.stringStackTrace( th ) );
    206
    207                                if( i == RETRY_COUNT ) {
    208                                        queue.addMsg( "[ERROR]UPTO RETRY COUNT!" + HybsSystem.CR );
    209                                        queue.setError();
    210                                }
    211                        }
    212                }
    213
    214                execEnd = System.currentTimeMillis();
    215        }
    216
    217        /**
    218         * キューを取り出します。
    219         *
    220         * @return キュー
    221         */
    222        private ExecQueue popQueue() {
    223                return queues.remove( 0 );
    224        }
    225
    226        /**
    227         * このクラスの文字列表現を返します。
    228         *
    229         * @og.rev 4.3.0.0 (2008/07/15) debugを追加
    230         *
    231         * @return 文字列表現
    232         */
    233        @Override
    234        public String toString() {
    235                StringBuilder sb = new StringBuilder();
    236                sb.append( "STATE=" ).append( state.toString() );
    237                sb.append( ", START=" ).append( HybsSystem.getDate( threadStart ) );
    238                sb.append( ", POOL=" ).append( queues.size() );
    239                sb.append( ", EXEC-START=" ).append( HybsSystem.getDate( execStart ) );
    240                sb.append( ", EXEC-END=" ).append( HybsSystem.getDate( execEnd ) );
    241                sb.append( ", DEBUG=" ).append( debug ); // 4.3.0.0 (2008/07/15) デバッグの追加
    242
    243                return sb.toString();
    244        }
    245}