    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         *
    176         * @og.rev 5.1.2.0 (2010/01/01) 256シートを超えた場合でも、正しく処理できるように対応
    177         *
    178         * @param       queue   ExecQueueオブジェクト
    179         */
    180        private void exec( final ExecQueue queue ) {
    181                execStart = System.currentTimeMillis();
    182
    183                ExecProcess oep = new ExecProcess( queue, debug );
    184                for( int i = 0; i <= RETRY_COUNT; i++ ) {
    185                        try {
    186                                // 5.1.2.0 (2010/01/01) データが終わるまで処理を継続する。
    187                                while( !queue.isEnd() ) {
    188                                        oep.process();
    189                                }
    190                                queue.setComplete();
    191                                break;
    192                        }
    193                        catch( Throwable th ) {
    194                                queue.addMsg( "[ERROR]ERROR OCCURRED!" + HybsSystem.CR );
    195                                queue.addMsg( StringUtil.stringStackTrace( th ) );
    196
    197                                if( i == RETRY_COUNT ) {
    198                                        queue.addMsg( "[ERROR]UPTO RETRY COUNT!" + HybsSystem.CR );
    199                                        queue.setError();
    200                                }
    201                        }
    202                }
    203
    204                execEnd = System.currentTimeMillis();
    205        }
    206
    207        /**
    208         * キューを取り出します。
    209         *
    210         * @return キュー
    211         */
    212        private ExecQueue popQueue() {
    213                return queues.remove( 0 );
    214        }
    215
    216        /**
    217         * このクラスの文字列表現を返します。
    218         *
    219         * @og.rev 4.3.0.0 (2008/07/15) debugを追加
    220         *
    221         * @return 文字列表現
    222         */
    223        @Override
    224        public String toString() {
    225                StringBuilder sb = new StringBuilder();
    226                sb.append( "STATE=" ).append( state.toString() );
    227                sb.append( ", START=" ).append( HybsSystem.getDate( threadStart ) );
    228                sb.append( ", POOL=" ).append( queues.size() );
    229                sb.append( ", EXEC-START=" ).append( HybsSystem.getDate( execStart ) );
    230                sb.append( ", EXEC-END=" ).append( HybsSystem.getDate( execEnd ) );
    231                sb.append( ", DEBUG=" ).append( debug ); // 4.3.0.0 (2008/07/15) デバッグの追加
    232
    233                return sb.toString();
    234        }
    235}