在 Java 中如何以原子方式将一个目录替换为另一个目录?

发布于 2024-10-06 20:05:17 字数 212 浏览 0 评论 0原文

我有一个目录,其中包含为客户端提供的数据文件,例如 /srv/data。在进行一系列更新时,我正在处理 /srv/data_tmp,在操作结束时,我想用 data_tmp 自动替换 data。当目标是现有目录时,File.renameTo() 总是返回 false。我该怎么做?

I have a directory that contains data files served to clients, say, /srv/data. While making a series of updates, I am working on /srv/data_tmp, and at the end of the operation, I would like to atomically replace data with data_tmp. File.renameTo() always returns false for me when the destination is an existing directory. How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

十六岁半 2024-10-13 20:05:17

恐怕你不能。至少不是SO级别。因此,即使您在 java 应用程序的上下文中管理“原子性”,也无法保证其他“流氓”进程会干扰实际的文件系统级别。

如果我是你,我会阅读这篇文章 (很旧,但应该给你一些想法),然后看看你是否可以将建议的方法移植到 更现代的版本

哦,等等,已经有人这样做了

显然您也不是第一个在这里提问的人

祝你好运...

I am afraid you can't. Not at the SO level at least. So even if you manage "atomicity" in the context of your java application, you have no guarantee about some other "rogue" process interfering at the actual filesystem level.

If I were you, I'd read this article (quite old, but should give you some ideas) and then see if you can port the suggested approach to a more modern version .

Oh, wait, someone did this already!

And apparently your aren't the first one to ask here, either

Best of luck...

绅士风度i 2024-10-13 20:05:17

您可以将 /srv/data 目录替换为符号链接(或 连接在 Windows XP 中),并在适当时更改链接的目标。
不过,您无法使用 Java 6 API 来做到这一点 - 您必须依赖库或自己编写命令行命令。

注意:我不保证该操作的原子性。

You could replace the /srv/data directory with a symbolic link (or a junction in Windows XP), and change the link's target when appropriate.
You won't be able to do that with a Java 6 API though - You'd have to rely on a library or write the command line commands yourself.

NB: I don't guarantee anything about the atomicity of that operation.

何以畏孤独 2024-10-13 20:05:17

Linux rename 系统调用不允许这样做(rename 系统调用只能覆盖空目录),所以我怀疑在 Linux 上用 Java 可以做到这一点。

The Linux rename system call doesn't allow this (the rename system call can only overwrite an empty directory), so I doubt it's possible to do in Java on Linux.

空气里的味道 2024-10-13 20:05:17

使用“符号链接”和“重命名”的组合以及中间 tmp 目录完全可以实现此目标。以下示例位于 shell 中,但您可以轻松地将此处的功能转换为使用底层调用:

mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./

此处的示例取自:http://axiscorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/

这归结为(在伪代码):

mkdir('./tmp');
mkdir('./tmp/real_dir1');
mkdir('./tmp/real_dir2');
symlink('./tmp/real_dir1', './target_dir')
symlink('./tmp/real_dir2', './tmp/target_dir')
rename('./tmp/target_dir', './target_dir')

这里的最终重命名是原子的,因此该操作要么成功,要么完全失败,从使用该目录的任何进程来看,该操作都是原子的。

Achieving this goal is entirely possible using a combination of "symlink" and "rename", along with an intermediate tmp directory. The following example is in shell, but you could easily translate the functionality here to use the underlying calls:

mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./

Example here taken from: http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/

This boils down to (in pseudo-code):

mkdir('./tmp');
mkdir('./tmp/real_dir1');
mkdir('./tmp/real_dir2');
symlink('./tmp/real_dir1', './target_dir')
symlink('./tmp/real_dir2', './tmp/target_dir')
rename('./tmp/target_dir', './target_dir')

The final rename here is atomic, so the action will either succeed or fail entirely, from the point of any process using the directory, the action is atomic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文