1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-20 06:35:50 +02:00

[192610] Fix thread safety for delete(), upload(), setReadOnly() operations

This commit is contained in:
Martin Oberhuber 2007-08-02 12:05:57 +00:00
parent 89d501fd49
commit 0bdec9ed01

View file

@ -55,6 +55,7 @@
* Javier Montalvo Orus (Symbian) - [195830] RSE performs unnecessary remote list commands * Javier Montalvo Orus (Symbian) - [195830] RSE performs unnecessary remote list commands
* Martin Oberhuber (Wind River) - [198638] Fix invalid caching * Martin Oberhuber (Wind River) - [198638] Fix invalid caching
* Martin Oberhuber (Wind River) - [198645] Fix case sensitivity issues * Martin Oberhuber (Wind River) - [198645] Fix case sensitivity issues
* Martin Oberhuber (Wind River) - [192610] Fix thread safety for delete(), upload(), setReadOnly() operations
********************************************************************************/ ********************************************************************************/
package org.eclipse.rse.internal.services.files.ftp; package org.eclipse.rse.internal.services.files.ftp;
@ -359,6 +360,10 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
_userHome = '/'+_userHome.substring(0,_userHome.lastIndexOf(']')); _userHome = '/'+_userHome.substring(0,_userHome.lastIndexOf(']'));
} }
//Just to be safe
synchronized (_fCachePreviousFiles) {
_fCachePreviousFiles.clear();
}
} }
public void disconnect() public void disconnect()
@ -422,6 +427,9 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
/** /**
* Return FTPHostFile object for a given parent dir and file name. * Return FTPHostFile object for a given parent dir and file name.
* This is different than {@link #getFile(String, String, IProgressMonitor)}
* in order to ensure we always return proper FTPHostFile type.
*
* @see org.eclipse.rse.services.files.IFileService#getFile(String, String, IProgressMonitor) * @see org.eclipse.rse.services.files.IFileService#getFile(String, String, IProgressMonitor)
*/ */
protected FTPHostFile getFileInternal(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException protected FTPHostFile getFileInternal(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException
@ -720,7 +728,6 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
bos.close(); bos.close();
if(retValue == true){ if(retValue == true){
setFileType(isBinary);
retValue = upload(tempFile, remoteParent, remoteFile, isBinary, "", hostEncoding, monitor); //$NON-NLS-1$ retValue = upload(tempFile, remoteParent, remoteFile, isBinary, "", hostEncoding, monitor); //$NON-NLS-1$
} }
@ -859,49 +866,50 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
public boolean delete(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException { public boolean delete(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException {
boolean hasSucceeded = false; boolean hasSucceeded = false;
FTPClient ftpClient = getFTPClient();
MyProgressMonitor progressMonitor = new MyProgressMonitor(monitor); MyProgressMonitor progressMonitor = new MyProgressMonitor(monitor);
progressMonitor.init(FTPServiceResources.FTP_File_Service_Deleting_Task+fileName, 1); progressMonitor.init(FTPServiceResources.FTP_File_Service_Deleting_Task+fileName, 1);
IHostFile file = getFile(remoteParent, fileName, monitor); IHostFile file = getFile(remoteParent, fileName, monitor);
boolean isFile = file.isFile(); boolean isFile = file.isFile();
try { if(_commandMutex.waitForLock(monitor, Long.MAX_VALUE)) {
hasSucceeded = FTPReply.isPositiveCompletion(ftpClient.cwd(remoteParent)); try {
FTPClient ftpClient = getFTPClient();
if(hasSucceeded)
{ hasSucceeded = FTPReply.isPositiveCompletion(ftpClient.cwd(remoteParent));
if(isFile)
if(hasSucceeded)
{ {
hasSucceeded = ftpClient.deleteFile(fileName); if(isFile)
{
hasSucceeded = ftpClient.deleteFile(fileName);
}
else
{
hasSucceeded = ftpClient.removeDirectory(fileName);
}
}
if(!hasSucceeded){
throw new Exception(ftpClient.getReplyString()+" ("+fileName+")"); //$NON-NLS-1$ //$NON-NLS-2$
} }
else else
{ {
hasSucceeded = ftpClient.removeDirectory(fileName); progressMonitor.worked(1);
} }
}
if(!hasSucceeded){
throw new Exception(ftpClient.getReplyString()+" ("+fileName+")"); //$NON-NLS-1$ //$NON-NLS-2$
}
else
{
progressMonitor.worked(1);
}
}
catch (Exception e) {
if(isFile){
throw new RemoteFileIOException(e);
}
else{
throw new RemoteFolderNotEmptyException(e);
}
}
catch (Exception e) {
if(isFile){
throw new RemoteFileIOException(e);
}
else{
throw new RemoteFolderNotEmptyException(e);
}
} finally {
_commandMutex.release();
}
} }
return hasSucceeded; return hasSucceeded;
@ -1073,7 +1081,10 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
return true; return true;
} }
/**
* Internal method to list files.
* MUST ALWAYS be called from _commandMutex protected region.
*/
private boolean listFiles(IProgressMonitor monitor) throws Exception private boolean listFiles(IProgressMonitor monitor) throws Exception
{ {
boolean result = true; boolean result = true;
@ -1254,40 +1265,36 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
} }
permissions = userPermissions * 100 + groupPermissions * 10 + otherPermissions; permissions = userPermissions * 100 + groupPermissions * 10 + otherPermissions;
try { if(_commandMutex.waitForLock(monitor, Long.MAX_VALUE)) {
result =_ftpClient.sendSiteCommand("CHMOD "+permissions+" "+file.getAbsolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ try {
} catch (IOException e) { result =_ftpClient.sendSiteCommand("CHMOD "+permissions+" "+file.getAbsolutePath()); //$NON-NLS-1$ //$NON-NLS-2$
result = false; } catch (IOException e) {
} result = false;
} finally {
_commandMutex.release();
}
}
return result; return result;
} }
/** /*
* Gets the input stream to access the contents of a remote file. * (non-Javadoc)
* @since 2.0
* @see org.eclipse.rse.services.files.AbstractFileService#getInputStream(java.lang.String, java.lang.String, boolean, org.eclipse.core.runtime.IProgressMonitor) * @see org.eclipse.rse.services.files.AbstractFileService#getInputStream(java.lang.String, java.lang.String, boolean, org.eclipse.core.runtime.IProgressMonitor)
*/ */
public InputStream getInputStream(String remoteParent, String remoteFile, boolean isBinary, IProgressMonitor monitor) throws SystemMessageException { public InputStream getInputStream(String remoteParent, String remoteFile, boolean isBinary, IProgressMonitor monitor) throws SystemMessageException {
if (monitor != null){ if (monitor != null && monitor.isCanceled()){
throw new RemoteFileCancelledException();
if (monitor.isCanceled()) {
return null;
}
} }
InputStream stream = null; InputStream stream = null;
if(_commandMutex.waitForLock(monitor, Long.MAX_VALUE)) if(_commandMutex.waitForLock(monitor, Long.MAX_VALUE))
{ {
FTPClient ftpClient = getFTPClient(); FTPClient ftpClient = getFTPClient();
try { try {
ftpClient.changeWorkingDirectory(remoteParent); ftpClient.changeWorkingDirectory(remoteParent);
setFileType(isBinary); setFileType(isBinary);
stream = new FTPBufferedInputStream(ftpClient.retrieveFileStream(remoteFile), ftpClient); stream = new FTPBufferedInputStream(ftpClient.retrieveFileStream(remoteFile), ftpClient);
@ -1295,26 +1302,29 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
catch (Exception e) { catch (Exception e) {
throw new RemoteFileIOException(e); throw new RemoteFileIOException(e);
}finally { }finally {
_commandMutex.release(); //TODO I am not 100% sure but I _think_ that the _commandMutex
//may only be released once reading the stream is complete,
//since in FTPBufferedInputStream.close() a pending command
//is being sent.
//After all, the safer solution would be to have a separate
//FTP client connection to the remote for the download, such
//that dir channel remains free. See bug #198636
_commandMutex.release();
} }
} else {
throw new RemoteFileCancelledException();
} }
return stream; return stream;
} }
/** /*
* Gets the output stream to write to a remote file. * (non-Javadoc)
* @since 2.0
* @see org.eclipse.rse.services.files.AbstractFileService#getOutputStream(java.lang.String, java.lang.String, boolean, org.eclipse.core.runtime.IProgressMonitor) * @see org.eclipse.rse.services.files.AbstractFileService#getOutputStream(java.lang.String, java.lang.String, boolean, org.eclipse.core.runtime.IProgressMonitor)
*/ */
public OutputStream getOutputStream(String remoteParent, String remoteFile, boolean isBinary, IProgressMonitor monitor) throws SystemMessageException { public OutputStream getOutputStream(String remoteParent, String remoteFile, boolean isBinary, IProgressMonitor monitor) throws SystemMessageException {
if (monitor != null){ if (monitor != null && monitor.isCanceled()){
throw new RemoteFileCancelledException();
if (monitor.isCanceled()) {
return null;
}
} }
OutputStream stream = null; OutputStream stream = null;