1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-19 22:25:52 +02:00

Use Mutex to avoid parallel FTP directory queries

This commit is contained in:
Martin Oberhuber 2006-08-17 10:21:06 +00:00
parent ec66da7bf4
commit 003e578773

View file

@ -36,6 +36,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.rse.services.Mutex;
import org.eclipse.rse.services.clientserver.NamePatternMatcher; import org.eclipse.rse.services.clientserver.NamePatternMatcher;
import org.eclipse.rse.services.clientserver.messages.SystemMessageException; import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
import org.eclipse.rse.services.files.AbstractFileService; import org.eclipse.rse.services.files.AbstractFileService;
@ -50,6 +51,9 @@ import sun.net.ftp.FtpClient;
public class FTPService extends AbstractFileService implements IFileService, IFTPService public class FTPService extends AbstractFileService implements IFileService, IFTPService
{ {
private FTPClientService _ftpClient; private FTPClientService _ftpClient;
private Mutex _mutex = new Mutex();
private long _mutexTimeout = 5000; //max.5 seconds to obtain dir channel
private String _userHome; private String _userHome;
private IFTPDirectoryListingParser _ftpPropertiesUtil; private IFTPDirectoryListingParser _ftpPropertiesUtil;
@ -151,6 +155,7 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
public IHostFile getFile(IProgressMonitor monitor, String remoteParent, String fileName) public IHostFile getFile(IProgressMonitor monitor, String remoteParent, String fileName)
{ {
//No Mutex lock needed here because internalFetch() does the lock
IHostFile[] matches = internalFetch(monitor, remoteParent, fileName, FILE_TYPE_FILES_AND_FOLDERS); IHostFile[] matches = internalFetch(monitor, remoteParent, fileName, FILE_TYPE_FILES_AND_FOLDERS);
if (matches != null && matches.length > 0) if (matches != null && matches.length > 0)
{ {
@ -174,44 +179,51 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
} }
NamePatternMatcher filematcher = new NamePatternMatcher(fileFilter, true, true); NamePatternMatcher filematcher = new NamePatternMatcher(fileFilter, true, true);
List results = new ArrayList(); List results = new ArrayList();
try if (_mutex.waitForLock(monitor, _mutexTimeout))
{ {
FtpClient ftp = getFTPClient();
try try
{ {
ftp.noop(); FtpClient ftp = getFTPClient();
try
{
ftp.noop();
}
catch (Exception e)
{
//e.printStackTrace();
disconnect();
// probably timed out
reconnect();
ftp = getFTPClient();
}
ftp.cd(parentPath);
TelnetInputStream stream = ftp.list();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line = reader.readLine();
while (line != null)
{
FTPHostFile node = getDirListingParser().getFTPHostFile(line, parentPath);
if (node != null && filematcher.matches(node.getName()))
{
if (isRightType(fileType, node))
{
results.add(node);
}
}
line = reader.readLine();
}
} }
catch (Exception e) catch (Exception e)
{ {
//e.printStackTrace(); e.printStackTrace();
disconnect();
// probably timed out
reconnect();
ftp = getFTPClient();
} }
finally
ftp.cd(parentPath);
TelnetInputStream stream = ftp.list();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line = reader.readLine();
while (line != null)
{ {
FTPHostFile node = getDirListingParser().getFTPHostFile(line, parentPath); _mutex.release();
if (node != null && filematcher.matches(node.getName()))
{
if (isRightType(fileType, node))
{
results.add(node);
}
}
line = reader.readLine();
} }
} }
catch (Exception e)
{
e.printStackTrace();
}
return (IHostFile[])results.toArray(new IHostFile[results.size()]); return (IHostFile[])results.toArray(new IHostFile[results.size()]);
} }
@ -271,50 +283,57 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
public boolean download(IProgressMonitor monitor, String remoteParent, String remoteFile, File localFile, boolean isBinary, String hostEncoding) public boolean download(IProgressMonitor monitor, String remoteParent, String remoteFile, File localFile, boolean isBinary, String hostEncoding)
{ {
FtpClient ftp = getFTPClient(); if (_mutex.waitForLock(monitor, _mutexTimeout))
try
{ {
ftp.cd(remoteParent); try
/*
if (isBinary)
ftp.binary();
else
ftp.ascii();
*/
// for now only binary seems to work
ftp.binary();
InputStream is = ftp.get(remoteFile);
BufferedInputStream bis = new BufferedInputStream(is);
if (!localFile.exists())
{ {
File localParentFile = localFile.getParentFile(); FtpClient ftp = getFTPClient();
if (!localParentFile.exists()) ftp.cd(remoteParent);
/*
if (isBinary)
ftp.binary();
else
ftp.ascii();
*/
// for now only binary seems to work
ftp.binary();
InputStream is = ftp.get(remoteFile);
BufferedInputStream bis = new BufferedInputStream(is);
if (!localFile.exists())
{ {
localParentFile.mkdirs(); File localParentFile = localFile.getParentFile();
if (!localParentFile.exists())
{
localParentFile.mkdirs();
}
localFile.createNewFile();
} }
localFile.createNewFile(); OutputStream os = new FileOutputStream(localFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
byte[] buffer = new byte[1024];
int totalWrote = 0;
int readCount;
while( (readCount = bis.read(buffer)) > 0)
{
bos.write(buffer, 0, readCount);
totalWrote += readCount;
}
bos.close();
return true;
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
_mutex.release();
} }
OutputStream os = new FileOutputStream(localFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
byte[] buffer = new byte[1024];
int totalWrote = 0;
int readCount;
while( (readCount = bis.read(buffer)) > 0)
{
bos.write(buffer, 0, readCount);
totalWrote += readCount;
}
bos.close();
} }
catch (Exception e) return false;
{
e.printStackTrace();
}
return true;
} }
public IHostFile getUserHome() public IHostFile getUserHome()
@ -336,13 +355,19 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
*/ */
public boolean delete(IProgressMonitor monitor, String remoteParent, String fileName) { public boolean delete(IProgressMonitor monitor, String remoteParent, String fileName) {
boolean hasSucceeded = false; boolean hasSucceeded = false;
try { if (_mutex.waitForLock(monitor, _mutexTimeout)) {
getFTPClient().cd(remoteParent); try {
int returnedValue = getFTPClient().sendCommand("DELE " + fileName); getFTPClient().cd(remoteParent);
hasSucceeded = (returnedValue > 0); int returnedValue = getFTPClient().sendCommand("DELE " + fileName);
} catch (IOException e) { hasSucceeded = (returnedValue > 0);
// Changing folder raised an exception }
hasSucceeded = false; catch (IOException e) {
// Changing folder raised an exception
hasSucceeded = false;
}
finally {
_mutex.release();
}
} }
return hasSucceeded; return hasSucceeded;
} }
@ -352,10 +377,17 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
*/ */
public boolean rename(IProgressMonitor monitor, String remoteParent, String oldName, String newName) { public boolean rename(IProgressMonitor monitor, String remoteParent, String oldName, String newName) {
boolean hasSucceeded = false; boolean hasSucceeded = false;
int returnedValue = getFTPClient().sendCommand("RNFR " + remoteParent + getSeparator() + oldName); if (_mutex.waitForLock(monitor, _mutexTimeout)) {
if (returnedValue > 0) { try {
returnedValue = getFTPClient().sendCommand("RNTO " + remoteParent + getSeparator() + newName); int returnedValue = getFTPClient().sendCommand("RNFR " + remoteParent + getSeparator() + oldName);
hasSucceeded = (returnedValue > 0); if (returnedValue > 0) {
returnedValue = getFTPClient().sendCommand("RNTO " + remoteParent + getSeparator() + newName);
hasSucceeded = (returnedValue > 0);
}
}
finally {
_mutex.release();
}
} }
return hasSucceeded; return hasSucceeded;
} }
@ -365,10 +397,17 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
*/ */
public boolean rename(IProgressMonitor monitor, String remoteParent, String oldName, String newName, IHostFile oldFile) { public boolean rename(IProgressMonitor monitor, String remoteParent, String oldName, String newName, IHostFile oldFile) {
boolean hasSucceeded = false; boolean hasSucceeded = false;
int returnedValue = getFTPClient().sendCommand("RNFR " + remoteParent + getSeparator() + oldName); if (_mutex.waitForLock(monitor, _mutexTimeout)) {
if (returnedValue > 0) { try {
returnedValue = getFTPClient().sendCommand("RNTO " + remoteParent + getSeparator() + newName); int returnedValue = getFTPClient().sendCommand("RNFR " + remoteParent + getSeparator() + oldName);
hasSucceeded = (returnedValue > 0); if (returnedValue > 0) {
returnedValue = getFTPClient().sendCommand("RNTO " + remoteParent + getSeparator() + newName);
hasSucceeded = (returnedValue > 0);
}
}
finally {
_mutex.release();
}
} }
return hasSucceeded; return hasSucceeded;
} }
@ -378,10 +417,17 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
*/ */
public boolean move(IProgressMonitor monitor, String srcParent, String srcName, String tgtParent, String tgtName) { public boolean move(IProgressMonitor monitor, String srcParent, String srcName, String tgtParent, String tgtName) {
boolean hasSucceeded = false; boolean hasSucceeded = false;
int returnedValue = getFTPClient().sendCommand("RNFR " + srcParent + getSeparator() + srcName); if (_mutex.waitForLock(monitor, _mutexTimeout)) {
if (returnedValue > 0) { try {
returnedValue = getFTPClient().sendCommand("RNTO " + tgtParent + getSeparator() + tgtName); int returnedValue = getFTPClient().sendCommand("RNFR " + srcParent + getSeparator() + srcName);
hasSucceeded = (returnedValue > 0); if (returnedValue > 0) {
returnedValue = getFTPClient().sendCommand("RNTO " + tgtParent + getSeparator() + tgtName);
hasSucceeded = (returnedValue > 0);
}
}
finally {
_mutex.release();
}
} }
return hasSucceeded; return hasSucceeded;
} }
@ -391,16 +437,27 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
*/ */
public IHostFile createFolder(IProgressMonitor monitor, String remoteParent, String folderName) public IHostFile createFolder(IProgressMonitor monitor, String remoteParent, String folderName)
{ {
try if (_mutex.waitForLock(monitor, _mutexTimeout))
{ {
FTPClientService ftp = getFTPClient(); try
ftp.cd(remoteParent); {
ftp.sendCommand("MKD " + folderName); FTPClientService ftp = getFTPClient();
} ftp.cd(remoteParent);
catch (Exception e) ftp.sendCommand("MKD " + folderName);
{ }
e.printStackTrace(); catch (Exception e)
{
e.printStackTrace();
}
finally
{
_mutex.release();
}
} }
//TODO getFile() will acquire the lock again after having released it
//For optimization, Mutex should notice when the _same_ thread tries
//to acquire a lock that it already holds again. To do so, the current
//locking thread would need to be remembered.
return getFile(monitor, remoteParent, folderName); return getFile(monitor, remoteParent, folderName);
} }
@ -408,12 +465,18 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
* @see org.eclipse.rse.services.files.IFileService#createFile(org.eclipse.core.runtime.IProgressMonitor, java.lang.String, java.lang.String) * @see org.eclipse.rse.services.files.IFileService#createFile(org.eclipse.core.runtime.IProgressMonitor, java.lang.String, java.lang.String)
*/ */
public IHostFile createFile(IProgressMonitor monitor, String remoteParent, String fileName) { public IHostFile createFile(IProgressMonitor monitor, String remoteParent, String fileName) {
try { if (_mutex.waitForLock(monitor, _mutexTimeout)) {
File tempFile = File.createTempFile("ftp", "temp"); try {
tempFile.deleteOnExit(); File tempFile = File.createTempFile("ftp", "temp");
upload(monitor, tempFile, remoteParent, fileName, true, null, null); tempFile.deleteOnExit();
} catch (Exception e) { upload(monitor, tempFile, remoteParent, fileName, true, null, null);
e.printStackTrace(); }
catch (Exception e) {
e.printStackTrace();
}
finally {
_mutex.release();
}
} }
return getFile(monitor, remoteParent, fileName); return getFile(monitor, remoteParent, fileName);
} }