Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't make RemoteFileUtils.makeDirectories syncronized #3370

Closed
dongja3 opened this issue Aug 26, 2020 · 4 comments · Fixed by #3380
Closed

Don't make RemoteFileUtils.makeDirectories syncronized #3370

dongja3 opened this issue Aug 26, 2020 · 4 comments · Fixed by #3380

Comments

@dongja3
Copy link

dongja3 commented Aug 26, 2020

In what version(s) of Spring Integration are you seeing this issue?
5.3.1.RELEASE

Describe the bug
It caused by org.springframework.integration.file.remote.RemoteFileUtils#makeDirectories, which is synchronized static method, when there are lots of (S)ftp move operation concurrently and slow speed of network, all requests of AbstractRemoteFileOutboundGateway#mv are queued and observed as very slow speed.

https://stackoverflow.com/questions/62772002/outbound-gateway-executes-the-mv-command-very-slowly

Expected behavior
in api doc, RemoteFileUtils#makeDirectories is static not synchronized,
https://docs.spring.io/spring-integration/docs/5.3.1.RELEASE/api/
However, in source code is static and syncronized.

@dongja3 dongja3 added status: waiting-for-triage The issue need to be evaluated and its future decided type: bug labels Aug 26, 2020
@dongja3 dongja3 changed the title don't make RemoteFileUtils.makeDirectories static syncronized Don't make RemoteFileUtils.makeDirectories syncronized Aug 26, 2020
@garyrussell
Copy link
Contributor

It was synchronized to fix a race condition.

#2915

@artembilan
Copy link
Member

I think the request is valid. Even with that synchronized we definitely still may fail with race condition when our application is in cluster, so different nodes may try to create the same dirs at the same moment.

It is better to rework this logic to really catch an exception from the session.mkdir(path) when it says that Eine Datei kann nicht erstellt werden, wenn sie bereits vorhanden ist (A file cannot be created if it already exists). Probably as a second session.exists(path) check in the catch block...

WDYT?

@garyrussell
Copy link
Contributor

Agreed; yes.

@dongja3
Copy link
Author

dongja3 commented Aug 27, 2020

Hi, Aterm, Gary
thanks for your prompt feedback, and look forward to the new release.

@artembilan artembilan added this to the 5.4 M3 milestone Sep 10, 2020
@artembilan artembilan added backport 5.2.x in: ftp in: sftp and removed status: waiting-for-triage The issue need to be evaluated and its future decided labels Sep 10, 2020
artembilan added a commit to artembilan/spring-integration that referenced this issue Sep 10, 2020
Fixes spring-projects#3370

The `synchronized` on the `RemoteFileUtils.makeDirectories()` makes an application too
 slow, especially when we deal with different paths in different sessions

* Remove the `synchronized` from that method and rework `SftpSession.mkdir()`
to return `false` when "A file cannot be created if it already exists" exception
is thrown from the server.
Essentially make an `exists()` call to be sure that an exception is really related
to "file-already-exists" answer from the server

**Cherry-pick to 5.3.x, 5.2.x & 4.3.x**
garyrussell pushed a commit that referenced this issue Sep 10, 2020
* GH-3370: Remove synchronized from RemoteFileUtils

Fixes #3370

The `synchronized` on the `RemoteFileUtils.makeDirectories()` makes an application too
 slow, especially when we deal with different paths in different sessions

* Remove the `synchronized` from that method and rework `SftpSession.mkdir()`
to return `false` when "A file cannot be created if it already exists" exception
is thrown from the server.
Essentially make an `exists()` call to be sure that an exception is really related
to "file-already-exists" answer from the server

**Cherry-pick to 5.3.x, 5.2.x & 4.3.x**

* * Re-throw an exception in the `SftpSession.mkdir()`
when error code is not `4` or remote dir does not exist

* * Check `session.mkdir()` result in the
`RemoteFileUtils` to throw an `IOException` when `false`

* * Fix mock test to return `true` for `mkdir` instead of `null`
garyrussell pushed a commit that referenced this issue Sep 10, 2020
* GH-3370: Remove synchronized from RemoteFileUtils

Fixes #3370

The `synchronized` on the `RemoteFileUtils.makeDirectories()` makes an application too
 slow, especially when we deal with different paths in different sessions

* Remove the `synchronized` from that method and rework `SftpSession.mkdir()`
to return `false` when "A file cannot be created if it already exists" exception
is thrown from the server.
Essentially make an `exists()` call to be sure that an exception is really related
to "file-already-exists" answer from the server

**Cherry-pick to 5.3.x, 5.2.x & 4.3.x**

* * Re-throw an exception in the `SftpSession.mkdir()`
when error code is not `4` or remote dir does not exist

* * Check `session.mkdir()` result in the
`RemoteFileUtils` to throw an `IOException` when `false`

* * Fix mock test to return `true` for `mkdir` instead of `null`
garyrussell pushed a commit that referenced this issue Sep 10, 2020
* GH-3370: Remove synchronized from RemoteFileUtils

Fixes #3370

The `synchronized` on the `RemoteFileUtils.makeDirectories()` makes an application too
 slow, especially when we deal with different paths in different sessions

* Remove the `synchronized` from that method and rework `SftpSession.mkdir()`
to return `false` when "A file cannot be created if it already exists" exception
is thrown from the server.
Essentially make an `exists()` call to be sure that an exception is really related
to "file-already-exists" answer from the server

**Cherry-pick to 5.3.x, 5.2.x & 4.3.x**

* * Re-throw an exception in the `SftpSession.mkdir()`
when error code is not `4` or remote dir does not exist

* * Check `session.mkdir()` result in the
`RemoteFileUtils` to throw an `IOException` when `false`

* * Fix mock test to return `true` for `mkdir` instead of `null`
artembilan added a commit that referenced this issue Sep 10, 2020
* GH-3370: Remove synchronized from RemoteFileUtils

Fixes #3370

The `synchronized` on the `RemoteFileUtils.makeDirectories()` makes an application too
 slow, especially when we deal with different paths in different sessions

* Remove the `synchronized` from that method and rework `SftpSession.mkdir()`
to return `false` when "A file cannot be created if it already exists" exception
is thrown from the server.
Essentially make an `exists()` call to be sure that an exception is really related
to "file-already-exists" answer from the server

**Cherry-pick to 5.3.x, 5.2.x & 4.3.x**

* * Re-throw an exception in the `SftpSession.mkdir()`
when error code is not `4` or remote dir does not exist

* * Check `session.mkdir()` result in the
`RemoteFileUtils` to throw an `IOException` when `false`

* * Fix mock test to return `true` for `mkdir` instead of `null`
# Conflicts:
#	spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileUtils.java
#	spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java
#	spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java
#	spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants