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