Tuesday, May 22, 2012

The IO operation failed. BINDING.JCA-11096

We are using a JCA FTPAdapter,and occasionally, under load, the FTPMove operation fails:

Unable to delete file '/messages/somefile.xml'; FTP command DELE returned unexpected reply code : 550



WSIF JCA Execute of operation ''FTPMove'' failed due to: The IO operation failed.
The IO operation failed.
The "OPER[NOOP][S->R,T->R]" IO operation for "/messages/somefile.xml" failed.
; nested exception is: 
 BINDING.JCA-11096
The IO operation failed.
The IO operation failed',null,null,null);



Looking in the oracle.tip.adapter.ftp.outbound.FTPIoOperation, I find out that "S->R,T->R" means "Source=Remote, Target=Remote - in fact we are moving files on the remote destination only.


and I see in the logs:

Error deleting file from FTP Server.
Error deleting file from FTP Server.
Unable to delete file from server.
Please ensure whether the remote file has delete permission.

        at oracle.tip.adapter.ftp.FTPClient.deleteFile(FTPClient.java:1362)
        at oracle.tip.adapter.ftp.FTPAgent.deleteFile(FTPAgent.java:736)
        at oracle.tip.adapter.ftp.outbound.FTPIoOperation.deleteFile(FTPIoOperation.java:188)
        at oracle.tip.adapter.ftp.outbound.FTPIoOperation.ioOnly(FTPIoOperation.java:174)


and in this case the code executed is:


if(!alreadyMoved && success && move)
try
{
deleteFile(fs.getSourceAgent(), spec, fInfo);
}
catch(Exception e)
{
throw new FileRetriableResourceException(11096, new Object[] {
(new StringBuilder()).append("OPER[NOOP][").append(mode).append("]").toString(), (new StringBuilder()).append(targetDir).append("/").append(targetFile).toString()
}, e);
}





Error "Please ensure whether the remote file has delete permission" is 11434


The delete is actually done in oracle.tip.adapter.ftp.FTPClient:

public boolean deleteFile(FTPManagedConnection managedConnection, String file)
        throws IOException, ResourceException
    {
        Socket controlSocket = managedConnection.getControlSocket();
        String replyStr = dele(controlSocket, file);
        int rc = getReplyCode(replyStr, m_ftpDesc.ftpHost);
        log((new StringBuilder()).append("FTPClient.deleteFile(): ").append(replyStr).toString(), 102);
        if(!m_ftpReplyValidator.isValidDELEReturnCode(rc))
        {
            log((new StringBuilder()).append("Unable to delete file '").append(file).append("'; ").append("FTP command DELE returned unexpected reply code : ").append(rc).toString(), 100);
            FileResourceException frex = new FileResourceException(11434);
            frex.setEISErrorCode(String.valueOf(rc));
            frex.setEISErrorMessage(replyStr);
            throw frex;
        } else
        {
            return true;
        }
    }

in oracle.tip.adapter.ftp.FTPReply I find out that:

public static final int FILE_UNAVAILABLE = 550;



still no clue on what goes wrong...


I understand that there is a FTP RNTO mode, if you want to enable, specify the JCA activation property UseFtpRenameOperation=true or UseNativeRenameOperation=true.
This will entail using a move() operation rather than a copy followed by a delete (you have to look at FTPIoOperation.ioOnly() method).


PS I discovered after a lot of pain that we were generating twice the same filename on the destination.... not a good idea...

No comments: