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