これが私が約1週間熱心に攻撃してきた仕事上の問題ですが成功しませんでした。
apache commonsnetFTPClientライブラリを使用してファイルをメインフレームに送信するレガシーJavaコードがあります。このコードは、86Mb未満のファイルに対して完全に機能します。ただし、86Mbを超えるファイルが検出されると、CopyStreamExceptionで失敗します(他の有用な情報はありません)。タイムアウトとCopyStreamListenerを追加しましたが無駄になりました。リスナーは、FTPが86Mbに達するまでデータのバッファーをメインフレームに正常にアップロードしていることを示すいくつかのメッセージを出力します(サンプルログ出力は以下に含まれています)。
当初、問題はネットワーク/ファイアウォールに関連していると思っていましたが(コードに非常に多くのタイムアウト操作が表示される理由です)、メインフレームに送信するスペース割り当てコマンドに関係していることがわかりました。私はここでメインフレームの専門家から支援を受けており、彼はBLKSIZE、SPACE、LRECLなどのさまざまな組み合わせについて多くの提案をしました。しかし、それらのどれもうまくいきませんでした。転送を一度完了させましたが、メインフレームの担当者から、メインフレームで作成されたファイルのブロックサイズとフォーマットのパラメーターが正しくないことが通知されたため、それを破棄する必要がありました(これについて説明します)この場合、以下で機能しました)。
まず、Javaコードは次のとおりです。
public static boolean copyFileThruFTP(
String srcFileName, String remoteFileName, Properties exportProps) {
boolean success = true;
String serverUserName = exportProps.getProperty(WebUtil.FTP_SERVER_USER);
String serverPwd = exportProps.getProperty(WebUtil.FTP_SERVER_PWD);
String serverIp = exportProps.getProperty(WebUtil.FTP_SERVER_IP);
File f = new File(srcFileName);
FTPClient ftpClient = null;
try {
String errorMessage = null;
FileInputStream input = new FileInputStream(f);
ftpClient = new FTPClient();
ftpClient.setDataTimeout(6000000); // 100 minutes
ftpClient.setConnectTimeout(6000000); // 100 minutes
ftpClient.connect(serverIp);
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
errorMessage = "FTP server refused connection: " + ftpClient.getReplyString();
} else {
if (!ftpClient.login(serverUserName,serverPwd)) {
errorMessage = "Failed to copy file thru FTP: login failed.";
} else {
ftpClient.setBufferSize(1024000);
ftpClient.setControlKeepAliveTimeout(30); // sends a keepalive every thirty seconds
if (ftpClient.deleteFile(remoteFileName)) {
log.warn("Deleted existing file from remote server: " + remoteFileName);
}
ftpClient.setFileTransferMode(FTP.ASCII_FILE_TYPE);
ftpClient.setFileType(FTP.ASCII_FILE_TYPE);
ftpClient.sendSiteCommand("RECFM=FB");
ftpClient.sendSiteCommand("LRECL=2000");
ftpClient.sendSiteCommand("BLKSIZE=27000");
//ftpClient.sendSiteCommand("DCB=(RECFM=FB,LRECL=2000,BLKSIZE=26000)");
ftpClient.sendSiteCommand("SPACE=(TRK,(500,500),RLSE)");
OutputStream ftpOut = ftpClient.storeFileStream(remoteFileName);
if (ftpOut == null) {
errorMessage = "FTP server could not open file for write: " + ftpClient.getReplyString();
} else {
OutputStream output = new BufferedOutputStream(ftpOut);
log.warn("copyFileThruFTP calling copyStream() for file: " + f.getAbsolutePath());
Util.copyStream(input, output, ftpClient.getBufferSize(), f.length(),
new CopyStreamAdapter() {
public void bytesTransferred(
long totalBytesTransferred, int bytesTransferred, long streamSize) {
log.warn(bytesTransferred + " bytes written; total: " + totalBytesTransferred + " of " + streamSize);
}
});
input.close();
output.close();
if (!ftpClient.completePendingCommand()) {
errorMessage = "Failed to copy file thru FTP: completePendingCommand failed.";
}
}
}
ftpClient.logout();
ftpClient.disconnect();
ftpClient = null;
}
if (!StringUtils.isEmpty(errorMessage)) {
log.error(errorMessage);
System.out.print(errorMessage);
success = false;
}
} catch (CopyStreamException cse){
cse.printStackTrace();
log.error("Failed to copy file thru FTP (CopyStreamException).", cse);
success = false;
} catch (IOException e){
e.printStackTrace();
log.error("Failed to copy file thru FTP (IOException).", e);
success = false;
} finally {
try {
if (ftpClient != null) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ignore) {}
}
return success;
}
さて、私が言ったように、このコードは86Mb未満のすべてのファイルで非常にうまく機能するので、知識の観点からは役立つかもしれませんが、Javaコーディングスタイルなどのヒントは本当に必要ありません。このメソッドを投稿して、コメントと無関係なコードを削除したので、これをeclipseにコピーして戻したときに何も表示されませんでしたが、構文エラーが1つか2つある可能性があります。私が解決しようとしているのは、このコードが小さなファイルでは機能するが、大きなファイルでは機能しない理由です。
大きなファイルのログ出力のサンプルを次に示します(見た目を良くするために少し変更しました)。
2012-02-29 11:13 WARN - copyFileThruFTP calling copyStream() for file: C:\data\mergedcdi\T0090200.txt
2012-02-29 11:13 WARN - 1024000 bytes; total: 1024000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 2048000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 3072000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 4096000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 5120000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 6144000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 7168000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 8192000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 9216000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 10240000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 11264000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 12288000 of 96580484
2012-02-29 11:13 WARN - 1024000 bytes; total: 13312000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 14336000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 15360000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 16384000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 17408000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 18432000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 19456000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 20480000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 21504000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 22528000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 23552000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 24576000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 25600000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 26624000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 27648000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 28672000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 29696000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 30720000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 31744000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 32768000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 33792000 of 96580484
2012-02-29 11:14 WARN - 1024000 bytes; total: 34816000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 35840000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 36864000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 37888000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 38912000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 39936000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 40960000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 41984000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 43008000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 44032000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 45056000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 46080000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 47104000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 48128000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 49152000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 50176000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 51200000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 52224000 of 96580484
2012-02-29 11:15 WARN - 1024000 bytes; total: 53248000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 54272000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 55296000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 56320000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 57344000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 58368000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 59392000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 60416000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 61440000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 62464000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 63488000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 64512000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 65536000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 66560000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 67584000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 68608000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 69632000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 70656000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 71680000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 72704000 of 96580484
2012-02-29 11:16 WARN - 1024000 bytes; total: 73728000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 74752000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 75776000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 76800000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 77824000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 78848000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 79872000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 80896000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 81920000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 82944000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 83968000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 84992000 of 96580484
2012-02-29 11:17 WARN - 1024000 bytes; total: 86016000 of 96580484
2012-02-29 11:17 ERROR- Failed to copy file thru FTP (CopyStreamException).
org.apache.commons.net.io.CopyStreamException: IOException caught while copying.
at org.apache.commons.net.io.Util.copyStream(Util.java:130)
at org.apache.commons.net.io.Util.copyStream(Util.java:174)
at com.pa.rollupedit.util.WebUtil.copyFileThruFTP(WebUtil.java:1120)
at com.pa.rollupedit.util.CdiBuilder.process(CdiBuilder.java:361)
at com.pa.rollupedit.controller.ExportCDI.doGet(ExportCDI.java:55)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
at com.pa.rollupedit.controller.LoginFilter.doFilter(LoginFilter.java:90)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
at com.pa.rollupedit.util.RequestTimeFilter.doFilter(RequestTimeFilter.java:18)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3496)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
では、メインフレームで何が起こるかを見てみましょう。不完全な送信によって生成されたファイルに関して、メインフレームの担当者から提供された情報は次のとおりです。
Data Set Name . . . . : BSFP.ICEDCDI.SPC10.T0090200
General Data Current Allocation
Management class . . : MCDFLT Allocated tracks . : 1,650
Storage class . . . : SCSTD Allocated extents . : 32
Volume serial . . . : SMS217 +
Device type . . . . : 3390
Data class . . . . . : DCDFLT
Organization . . . : PS Current Utilization
Record format . . . : FB Used tracks . . . . : 1,650
Record length . . . : 2000 Used extents . . . : 32
Block size . . . . : 26000
1st extent tracks . : 100
Secondary tracks . : 50 Dates
Data set name type : Creation date . . . : 2012/02/29
SMS Compressible. . : NO Referenced date . . : 2012/02/29
Expiration date . . : None
レコード長、レコード形式、およびブロックサイズは、私が送信したサイトコマンドに基づいていると予想されるとおりであることに注意してください。ただし、1次トラックと2次トラックは、私には正しくないように見えます。メインフレームの担当者から、約10種類のSPACEコマンドを試してもらいました(ブロックサイズの変更もあります)。レコードサイズは間違いなく2000文字なので、一貫性が保たれています。しかし、これまでのところ、彼の提案はどれもうまくいきませんでした。
私自身、パラメータを設定する別の方法を発見し、ある時点でそれを試しました。これは、コメント化された行としてコードで確認できます。
//ftpClient.sendSiteCommand("DCB=(RECFM=FB,LRECL=2000,BLKSIZE=26000)");
これについて興味深いのは、このコマンドを使用したとき(そして、RECFM / LRECL / BLKSIZEコマンドをコメントアウトしたとき)、ftp送信が成功したことです!! しかし、メインフレームの担当者は、次のリモートファイル情報を共有しました。これは、さまざまなパラメータが正しく設定されていないことを示しています。DCBコマンドがまったく機能しなかったように見えます。
Data Set Name . . . . : BSFP.ICEDCDI.SPC10.T0090200
General Data Current Allocation
Management class . . : MCDFLT Allocated tracks . : 230
Storage class . . . : SCSTD Allocated extents . : 4
Volume serial . . . : SMS195
Device type . . . . : 3390
Data class . . . . . : DCDFLT
Organization . . . : PS Current Utilization
Record format . . . : VB Used tracks . . . . : 230
Record length . . . : 256 Used extents . . . : 4
Block size . . . . : 27000
1st extent tracks . : 100
Secondary tracks . : 50 Dates
Data set name type : Creation date . . . : 2012/02/28
SMS Compressible. . : NO Referenced date . . : 2012/02/29
Expiration date . . : None
言うまでもなく、それは本当に物事にダンパーを置きます。
今朝からの更新:メインフレームの人が他のメインフレームの専門家に連絡しました。そのうちの1人は、SPACEコマンドで「TRK」が正しくないことを伝え、代わりに次を使用しました。
ftpClient.sendSiteCommand("SPACE=(TRA,(PRI=500,SEC=500))");
私はこれを(PRI=やSEC=なしなどの他のバリエーションと一緒に)試しましたが、結果はまったく同じです(つまり、86Mbで失敗します)。
ご覧のとおり、これは些細な質問ではありません。これがネットワークの問題ではないことを確認するために経験した多くの旋回についても詳しく調べていません。この時点で、この問題の原因はメインフレームのサイトコマンドであると約98.6%確信しています。
何かお手伝いいただければ幸いです!!